├── android ├── app │ ├── .gitignore │ ├── libs │ │ └── put 'godot-lib.arr' here │ ├── src │ │ ├── main │ │ │ ├── java │ │ │ │ └── vn │ │ │ │ │ └── kyoz │ │ │ │ │ └── godot │ │ │ │ │ └── haptics │ │ │ │ │ ├── HapticsVibrationType.java │ │ │ │ │ ├── HapticsImpactType.java │ │ │ │ │ └── Haptics.java │ │ │ └── AndroidManifest.xml │ │ ├── test │ │ │ └── java │ │ │ │ └── vn │ │ │ │ └── kyoz │ │ │ │ └── godot │ │ │ │ └── haptics │ │ │ │ └── ExampleUnitTest.java │ │ └── androidTest │ │ │ └── java │ │ │ └── vn │ │ │ └── kyoz │ │ │ └── godot │ │ │ └── haptics │ │ │ └── ExampleInstrumentedTest.java │ ├── proguard-rules.pro │ └── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── Haptics.gdap ├── build.gradle ├── settings.gradle ├── .gitignore ├── gradle.properties ├── gradlew.bat └── gradlew ├── example ├── godot_3 │ ├── ios │ │ └── plugins │ │ │ └── dummy │ ├── icon.png │ ├── assets │ │ └── Roboto-Regular.ttf │ ├── .gitignore │ ├── default_env.tres │ ├── Main.gd │ ├── icon.png.import │ ├── autoload │ │ └── Haptics.gd │ ├── project.godot │ ├── Main.tscn │ └── export_presets.cfg └── godot_4 │ ├── ios │ └── plugins │ │ └── dummy │ ├── icon.png │ ├── assets │ ├── Roboto-Regular.ttf │ └── Roboto-Regular.ttf.import │ ├── .gitignore │ ├── default_env.tres │ ├── Main.gd │ ├── icon.png.import │ ├── autoload │ └── Haptics.gd │ ├── project.godot │ ├── Main.tscn │ └── export_presets.cfg ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── feature_request.yml │ └── bug_report.yml └── workflows │ └── release.yml ├── .gitignore ├── icon.png ├── .idea ├── .gitignore ├── modules.xml └── godot-haptics.iml ├── scripts ├── ios │ ├── timeout │ ├── generate_headers.sh │ ├── generate_static_library.sh │ ├── install.sh │ ├── build.sh │ └── release.sh ├── clear-caches.sh ├── utils.sh └── android │ ├── build.sh │ ├── install.sh │ └── release.sh ├── ios ├── plugin │ ├── haptics.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── xcuserdata │ │ │ └── kyoz.xcuserdatad │ │ │ │ ├── xcdebugger │ │ │ │ └── Breakpoints_v2.xcbkptlist │ │ │ │ └── xcschemes │ │ │ │ └── xcschememanagement.plist │ │ └── project.pbxproj │ ├── haptics.gdip │ └── haptics │ │ ├── haptics_module.h │ │ ├── haptics_module.mm │ │ ├── haptics.h │ │ └── haptics.mm ├── .gitignore └── SConstruct ├── autoload ├── godot_3 │ └── Haptics.gd └── godot_4 │ └── Haptics.gd ├── LICENSE ├── README.md └── DEVELOP.md /android/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /example/godot_3/ios/plugins/dummy: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /example/godot_4/ios/plugins/dummy: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /android/app/libs/put 'godot-lib.arr' here: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | patreon: Kyoz 2 | ko_fi: minkyoz -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .release 3 | .cache 4 | .sconsign.dblite -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyoz/godot-haptics/HEAD/icon.png -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /example/godot_3/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyoz/godot-haptics/HEAD/example/godot_3/icon.png -------------------------------------------------------------------------------- /example/godot_4/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyoz/godot-haptics/HEAD/example/godot_4/icon.png -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyoz/godot-haptics/HEAD/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/godot_3/assets/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyoz/godot-haptics/HEAD/example/godot_3/assets/Roboto-Regular.ttf -------------------------------------------------------------------------------- /example/godot_4/assets/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyoz/godot-haptics/HEAD/example/godot_4/assets/Roboto-Regular.ttf -------------------------------------------------------------------------------- /example/godot_3/.gitignore: -------------------------------------------------------------------------------- 1 | # Godot 4+ specific ignores 2 | .godot/ 3 | 4 | .import/ 5 | android 6 | 7 | # iOS exported project 8 | exported/ 9 | ios/plugins/* 10 | !ios/plugins/dummy -------------------------------------------------------------------------------- /example/godot_4/.gitignore: -------------------------------------------------------------------------------- 1 | # Godot 4+ specific ignores 2 | .godot/ 3 | 4 | .import/ 5 | android 6 | 7 | # iOS exported project 8 | exported/ 9 | ios/plugins/* 10 | !ios/plugins/dummy -------------------------------------------------------------------------------- /android/Haptics.gdap: -------------------------------------------------------------------------------- 1 | [config] 2 | 3 | name="Haptics" 4 | binary_type="local" 5 | binary="haptics-release.aar" 6 | 7 | [dependencies] 8 | 9 | local=[] 10 | remote=[] 11 | custom_maven_repos=[] -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | plugins { 3 | id 'com.android.library' version '8.0.2' apply false 4 | } -------------------------------------------------------------------------------- /scripts/ios/timeout: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ( 3 | sleep 60 4 | 5 | kill -s SIGTERM $$ && kill -0 $$ || exit 0 6 | sleep 1 7 | kill -s SIGKILL $$ 8 | ) 2> /dev/null & 9 | 10 | exec "$@" -------------------------------------------------------------------------------- /example/godot_3/default_env.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Environment" load_steps=2 format=2] 2 | 3 | [sub_resource type="ProceduralSky" id=1] 4 | 5 | [resource] 6 | background_mode = 2 7 | background_sky = SubResource( 1 ) 8 | -------------------------------------------------------------------------------- /example/godot_4/default_env.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Environment" load_steps=2 format=2] 2 | 3 | [sub_resource type="ProceduralSky" id=1] 4 | 5 | [resource] 6 | background_mode = 2 7 | background_sky = SubResource( 1 ) 8 | -------------------------------------------------------------------------------- /ios/plugin/haptics.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/plugin/haptics.xcodeproj/xcuserdata/kyoz.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /scripts/ios/generate_headers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd ./ios/godot 4 | 5 | if [[ "$1" == "3.x" ]]; 6 | then 7 | ./../../scripts/ios/timeout scons platform=iphone target=release_debug 8 | else 9 | ./../../scripts/ios/timeout scons platform=ios target=template_release 10 | fi -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Jul 05 13:57:01 ICT 2023 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /example/godot_3/Main.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | 4 | func _ready(): 5 | Haptics.init() 6 | 7 | 8 | func _on_LightBtn_pressed(): 9 | Haptics.light() 10 | 11 | 12 | func _on_MediumBtn_pressed(): 13 | Haptics.medium() 14 | 15 | 16 | func _on_HeavyBtn_pressed(): 17 | Haptics.heavy() 18 | -------------------------------------------------------------------------------- /example/godot_4/Main.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | 4 | func _ready(): 5 | Haptics.init() 6 | 7 | 8 | func _on_LightBtn_pressed(): 9 | Haptics.light() 10 | 11 | 12 | func _on_MediumBtn_pressed(): 13 | Haptics.medium() 14 | 15 | 16 | func _on_HeavyBtn_pressed(): 17 | Haptics.heavy() 18 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/plugin/haptics.gdip: -------------------------------------------------------------------------------- 1 | [config] 2 | name="Haptics" 3 | binary="haptics.a" 4 | 5 | initialization="register_haptics_types" 6 | deinitialization="unregister_haptics_types" 7 | 8 | [dependencies] 9 | linked=[] 10 | embedded=[] 11 | system=[] 12 | 13 | capabilities=[] 14 | 15 | files=[] 16 | 17 | [plist] 18 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | extracted_headers 4 | godot 5 | bin 6 | 7 | plugin/*/lib 8 | plugin/Pods/ 9 | 10 | *.a 11 | *.o 12 | *.d 13 | *.hmap 14 | *.yaml 15 | *.dia 16 | *.xcbuild 17 | *.db 18 | *.LinkFileList 19 | *BuildDescriptionCacheIndex* 20 | *.xcuserstate 21 | *.dblite 22 | *ios*.zip 23 | *.tar.xz 24 | -------------------------------------------------------------------------------- /ios/plugin/haptics.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/godot-haptics.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/plugin/haptics/haptics_module.h: -------------------------------------------------------------------------------- 1 | // 2 | // haptics_module.h 3 | // haptics 4 | // 5 | // Created by Kyoz on 07/07/2023. 6 | // 7 | 8 | #ifndef haptics_module_h 9 | #define haptics_module_h 10 | 11 | #import 12 | #import "./haptics.h" 13 | 14 | void register_haptics_types(); 15 | void unregister_haptics_types(); 16 | 17 | #endif /* haptics_module_h */ 18 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | gradlePluginPortal() 6 | } 7 | } 8 | dependencyResolutionManagement { 9 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | } 15 | rootProject.name = "Godot Native Haptics" 16 | include ':app' 17 | -------------------------------------------------------------------------------- /android/app/src/main/java/vn/kyoz/godot/haptics/HapticsVibrationType.java: -------------------------------------------------------------------------------- 1 | // Source: https://github.com/ionic-team/capacitor-plugins/blob/main/haptics/android/src/main/java/com/capacitorjs/plugins/haptics/arguments/HapticsVibrationType.java 2 | package vn.kyoz.godot.haptics; 3 | 4 | public interface HapticsVibrationType { 5 | long[] getTimings(); 6 | 7 | int[] getAmplitudes(); 8 | 9 | long[] getOldSDKPattern(); 10 | } 11 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | 17 | # Android 18 | *.aar 19 | *.idea 20 | *.gradle 21 | !build.gradle 22 | !settings.gradle 23 | build/ 24 | local.properties 25 | *.aar 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Suggest an idea or request a new feature 3 | body: 4 | 5 | - type: textarea 6 | attributes: 7 | label: What feature or improvement would you like to have? 8 | validations: 9 | required: true 10 | 11 | - type: textarea 12 | attributes: 13 | label: Additional context 14 | description: | 15 | Including screenshots or an example will help contributors implement it more faster. -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/plugin/haptics.xcodeproj/xcuserdata/kyoz.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | haptics.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /android/app/src/test/java/vn/kyoz/godot/haptics/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package vn.kyoz.godot.haptics; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /ios/plugin/haptics/haptics_module.mm: -------------------------------------------------------------------------------- 1 | // 2 | // haptics_module.m 3 | // haptics 4 | // 5 | // Created by Kyoz on 10/07/2023. 6 | // 7 | 8 | 9 | #ifdef VERSION_4_0 10 | #include "core/config/engine.h" 11 | #else 12 | #include "core/engine.h" 13 | #endif 14 | 15 | 16 | #include "haptics_module.h" 17 | 18 | Haptics * haptics; 19 | 20 | void register_haptics_types() { 21 | haptics = memnew(Haptics); 22 | Engine::get_singleton()->add_singleton(Engine::Singleton("Haptics", haptics)); 23 | }; 24 | 25 | void unregister_haptics_types() { 26 | if (haptics) { 27 | memdelete(haptics); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /scripts/clear-caches.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "This will remove all cache, build, release example template files." 4 | echo "Will save you lots of storage (>1GB to ~10MB)." 5 | echo "But next build time, it will be slower." 6 | read -p "Are you sure? (y/n)" -n 1 -r 7 | echo 8 | if [[ ! $REPLY =~ ^[Yy]$ ]] 9 | then 10 | exit 1 11 | fi 12 | 13 | echo ">> Removing all cache, build, release, example template files..." 14 | 15 | # Cache 16 | rm -rf .cache 17 | rm -rf .release 18 | 19 | # Android 20 | rm -rf ./android/app/libs/*.aar 21 | 22 | # iOS 23 | rm -rf ./ios/bin 24 | rm -rf ./ios/godot 25 | 26 | # Example 27 | rm -rf ./example/*/android 28 | rm -rf ./example/*/exported/ios/* -------------------------------------------------------------------------------- /ios/plugin/haptics/haptics.h: -------------------------------------------------------------------------------- 1 | // 2 | // haptics.h 3 | // haptics 4 | // 5 | // Created by Kyoz on 07/07/2023. 6 | // 7 | 8 | #ifndef HAPTICS_H 9 | #define HAPTICS_H 10 | 11 | #ifdef VERSION_4_0 12 | #include "core/object/object.h" 13 | #endif 14 | 15 | #ifdef VERSION_3_X 16 | #include "core/object.h" 17 | #endif 18 | 19 | class Haptics : public Object { 20 | 21 | GDCLASS(Haptics, Object); 22 | 23 | static Haptics *instance; 24 | 25 | public: 26 | void light(); 27 | void medium(); 28 | void heavy(); 29 | 30 | static Haptics *get_singleton(); 31 | 32 | Haptics(); 33 | ~Haptics(); 34 | 35 | protected: 36 | static void _bind_methods(); 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /autoload/godot_3/Haptics.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | signal on_error(error_message) 4 | 5 | var haptics = null 6 | 7 | 8 | # Change this to _ready() if you want automatically init 9 | func init(): 10 | if Engine.has_singleton("Haptics"): 11 | haptics = Engine.get_singleton("Haptics") 12 | 13 | 14 | func light(): 15 | if not haptics: 16 | not_found_plugin() 17 | return 18 | 19 | haptics.light() 20 | 21 | 22 | func medium(): 23 | if not haptics: 24 | not_found_plugin() 25 | return 26 | 27 | haptics.medium() 28 | 29 | 30 | func heavy(): 31 | if not haptics: 32 | not_found_plugin() 33 | return 34 | 35 | haptics.heavy() 36 | 37 | 38 | func not_found_plugin(): 39 | print('[Haptics] Not found plugin. Please ensure that you checked Haptics plugin in the export template') 40 | -------------------------------------------------------------------------------- /autoload/godot_4/Haptics.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | signal on_error(error_message) 4 | 5 | var haptics = null 6 | 7 | 8 | # Change this to _ready() if you want automatically init 9 | func init(): 10 | if Engine.has_singleton("Haptics"): 11 | haptics = Engine.get_singleton("Haptics") 12 | 13 | 14 | func light(): 15 | if not haptics: 16 | not_found_plugin() 17 | return 18 | 19 | haptics.light() 20 | 21 | 22 | func medium(): 23 | if not haptics: 24 | not_found_plugin() 25 | return 26 | 27 | haptics.medium() 28 | 29 | 30 | func heavy(): 31 | if not haptics: 32 | not_found_plugin() 33 | return 34 | 35 | haptics.heavy() 36 | 37 | 38 | func not_found_plugin(): 39 | print('[Haptics] Not found plugin. Please ensure that you checked Haptics plugin in the export template') 40 | -------------------------------------------------------------------------------- /scripts/utils.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | get_android_template_file_name() { 4 | VERSION=$1 5 | 6 | if [ "${VERSION:0:1}" != "4" ]; then 7 | echo "godot-lib.${VERSION}.stable.release.aar" 8 | else 9 | echo "godot-lib.${VERSION}.stable.template_release.aar" 10 | fi 11 | } 12 | 13 | get_ios_template_file_name() { 14 | echo extracted_headers_godot_$1.zip 15 | } 16 | 17 | get_major_version() { 18 | VERSION=$1 19 | 20 | if [[ $VERSION =~ ^3\..* ]]; then 21 | echo $VERSION | sed -E 's/^([0-9]+)\..*$/\1.x/g' 22 | else 23 | echo "4.0" 24 | fi 25 | } 26 | 27 | get_example_path() { 28 | VERSION=$1 29 | 30 | if [[ $VERSION =~ ^3\..* ]]; then 31 | echo ./example/godot_3 32 | else 33 | echo ./example/godot_4 34 | fi 35 | } -------------------------------------------------------------------------------- /android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile -------------------------------------------------------------------------------- /example/godot_3/icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://icon.png" 13 | dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=true 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /example/godot_4/assets/Roboto-Regular.ttf.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="font_data_dynamic" 4 | type="FontFile" 5 | uid="uid://bgp565jxggj6l" 6 | path="res://.godot/imported/Roboto-Regular.ttf-3c92ca3227521cd50f0dab9e26b7bee4.fontdata" 7 | 8 | [deps] 9 | 10 | source_file="res://assets/Roboto-Regular.ttf" 11 | dest_files=["res://.godot/imported/Roboto-Regular.ttf-3c92ca3227521cd50f0dab9e26b7bee4.fontdata"] 12 | 13 | [params] 14 | 15 | Rendering=null 16 | antialiasing=1 17 | generate_mipmaps=false 18 | multichannel_signed_distance_field=false 19 | msdf_pixel_range=8 20 | msdf_size=48 21 | allow_system_fallback=true 22 | force_autohinter=false 23 | hinting=1 24 | subpixel_positioning=1 25 | oversampling=0.0 26 | Fallbacks=null 27 | fallbacks=[] 28 | Compress=null 29 | compress=true 30 | preload=[] 31 | language_support={} 32 | script_support={} 33 | opentype_features={} 34 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.library' 3 | } 4 | 5 | android { 6 | namespace 'vn.kyoz.godot.haptics' 7 | compileSdk 33 8 | 9 | defaultConfig { 10 | minSdk 19 11 | targetSdk 33 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | } 17 | 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | compileOptions { 25 | sourceCompatibility JavaVersion.VERSION_1_8 26 | targetCompatibility JavaVersion.VERSION_1_8 27 | } 28 | } 29 | 30 | dependencies { 31 | compileOnly fileTree(dir: 'libs', include: ['godot-lib*.aar']) 32 | implementation 'androidx.appcompat:appcompat:1.6.1' 33 | } -------------------------------------------------------------------------------- /example/godot_4/icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://crf43pvh1g7jd" 6 | path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.png" 14 | dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /scripts/ios/generate_static_library.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | cd ios 5 | 6 | # Compile static libraries 7 | 8 | # ARM64 Device 9 | scons target=$2 arch=arm64 plugin=$1 version=$3 10 | # ARM7 Device 11 | scons target=$2 arch=armv7 plugin=$1 version=$3 12 | # x86_64 Simulator 13 | scons target=$2 arch=x86_64 simulator=yes plugin=$1 version=$3 14 | 15 | # Creating a fat libraries for device and simulator 16 | # lib.-..a 17 | 18 | if [[ "$3" == "3.x" ]]; 19 | then 20 | lipo -create "./bin/lib$1.x86_64-simulator.$2.a" \ 21 | "./bin/lib$1.armv7-iphone.$2.a" \ 22 | "./bin/lib$1.arm64-iphone.$2.a" \ 23 | -output "./bin/$1.$2.a" 24 | else 25 | lipo -create "./bin/lib$1.x86_64-simulator.$2.a" \ 26 | "./bin/lib$1.armv7-ios.$2.a" \ 27 | "./bin/lib$1.arm64-ios.$2.a" \ 28 | -output "./bin/$1.$2.a" 29 | fi 30 | 31 | cd .. -------------------------------------------------------------------------------- /android/app/src/androidTest/java/vn/kyoz/godot/haptics/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package vn.kyoz.godot.haptics; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.test.platform.app.InstrumentationRegistry; 6 | import androidx.test.ext.junit.runners.AndroidJUnit4; 7 | 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | /** 14 | * Instrumented test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class ExampleInstrumentedTest { 20 | @Test 21 | public void useAppContext() { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 24 | assertEquals("vn.kyoz.godot.haptics", appContext.getPackageName()); 25 | } 26 | } -------------------------------------------------------------------------------- /example/godot_3/autoload/Haptics.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | signal on_error(error_message) 4 | 5 | var haptics = null 6 | 7 | 8 | # Change this to _ready() if you want automatically init 9 | func init(): 10 | if Engine.has_singleton("Haptics"): 11 | haptics = Engine.get_singleton("Haptics") 12 | init_signals() 13 | 14 | 15 | func init_signals(): 16 | haptics.connect("error", self, "_on_error") 17 | 18 | 19 | func _on_error(error_message): 20 | emit_signal("on_error", error_message) 21 | 22 | 23 | func light(): 24 | if not haptics: 25 | not_found_plugin() 26 | return 27 | 28 | haptics.light() 29 | 30 | 31 | func medium(): 32 | if not haptics: 33 | not_found_plugin() 34 | return 35 | 36 | haptics.medium() 37 | 38 | 39 | func heavy(): 40 | if not haptics: 41 | not_found_plugin() 42 | return 43 | 44 | haptics.heavy() 45 | 46 | 47 | func not_found_plugin(): 48 | print('[Haptics] Not found plugin. Please ensure that you checked Haptics plugin in the export template') 49 | -------------------------------------------------------------------------------- /example/godot_4/autoload/Haptics.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | signal on_error(error_message) 4 | 5 | var haptics = null 6 | 7 | 8 | # Change this to _ready() if you want automatically init 9 | func init(): 10 | if Engine.has_singleton("Haptics"): 11 | haptics = Engine.get_singleton("Haptics") 12 | init_signals() 13 | 14 | 15 | func init_signals(): 16 | haptics.connect("error", self, "_on_error") 17 | 18 | 19 | func _on_error(error_message): 20 | emit_signal("on_error", error_message) 21 | 22 | 23 | func light(): 24 | if not haptics: 25 | not_found_plugin() 26 | return 27 | 28 | haptics.light() 29 | 30 | 31 | func medium(): 32 | if not haptics: 33 | not_found_plugin() 34 | return 35 | 36 | haptics.medium() 37 | 38 | 39 | func heavy(): 40 | if not haptics: 41 | not_found_plugin() 42 | return 43 | 44 | haptics.heavy() 45 | 46 | 47 | func not_found_plugin(): 48 | print('[Haptics] Not found plugin. Please ensure that you checked Haptics plugin in the export template') 49 | -------------------------------------------------------------------------------- /example/godot_3/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=4 10 | 11 | [application] 12 | 13 | config/name="Godot 3.x Example: Haptics" 14 | run/main_scene="res://Main.tscn" 15 | config/icon="res://icon.png" 16 | 17 | [autoload] 18 | 19 | Haptics="*res://autoload/Haptics.gd" 20 | 21 | [display] 22 | 23 | window/size/width=720 24 | window/size/height=1280 25 | window/handheld/orientation="portrait" 26 | window/stretch/mode="2d" 27 | window/stretch/aspect="expand" 28 | 29 | [gui] 30 | 31 | common/drop_mouse_on_gui_input_disabled=true 32 | 33 | [physics] 34 | 35 | common/enable_pause_aware_picking=true 36 | 37 | [rendering] 38 | 39 | quality/driver/driver_name="GLES2" 40 | vram_compression/import_etc=true 41 | vram_compression/import_etc2=false 42 | vram_compression/import_pvrtc=true 43 | environment/default_environment="res://default_env.tres" 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Kyoz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /scripts/ios/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ./build.env 4 | source ./scripts/utils.sh 5 | 6 | CACHE_DIR=${IOS_CACHE_DIR} 7 | SUPPORT_VERSIONS=(${IOS_TEMPLATES[@]}) 8 | VERSION=$([ ! -z "$1" ] && echo $1 || echo ${DEFAULT_IOS_TEMPLATE}) 9 | 10 | GODOT_SOURCE_URL="https://github.com/kyoz/godot-ios-extracted-headers/releases/download/stable" 11 | 12 | # Create .cache folder if not existed 13 | if [ ! -d "${CACHE_DIR}" ]; then 14 | mkdir -p "${CACHE_DIR}" 15 | fi 16 | 17 | # Check if template version is support or not 18 | if [[ ! " ${SUPPORT_VERSIONS[*]} " =~ " ${VERSION} " ]]; then 19 | echo "- Your template version is not supported yet :'(" 20 | exit 1 21 | fi 22 | 23 | # Install godot extracted headers, will bypass cached ones 24 | HEADER_FILE=$(get_ios_template_file_name $VERSION) 25 | 26 | # Check if version is cached 27 | if test -f "${CACHE_DIR}/${HEADER_FILE}"; then 28 | echo "- Downloaded godot extracted headers version ${VERSION} (cached)" 29 | else 30 | echo "- Downloading godot extracted headers version ${VERSION}..." 31 | wget -P "${CACHE_DIR}" "${GODOT_SOURCE_URL}/${HEADER_FILE}" 32 | fi 33 | 34 | -------------------------------------------------------------------------------- /example/godot_4/project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="Godot 4.x Example: Haptics" 14 | run/main_scene="res://Main.tscn" 15 | config/features=PackedStringArray("4.1") 16 | config/icon="res://icon.png" 17 | 18 | [autoload] 19 | 20 | Haptics="*res://autoload/Haptics.gd" 21 | 22 | [display] 23 | 24 | window/stretch/mode="2d" 25 | window/stretch/aspect="expand" 26 | window/handheld/orientation="portrait" 27 | window/size/width=720 28 | window/size/height=1280 29 | 30 | [gui] 31 | 32 | common/drop_mouse_on_gui_input_disabled=true 33 | 34 | [physics] 35 | 36 | common/enable_pause_aware_picking=true 37 | 38 | [rendering] 39 | 40 | quality/driver/driver_name="GLES2" 41 | vram_compression/import_etc=true 42 | vram_compression/import_etc2=false 43 | vram_compression/import_pvrtc=true 44 | environment/default_environment="res://default_env.tres" 45 | -------------------------------------------------------------------------------- /scripts/android/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | source ./build.env 5 | source ./scripts/utils.sh 6 | 7 | CACHE_DIR=${ANDROID_CACHE_DIR} 8 | BUILD_VERSION=$([ ! -z "$1" ] && echo $1 || echo ${DEFAULT_ANDROID_TEMPLATE}) 9 | AAR_OUTPUT_PATH=android/app/build/outputs/aar 10 | 11 | echo ">> Install Android template..." 12 | ./scripts/android/install.sh $BUILD_VERSION 13 | 14 | echo ">> Cleaning..." 15 | rm -rf $AAR_OUTPUT_PATH/* 16 | 17 | echo ">> Preparing build template..." 18 | # Remove other templates 19 | find "android/app/libs" -name "*.aar" -type f -delete 20 | # Copy matching godot aar template 21 | AAR_FILE=$(get_android_template_file_name $BUILD_VERSION) 22 | cp ${CACHE_DIR}/${AAR_FILE} android/app/libs/${AAR_FILE} 23 | 24 | echo ">> Building lib..." 25 | cd android 26 | ./gradlew assembleRelease 27 | cd .. 28 | 29 | # Copy to example if possible (for faster development) 30 | EXAMPLE_PATH=$(get_example_path $BUILD_VERSION)/android/plugins 31 | 32 | if [ -d $EXAMPLE_PATH ] 33 | then 34 | echo ">> Copy plugin to example" 35 | 36 | cp $AAR_OUTPUT_PATH/app-release.aar $EXAMPLE_PATH/${PLUGIN_NAME}-release.aar 37 | cp android/${GDAP_FILE} $EXAMPLE_PATH/ 38 | fi -------------------------------------------------------------------------------- /scripts/android/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | source ./build.env 4 | source ./scripts/utils.sh 5 | 6 | CACHE_DIR=${ANDROID_CACHE_DIR} 7 | SUPPORT_VERSIONS=(${ANDROID_TEMPLATES[@]}) 8 | VERSION=$([ ! -z "$1" ] && echo $1 || echo ${DEFAULT_ANDROID_TEMPLATE}) 9 | 10 | GODOT_AAR_URL="https://github.com/kyoz/godot-android-release-libs/releases/download/v1.0.0" 11 | 12 | # Create .cache folder if not existed 13 | if [ ! -d "${CACHE_DIR}" ]; then 14 | mkdir -p "${CACHE_DIR}" 15 | fi 16 | 17 | # Check if template version is support or not 18 | if [[ ! " ${SUPPORT_VERSIONS[*]} " =~ " ${VERSION} " ]]; then 19 | echo "- Your template version is not supported yet :'(" 20 | exit 1 21 | fi 22 | 23 | # Install template, will bypass cached templates 24 | AAR_FILE=$(get_android_template_file_name $VERSION) 25 | 26 | # Check if version is cached 27 | if test -f "${CACHE_DIR}/${AAR_FILE}"; then 28 | echo "- Downloaded android template version ${VERSION} (cached)" 29 | else 30 | echo "- Downloading android template version ${VERSION}..." 31 | #wget -P "${CACHE_DIR}" "${GODOT_AAR_URL}/${VERSION}/${AAR_FILE}" 32 | wget -P "${CACHE_DIR}" "${GODOT_AAR_URL}/${AAR_FILE}" 33 | fi 34 | 35 | 36 | -------------------------------------------------------------------------------- /example/godot_4/Main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://dgd267qp14jml"] 2 | 3 | [ext_resource type="Script" path="res://Main.gd" id="2"] 4 | 5 | [node name="Main" type="Node"] 6 | script = ExtResource("2") 7 | 8 | [node name="CanvasLayer" type="CanvasLayer" parent="."] 9 | 10 | [node name="Center" type="CenterContainer" parent="CanvasLayer"] 11 | anchors_preset = 15 12 | anchor_right = 1.0 13 | anchor_bottom = 1.0 14 | 15 | [node name="VBox" type="VBoxContainer" parent="CanvasLayer/Center"] 16 | layout_mode = 2 17 | 18 | [node name="LightBtn" type="Button" parent="CanvasLayer/Center/VBox"] 19 | layout_mode = 2 20 | text = "Light" 21 | 22 | [node name="MediumBtn" type="Button" parent="CanvasLayer/Center/VBox"] 23 | layout_mode = 2 24 | text = "Medium" 25 | 26 | [node name="HeavyBtn" type="Button" parent="CanvasLayer/Center/VBox"] 27 | layout_mode = 2 28 | text = "Heavy" 29 | 30 | [connection signal="pressed" from="CanvasLayer/Center/VBox/LightBtn" to="." method="_on_LightBtn_pressed"] 31 | [connection signal="pressed" from="CanvasLayer/Center/VBox/MediumBtn" to="." method="_on_MediumBtn_pressed"] 32 | [connection signal="pressed" from="CanvasLayer/Center/VBox/HeavyBtn" to="." method="_on_HeavyBtn_pressed"] 33 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android opehaptics system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Enables namespacing of each library's R class so that its R class includes only the 19 | # resources declared in the library itself and none from the library's dependencies, 20 | # thereby reducing the size of the R class for that library 21 | android.nonTransitiveRClass=true -------------------------------------------------------------------------------- /android/app/src/main/java/vn/kyoz/godot/haptics/HapticsImpactType.java: -------------------------------------------------------------------------------- 1 | // Source: https://github.com/ionic-team/capacitor-plugins/blob/main/haptics/android/src/main/java/com/capacitorjs/plugins/haptics/arguments/HapticsImpactType.java 2 | package vn.kyoz.godot.haptics; 3 | 4 | 5 | public enum HapticsImpactType implements HapticsVibrationType { 6 | LIGHT("LIGHT", new long[] { 0, 50 }, new int[] { 0, 110 }, new long[] { 0, 20 }), 7 | MEDIUM("MEDIUM", new long[] { 0, 43 }, new int[] { 0, 180 }, new long[] { 0, 43 }), 8 | HEAVY("HEAVY", new long[] { 0, 60 }, new int[] { 0, 255 }, new long[] { 0, 61 }); 9 | 10 | private final String type; 11 | private final long[] timings; 12 | private final int[] amplitudes; 13 | private final long[] oldSDKPattern; 14 | 15 | HapticsImpactType(String type, long[] timings, int[] amplitudes, long[] oldSDKPattern) { 16 | this.type = type; 17 | this.timings = timings; 18 | this.amplitudes = amplitudes; 19 | this.oldSDKPattern = oldSDKPattern; 20 | } 21 | 22 | @Override 23 | public long[] getTimings() { 24 | return timings; 25 | } 26 | 27 | @Override 28 | public int[] getAmplitudes() { 29 | return amplitudes; 30 | } 31 | 32 | @Override 33 | public long[] getOldSDKPattern() { 34 | return oldSDKPattern; 35 | } 36 | } -------------------------------------------------------------------------------- /scripts/android/release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | source ./build.env 5 | source ./scripts/utils.sh 6 | 7 | CACHE_DIR=${ANDROID_CACHE_DIR} 8 | BUILD_VERSIONS=($([ ! -z "$1" ] && echo $1 || echo ${ANDROID_TEMPLATES[@]})) 9 | AAR_OUTPUT_PATH=android/app/build/outputs/aar 10 | RELEASE_FOLDER=.release/android 11 | 12 | echo ">> Init release folder..." 13 | mkdir -p $RELEASE_FOLDER 14 | 15 | # Build template for all versions (or provided version) 16 | for version in "${BUILD_VERSIONS[@]}"; do 17 | echo ">> Building android template version: $version" 18 | 19 | echo "- Cleaning..." 20 | rm -rf $AAR_OUTPUT_PATH/* 21 | 22 | echo "- Install Android template..." 23 | ./scripts/android/install.sh $version 24 | 25 | echo "- Preparing build template..." 26 | # Remove other templates 27 | find "android/app/libs" -name "*.aar" -type f -delete 28 | # Copy matching godot aar template 29 | AAR_FILE=$(get_android_template_file_name $version) 30 | cp ${CACHE_DIR}/${AAR_FILE} android/app/libs/${AAR_FILE} 31 | 32 | echo "- Building lib..." 33 | cd android 34 | ./gradlew assembleRelease 35 | cd .. 36 | 37 | echo ">> Release to zip file..." 38 | mv $AAR_OUTPUT_PATH/app-release.aar $AAR_OUTPUT_PATH/${PLUGIN_NAME}-release.aar 39 | zip -j $RELEASE_FOLDER/android-template-${version}.zip \ 40 | $AAR_OUTPUT_PATH/${PLUGIN_NAME}-release.aar \ 41 | android/${GDAP_FILE} 42 | done 43 | 44 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: Report a bug of the plugin 3 | labels: bug 4 | body: 5 | 6 | - type: input 7 | attributes: 8 | label: Godot version 9 | placeholder: '3.5' 10 | description: Specify the Godot version you used to build your app/game 11 | validations: 12 | required: true 13 | 14 | - type: input 15 | attributes: 16 | label: Plugin version 17 | placeholder: 'v1.0.0' 18 | description: | 19 | The plugin version you are using 20 | validations: 21 | required: true 22 | 23 | - type: input 24 | attributes: 25 | label: Phone information 26 | placeholder: 'Google Pixel 7 - Android 12' 27 | description: | 28 | Your phone information (Modal, OS version...) 29 | validations: 30 | required: true 31 | 32 | - type: textarea 33 | attributes: 34 | label: Issue description 35 | description: | 36 | Describe your issue briefly. What doesn't work, and how do you expect it to work instead? 37 | validations: 38 | required: true 39 | 40 | - type: textarea 41 | attributes: 42 | label: Steps to reproduce 43 | placeholder: | 44 | 1. Go to '...' 45 | 2. Click on '...' 46 | description: | 47 | List of steps or sample code that reproduces the issue. 48 | validations: 49 | required: true 50 | 51 | - type: textarea 52 | attributes: 53 | label: Additional context 54 | description: | 55 | Including screenshots or a minimal reproduction project can greatly speed up your issue's resolution. -------------------------------------------------------------------------------- /scripts/ios/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | source ./build.env 5 | source ./scripts/utils.sh 6 | 7 | PLUGIN=${PLUGIN_NAME} 8 | CACHE_DIR=${IOS_CACHE_DIR} 9 | BUILD_VERSION=$([ ! -z "$1" ] && echo $1 || echo ${DEFAULT_IOS_TEMPLATE}) 10 | BUILDED_FOLDER=ios/bin/release 11 | 12 | echo ">> Install iOS template..." 13 | ./scripts/ios/install.sh $BUILD_VERSION 14 | 15 | echo ">> Cleaning and preparing folders..." 16 | rm -rf ios/bin 17 | mkdir -p ios/bin 18 | rm -rf ios/godot 19 | mkdir -p ios/godot 20 | 21 | echo ">> Preparing extracted header template..." 22 | HEADER_FILE=$(get_ios_template_file_name $BUILD_VERSION) 23 | unzip ${CACHE_DIR}/${HEADER_FILE} -d ./ios/ 24 | 25 | echo ">> Building..." 26 | MAJOR_VERSION=$(get_major_version $BUILD_VERSION) 27 | 28 | # Compile Plugin 29 | ./scripts/ios/generate_static_library.sh $PLUGIN release $MAJOR_VERSION 30 | ./scripts/ios/generate_static_library.sh $PLUGIN release_debug $MAJOR_VERSION 31 | mv ./ios/bin/${PLUGIN}.release_debug.a ./ios/bin/${PLUGIN}.debug.a 32 | 33 | # Move to release folder 34 | rm -rf $BUILDED_FOLDER 35 | mkdir $BUILDED_FOLDER 36 | rm -rf $BUILDED_FOLDER/${PLUGIN} 37 | mkdir -p $BUILDED_FOLDER/${PLUGIN} 38 | 39 | # Move Plugin 40 | mv ./ios/bin/${PLUGIN}.{release,debug}.a $BUILDED_FOLDER/${PLUGIN} 41 | cp ./ios/plugin/${PLUGIN}.gdip $BUILDED_FOLDER/${PLUGIN} 42 | 43 | # Copy to example if possible (for faster development) 44 | 45 | EXAMPLE_PATH=$(get_example_path $BUILD_VERSION)/ios/plugins 46 | if [ -d $EXAMPLE_PATH ] 47 | then 48 | echo ">> Copy plugin to example" 49 | rm -rf ${EXAMPLE_PATH}/${PLUGIN} 50 | cp -r $BUILDED_FOLDER/${PLUGIN} ${EXAMPLE_PATH}/${PLUGIN} 51 | fi -------------------------------------------------------------------------------- /ios/plugin/haptics/haptics.mm: -------------------------------------------------------------------------------- 1 | // 2 | // haptics.m 3 | // haptics 4 | // 5 | // Created by Kyoz on 07/07/2023. 6 | // 7 | 8 | #import 9 | #import 10 | #import 11 | 12 | #ifdef VERSION_4_0 13 | #include "core/object/class_db.h" 14 | #else 15 | #include "core/class_db.h" 16 | #endif 17 | 18 | #include "haptics.h" 19 | 20 | Haptics *Haptics::instance = NULL; 21 | 22 | Haptics::Haptics() { 23 | instance = this; 24 | NSLog(@"initialize haptics"); 25 | } 26 | 27 | Haptics::~Haptics() { 28 | if (instance == this) { 29 | instance = NULL; 30 | } 31 | NSLog(@"deinitialize haptics"); 32 | } 33 | 34 | Haptics *Haptics::get_singleton() { 35 | return instance; 36 | }; 37 | 38 | 39 | void Haptics::_bind_methods() { 40 | ClassDB::bind_method("light", &Haptics::light); 41 | ClassDB::bind_method("medium", &Haptics::medium); 42 | ClassDB::bind_method("heavy", &Haptics::heavy); 43 | } 44 | 45 | void Haptics::light() { 46 | UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight]; 47 | [generator prepare]; 48 | [generator impactOccurred]; 49 | } 50 | 51 | void Haptics::medium() { 52 | UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium]; 53 | [generator prepare]; 54 | [generator impactOccurred]; 55 | } 56 | 57 | void Haptics::heavy() { 58 | UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleHeavy]; 59 | [generator prepare]; 60 | [generator impactOccurred]; 61 | } 62 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release Plugin 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | build-android: 10 | name: Building for Android 11 | runs-on: "ubuntu-latest" 12 | 13 | steps: 14 | - uses: actions/checkout@v3 15 | 16 | - name: Setup Java 17 | uses: actions/setup-java@v3 18 | with: 19 | distribution: 'temurin' 20 | java-version: '17' 21 | cache: 'gradle' 22 | 23 | - name: Compile android plugins 24 | run: | 25 | ./scripts/android/release.sh 26 | ls -l .release/android 27 | 28 | - uses: actions/upload-artifact@v4 29 | with: 30 | name: android-plugins 31 | path: .release/android/*.zip 32 | retention-days: 4 33 | if-no-files-found: error 34 | 35 | build-ios: 36 | name: Building for iOS 37 | runs-on: "macos-latest" 38 | 39 | steps: 40 | - uses: actions/checkout@v3 41 | 42 | - name: Set up Python 3.x 43 | uses: actions/setup-python@v2 44 | with: 45 | python-version: '3.x' 46 | architecture: 'x64' 47 | 48 | - name: Configuring Python 49 | run: | 50 | python -c "import sys; print(sys.version)" 51 | python -m pip install scons 52 | python --version 53 | scons --version 54 | 55 | - name: Compile ios plugins 56 | run: | 57 | ./scripts/ios/release.sh 58 | ls -l .release/ios 59 | 60 | - uses: actions/upload-artifact@v4 61 | with: 62 | name: ios-plugins 63 | path: .release/ios/*.zip 64 | retention-days: 4 65 | if-no-files-found: error 66 | 67 | -------------------------------------------------------------------------------- /example/godot_3/Main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://assets/Roboto-Regular.ttf" type="DynamicFontData" id=1] 4 | [ext_resource path="res://Main.gd" type="Script" id=2] 5 | 6 | [sub_resource type="DynamicFont" id=1] 7 | size = 26 8 | font_data = ExtResource( 1 ) 9 | 10 | [node name="Main" type="Node"] 11 | script = ExtResource( 2 ) 12 | 13 | [node name="CanvasLayer" type="CanvasLayer" parent="."] 14 | 15 | [node name="Center" type="CenterContainer" parent="CanvasLayer"] 16 | anchor_right = 1.0 17 | anchor_bottom = 1.0 18 | 19 | [node name="VBox" type="VBoxContainer" parent="CanvasLayer/Center"] 20 | margin_left = 260.0 21 | margin_top = 466.0 22 | margin_right = 460.0 23 | margin_bottom = 814.0 24 | custom_constants/separation = 48 25 | 26 | [node name="LightBtn" type="Button" parent="CanvasLayer/Center/VBox"] 27 | margin_right = 200.0 28 | margin_bottom = 84.0 29 | rect_min_size = Vector2( 200, 84 ) 30 | custom_fonts/font = SubResource( 1 ) 31 | text = "Light" 32 | 33 | [node name="MediumBtn" type="Button" parent="CanvasLayer/Center/VBox"] 34 | margin_top = 132.0 35 | margin_right = 200.0 36 | margin_bottom = 216.0 37 | rect_min_size = Vector2( 0, 84 ) 38 | custom_fonts/font = SubResource( 1 ) 39 | text = "Medium" 40 | 41 | [node name="HeavyBtn" type="Button" parent="CanvasLayer/Center/VBox"] 42 | margin_top = 264.0 43 | margin_right = 200.0 44 | margin_bottom = 348.0 45 | rect_min_size = Vector2( 0, 84 ) 46 | custom_fonts/font = SubResource( 1 ) 47 | text = "Heavy" 48 | 49 | [connection signal="pressed" from="CanvasLayer/Center/VBox/LightBtn" to="." method="_on_LightBtn_pressed"] 50 | [connection signal="pressed" from="CanvasLayer/Center/VBox/MediumBtn" to="." method="_on_MediumBtn_pressed"] 51 | [connection signal="pressed" from="CanvasLayer/Center/VBox/HeavyBtn" to="." method="_on_HeavyBtn_pressed"] 52 | -------------------------------------------------------------------------------- /scripts/ios/release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | source ./build.env 5 | source ./scripts/utils.sh 6 | 7 | PLUGIN=${PLUGIN_NAME} 8 | CACHE_DIR=${IOS_CACHE_DIR} 9 | BUILD_VERSIONS=($([ ! -z "$1" ] && echo $1 || echo ${IOS_TEMPLATES[@]})) 10 | BUILDED_FOLDER=ios/bin/release 11 | RELEASE_FOLDER=.release/ios 12 | 13 | echo ">> Init release folder..." 14 | mkdir -p $RELEASE_FOLDER 15 | 16 | # Build template for all versions (or provided version) 17 | for version in "${BUILD_VERSIONS[@]}"; do 18 | echo ">> Building ios template version: $version" 19 | 20 | echo ">> Install iOS template..." 21 | ./scripts/ios/install.sh $version 22 | 23 | echo ">> Cleaning and preparing folders..." 24 | rm -rf ios/bin 25 | mkdir -p ios/bin 26 | rm -rf ios/godot 27 | mkdir -p ios/godot 28 | 29 | echo ">> Preparing extracted header template..." 30 | HEADER_FILE=$(get_ios_template_file_name $version) 31 | unzip ${CACHE_DIR}/${HEADER_FILE} -d ./ios/ 32 | 33 | echo ">> Building..." 34 | MAJOR_VERSION=$(get_major_version $version) 35 | 36 | # Compile Plugin 37 | ./scripts/ios/generate_static_library.sh $PLUGIN release $MAJOR_VERSION 38 | ./scripts/ios/generate_static_library.sh $PLUGIN release_debug $MAJOR_VERSION 39 | mv ./ios/bin/${PLUGIN}.release_debug.a ./ios/bin/${PLUGIN}.debug.a 40 | 41 | # Move to release folder 42 | rm -rf $BUILDED_FOLDER 43 | mkdir $BUILDED_FOLDER 44 | rm -rf $BUILDED_FOLDER/${PLUGIN} 45 | mkdir -p $BUILDED_FOLDER/${PLUGIN} 46 | 47 | # Move Plugin 48 | mv ./ios/bin/${PLUGIN}.{release,debug}.a $BUILDED_FOLDER/${PLUGIN} 49 | cp ./ios/plugin/${PLUGIN}.gdip $BUILDED_FOLDER/${PLUGIN} 50 | 51 | # Pack the plugin to zip file 52 | cd $BUILDED_FOLDER 53 | zip -r $PLUGIN.zip haptics/ 54 | cd ../../.. 55 | 56 | mv $BUILDED_FOLDER/$PLUGIN.zip $RELEASE_FOLDER/ios-template-${version}.zip 57 | done 58 | 59 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /android/app/src/main/java/vn/kyoz/godot/haptics/Haptics.java: -------------------------------------------------------------------------------- 1 | package vn.kyoz.godot.haptics; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.os.Vibrator; 6 | import android.os.VibratorManager; 7 | import android.os.VibrationEffect; 8 | import android.os.Build; 9 | import android.util.Log; 10 | 11 | import androidx.annotation.NonNull; 12 | import androidx.collection.ArraySet; 13 | 14 | import org.godotengine.godot.Godot; 15 | import org.godotengine.godot.plugin.GodotPlugin; 16 | import org.godotengine.godot.plugin.SignalInfo; 17 | import org.godotengine.godot.plugin.UsedByGodot; 18 | 19 | import java.util.Set; 20 | 21 | public class Haptics extends GodotPlugin { 22 | private static final String TAG = "GodotHaptics"; 23 | private Activity activity; 24 | private Context context; 25 | private final Vibrator vibrator; 26 | 27 | 28 | public Haptics(Godot godot) { 29 | super(godot); 30 | activity = getActivity(); 31 | context = activity.getApplicationContext(); 32 | 33 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { 34 | VibratorManager vibratorManager = (VibratorManager) context.getSystemService(Context.VIBRATOR_MANAGER_SERVICE); 35 | this.vibrator = vibratorManager.getDefaultVibrator(); 36 | } else { 37 | this.vibrator = getDeprecatedVibrator(context); 38 | } 39 | } 40 | 41 | @NonNull 42 | @Override 43 | public String getPluginName() { 44 | return getClass().getSimpleName(); 45 | } 46 | 47 | 48 | @SuppressWarnings("deprecation") 49 | private Vibrator getDeprecatedVibrator(Context context) { 50 | return (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); 51 | } 52 | 53 | @SuppressWarnings({ "deprecation" }) 54 | private void vibratePre26(int duration) { 55 | vibrator.vibrate(duration); 56 | } 57 | 58 | @SuppressWarnings({ "deprecation" }) 59 | private void vibratePre26(long[] pattern, int repeat) { 60 | vibrator.vibrate(pattern, repeat); 61 | } 62 | 63 | @UsedByGodot 64 | public void light() { 65 | Log.d(TAG, "called light()"); 66 | HapticsImpactType type = HapticsImpactType.LIGHT; 67 | 68 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 69 | vibrator.vibrate(VibrationEffect.createWaveform(type.getTimings(), type.getAmplitudes(), -1)); 70 | } else { 71 | vibratePre26(type.getOldSDKPattern(), -1); 72 | } 73 | } 74 | 75 | @UsedByGodot 76 | public void medium() { 77 | Log.d(TAG, "called medium()"); 78 | HapticsImpactType type = HapticsImpactType.MEDIUM; 79 | 80 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 81 | vibrator.vibrate(VibrationEffect.createWaveform(type.getTimings(), type.getAmplitudes(), -1)); 82 | } else { 83 | vibratePre26(type.getOldSDKPattern(), -1); 84 | } 85 | } 86 | 87 | @UsedByGodot 88 | public void heavy() { 89 | Log.d(TAG, "called heavy()"); 90 | HapticsImpactType type = HapticsImpactType.HEAVY; 91 | 92 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 93 | vibrator.vibrate(VibrationEffect.createWaveform(type.getTimings(), type.getAmplitudes(), -1)); 94 | } else { 95 | vibratePre26(type.getOldSDKPattern(), -1); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 |
3 | Godot Native Haptics 4 |
5 | Godot Native Haptics 6 |
7 |

8 | 9 |

Godot plugin to use Haptics on Android/iOS. Support Godot 3 & 4.

10 | 11 |

12 | 13 | 14 | 15 |   16 | 17 | 18 | 19 |   20 | 21 | 22 | 23 |   24 | 25 |   26 | 27 |

28 | 29 |

30 | About • 31 | Installation • 32 | Usage • 33 | API • 34 | Contribute • 35 | Downloads 36 |

37 | 38 | # About 39 | 40 | This plugin help to use haptics on mobile app (Android/iOS). Because the default vibration options of Godot is a bit to strong on some old Android/iOS device since vibration duration does not work on them. 41 | 42 | *Notes:* On iPhone, haptics only available on newer modals. 43 | 44 | Was build using automation scripts combine with CI/CD to help faster the release progress and well as release hotfix which save some of our times. 45 | 46 | Support Godot 3 & 4. 47 | 48 | # Installation 49 | 50 | ## Android 51 | 52 | Download the [android plugin](https://github.com/kyoz/godot-haptics/releases) (match your Godot version), extract them to `your_project/android/plugins` 53 | 54 | Enable `Haptics` plugin in your android export preset 55 | 56 | Enable `Vibrate` permission. 57 | 58 | *Note*: You must [use gradle build](https://docs.godotengine.org/en/stable/tutorials/export/android_gradle_build.html) for Android to use plugins. 59 | 60 | ## iOS 61 | 62 | Download the [ios plugin](https://github.com/kyoz/godot-haptics/releases) (match your Godot version), extract them to `ios/plugins` 63 | 64 | Enable `Haptics` plugin in your ios export preset 65 | 66 | # Usage 67 | 68 | You will need to add an `autoload` script to use this plugin more easily. 69 | 70 | Download [autoload file](./autoload) to your game (Choose correct Godot version). Add it to your project `autoload` list. 71 | 72 | Then you can easily use it anywhere with: 73 | 74 | ```gdscript 75 | Haptics.light() 76 | Haptics.medium() 77 | Haptics.heavy() 78 | 79 | Why have to call `init()`. Well, if you don't want to call init, you can change `init()` to `_ready()` on the `autoload` file. But for my experience when using a lots of plugin, init all plugins on `_ready()` is not a good idea. So i let you choose whenever you init the plugin. When showing a loading scene...etc... 80 | 81 | For more detail, see [examples](./example/) 82 | 83 | # API 84 | 85 | ## Methods 86 | 87 | ```gdscript 88 | void light() # A collision between small, light user interface elements 89 | void medium() # A collision between moderately sized user interface elements 90 | void heavy() # A collision between large, heavy user interface elements 91 | ``` 92 | 93 | # Contribute 94 | 95 | I want to help contribute to Godot community so i create these plugins. I've prepared almost everything to help the development and release progress faster and easier. 96 | 97 | Only one command and you'll build, release this plugin. Read [DEVELOP.md](./DEVELOP.md) for more information. 98 | 99 | If you found bug of the plugin, please open issues. 100 | 101 | If you have time to fix bugs or improve the plugins. Please open PR, it's always welcome. 102 | 103 | # License 104 | 105 | MIT © [Kyoz](mailto:banminkyoz@gmail.com) 106 | -------------------------------------------------------------------------------- /DEVELOP.md: -------------------------------------------------------------------------------- 1 | # Develop 2 | 3 | This is the full guide of how to start develop with this plugin. 4 | 5 | Just install [requirements](#requirements) tools and make sure it work. The rest is pretty simple cause i have writed automation script to build and release. Yay. 6 | 7 | ## Table of Contents 8 | - [Requirements](#requirements) 9 | - [Project Structure](#project-structure) 10 | - [Workflow](#workflow) 11 | - [Scripts](#scripts) 12 | - [Android](#android-scripts) 13 | - [iOS](#ios-scripts) 14 | 15 | ## Requirements 16 | 17 | > Android Plugin 18 | 19 | - Android Studio (prefer latest) & related sdk ([Download](https://developer.android.com)) 20 | - Java 17 21 | 22 | > iOS Plugin 23 | 24 | - XCode (prefer latest) 25 | - Python 3.x - ([Install](https://docs.python-guide.org/starting/install3/osx/)) 26 | - Scon ([Install](https://scons.org/doc/production/HTML/scons-user/ch01s02.html)) 27 | 28 | 29 | ## Project Structure 30 | 31 | ``` 32 | . 33 | └── root/ 34 | ├── android/ - Android plugin 35 | ├── ios/ - iOS plugin 36 | ├── autoload/ - Autoload file to load Singleton plugin 37 | ├── scripts/ - Scripts to install, build, release for Android/iOS 38 | ├── example/ - Example of how to use the plugin 39 | ├── .cache/ - Cache folder to download building templates, headers 40 | ├── .release/ - When release a plugin, it will be here 41 | └── build.env - Plugin build enviroment 42 | ``` 43 | 44 | ## Workflow 45 | 46 | ### Android 47 | 48 | Make sure you have opened the example (Godot 3 or 4 base on your prefer). Install Android Custom Template (So there will be `android/plugins` folder) 49 | 50 | Coding android plugin in `./android` folder 51 | 52 | Then run: 53 | 54 | ```sh 55 | ./scripts/android/build 56 | ``` 57 | 58 | The plugin will build and also copy to the example, and you are ready to test it :) 59 | 60 | (Remember the check if the plugin is checked in exported preset) 61 | 62 | ### iOS 63 | 64 | Coding iOS plugin in `./ios` folder 65 | 66 | Then run: 67 | 68 | ```sh 69 | ./scripts/android/build 70 | ``` 71 | 72 | The plugin will build and also copy to the example, just export the ios project (make sure to check the plugin in export preset) 73 | 74 | And done, everything is ready to test :) 75 | 76 | ## Scripts 77 | 78 | ### Android Scripts 79 | 80 | > [install.sh](./scripts/android/install.sh) 81 | 82 | Install godot-lib.aar, which require to build Android plugin. 83 | 84 | (Will install default version in [build.env](./build.env) if no version provided) 85 | 86 | Example: 87 | 88 | ```sh 89 | ./scripts/android/install.sh 3.5 90 | ``` 91 | 92 | > [build.sh](./scripts/android/build.sh) 93 | 94 | Install and build the Android plugin 95 | 96 | This will also copy builded file to the example projects (if you have install android custom template) 97 | 98 | (Will build default version in [build.env](./build.env) if no version provided) 99 | 100 | Example: 101 | 102 | ```sh 103 | ./scripts/android/build.sh 3.5 104 | ``` 105 | 106 | > [release.sh](./scripts/android/release.sh) 107 | 108 | Build and release an Android plugin, the output will be in `.release/android/` folder. 109 | 110 | (Will build and release all support versions in [build.env](./build.env) if no version provided) 111 | 112 | Example: 113 | 114 | ```sh 115 | # Release a specific version 116 | ./scripts/android/release.sh 3.5 117 | 118 | # Release all version 119 | ./scripts/android/release.sh 120 | ``` 121 | 122 | ### iOS Scripts 123 | 124 | > [install.sh](./scripts/ios/install.sh) 125 | 126 | Install godot extracted headers, which require to build iOS plugin. 127 | 128 | (Will install default version in [build.env](./build.env) if no version provided) 129 | 130 | Example: 131 | 132 | ```sh 133 | ./scripts/ios/install.sh 3.5 134 | ``` 135 | 136 | > [build.sh](./scripts/ios/build.sh) 137 | 138 | Install and build the iOS plugin 139 | 140 | This will also copy builded file to the example projects has exported ios project to `exported/ios`) 141 | 142 | (Will build default version in [build.env](./build.env) if no version provided) 143 | 144 | Example: 145 | 146 | ```sh 147 | ./scripts/ios/build.sh 3.5 148 | ``` 149 | 150 | > [release.sh](./scripts/ios/release.sh) 151 | 152 | Build and release an iOS plugin, the output will be in `.release/ios/` folder. 153 | 154 | (Will build and release all support versions in [build.env](./build.env) if no version provided) 155 | 156 | Example: 157 | 158 | ```sh 159 | # Release a specific version 160 | ./scripts/ios/release.sh 3.5 161 | 162 | # Release all version 163 | ./scripts/ios/release.sh 164 | ``` -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /ios/SConstruct: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | import subprocess 5 | 6 | if sys.version_info < (3,): 7 | def decode_utf8(x): 8 | return x 9 | else: 10 | import codecs 11 | def decode_utf8(x): 12 | return codecs.utf_8_decode(x)[0] 13 | 14 | # Most of the settings are taken from https://github.com/BastiaanOlij/gdnative_cpp_example 15 | 16 | opts = Variables([], ARGUMENTS) 17 | 18 | # Gets the standard flags CC, CCX, etc. 19 | env = DefaultEnvironment() 20 | 21 | # Define our options 22 | opts.Add(EnumVariable('target', "Compilation target", 'debug', ['debug', 'release', "release_debug"])) 23 | opts.Add(EnumVariable('arch', "Compilation Architecture", '', ['', 'arm64', 'armv7', 'x86_64'])) 24 | opts.Add(BoolVariable('simulator', "Compilation platform", 'no')) 25 | opts.Add(BoolVariable('use_llvm', "Use the LLVM / Clang compiler", 'no')) 26 | opts.Add(PathVariable('target_path', 'The path where the lib is installed.', 'bin/')) 27 | opts.Add(EnumVariable('plugin', 'Plugin to build', '', ['', 'haptics'])) 28 | opts.Add(EnumVariable('version', 'Godot version to target', '', ['', '3.x', '4.0'])) 29 | 30 | # Updates the environment with the option variables. 31 | opts.Update(env) 32 | 33 | # Process some arguments 34 | if env['use_llvm']: 35 | env['CC'] = 'clang' 36 | env['CXX'] = 'clang++' 37 | 38 | if env['arch'] == '': 39 | print("No valid arch selected.") 40 | quit(); 41 | 42 | if env['plugin'] == '': 43 | print("No valid plugin selected.") 44 | quit(); 45 | 46 | if env['version'] == '': 47 | print("No valid Godot version selected.") 48 | quit(); 49 | 50 | # For the reference: 51 | # - CCFLAGS are compilation flags shared between C and C++ 52 | # - CFLAGS are for C-specific compilation flags 53 | # - CXXFLAGS are for C++-specific compilation flags 54 | # - CPPFLAGS are for pre-processor flags 55 | # - CPPDEFINES are for pre-processor defines 56 | # - LINKFLAGS are for linking flags 57 | 58 | # Enable Obj-C modules 59 | env.Append(CCFLAGS=["-fmodules", "-fcxx-modules"]) 60 | 61 | if env['simulator']: 62 | sdk_name = 'iphonesimulator' 63 | env.Append(CCFLAGS=['-mios-simulator-version-min=10.0']) 64 | env.Append(LINKFLAGS=["-mios-simulator-version-min=10.0"]) 65 | else: 66 | sdk_name = 'iphoneos' 67 | env.Append(CCFLAGS=['-miphoneos-version-min=10.0']) 68 | env.Append(LINKFLAGS=["-miphoneos-version-min=10.0"]) 69 | 70 | try: 71 | sdk_path = decode_utf8(subprocess.check_output(['xcrun', '--sdk', sdk_name, '--show-sdk-path']).strip()) 72 | except (subprocess.CalledProcessError, OSError): 73 | raise ValueError("Failed to find SDK path while running xcrun --sdk {} --show-sdk-path.".format(sdk_name)) 74 | 75 | env.Append(CCFLAGS=[ 76 | '-fobjc-arc', 77 | '-fmessage-length=0', '-fno-strict-aliasing', '-fdiagnostics-print-source-range-info', 78 | '-fdiagnostics-show-category=id', '-fdiagnostics-parseable-fixits', '-fpascal-strings', 79 | '-fblocks', '-fvisibility=hidden', '-MMD', '-MT', 'dependencies', '-fno-exceptions', 80 | '-Wno-ambiguous-macro', 81 | '-Wall', '-Werror=return-type', 82 | # '-Wextra', 83 | ]) 84 | 85 | env.Append(CCFLAGS=['-arch', env['arch'], "-isysroot", "$IOS_SDK_PATH", "-stdlib=libc++", '-isysroot', sdk_path]) 86 | env.Append(CCFLAGS=['-DPTRCALL_ENABLED']) 87 | env.Prepend(CXXFLAGS=[ 88 | '-DNEED_LONG_INT', '-DLIBYUV_DISABLE_NEON', 89 | '-DIOS_ENABLED', '-DUNIX_ENABLED', '-DCOREAUDIO_ENABLED' 90 | ]) 91 | env.Append(LINKFLAGS=["-arch", env['arch'], '-isysroot', sdk_path, '-F' + sdk_path]) 92 | 93 | if env['arch'] == 'armv7': 94 | env.Prepend(CXXFLAGS=['-fno-aligned-allocation']) 95 | 96 | if env['version'] == '3.x': 97 | env.Append(CCFLAGS=["$IPHONESDK"]) 98 | env.Prepend(CXXFLAGS=['-DIPHONE_ENABLED']) 99 | env.Prepend(CXXFLAGS=['-DVERSION_3_X']) 100 | 101 | env.Prepend(CFLAGS=['-std=gnu11']) 102 | env.Prepend(CXXFLAGS=['-DGLES_ENABLED', '-std=gnu++14']) 103 | 104 | if env['target'] == 'debug': 105 | env.Prepend(CXXFLAGS=[ 106 | '-gdwarf-2', '-O0', 107 | '-DDEBUG_MEMORY_ALLOC', '-DDISABLE_FORCED_INLINE', 108 | '-D_DEBUG', '-DDEBUG=1', '-DDEBUG_ENABLED', 109 | '-DPTRCALL_ENABLED', 110 | ]) 111 | elif env['target'] == 'release_debug': 112 | env.Prepend(CXXFLAGS=['-O2', '-ftree-vectorize', 113 | '-DNDEBUG', '-DNS_BLOCK_ASSERTIONS=1', '-DDEBUG_ENABLED', 114 | '-DPTRCALL_ENABLED', 115 | ]) 116 | 117 | if env['arch'] != 'armv7': 118 | env.Prepend(CXXFLAGS=['-fomit-frame-pointer']) 119 | else: 120 | env.Prepend(CXXFLAGS=[ 121 | '-O2', '-ftree-vectorize', 122 | '-DNDEBUG', '-DNS_BLOCK_ASSERTIONS=1', 123 | '-DPTRCALL_ENABLED', 124 | ]) 125 | 126 | if env['arch'] != 'armv7': 127 | env.Prepend(CXXFLAGS=['-fomit-frame-pointer']) 128 | elif env['version'] == '4.0': 129 | env.Append(CCFLAGS=["$IOS_SDK_PATH"]) 130 | env.Prepend(CXXFLAGS=['-DIOS_ENABLED']) 131 | env.Prepend(CXXFLAGS=['-DVERSION_4_0']) 132 | 133 | env.Prepend(CFLAGS=['-std=gnu11']) 134 | env.Prepend(CXXFLAGS=['-DVULKAN_ENABLED', '-std=gnu++17']) 135 | 136 | if env['target'] == 'debug': 137 | env.Prepend(CXXFLAGS=[ 138 | '-gdwarf-2', '-O0', 139 | '-DDEBUG_MEMORY_ALLOC', '-DDISABLE_FORCED_INLINE', 140 | '-D_DEBUG', '-DDEBUG=1', '-DDEBUG_ENABLED', 141 | ]) 142 | elif env['target'] == 'release_debug': 143 | env.Prepend(CXXFLAGS=[ 144 | '-O2', '-ftree-vectorize', 145 | '-DNDEBUG', '-DNS_BLOCK_ASSERTIONS=1', '-DDEBUG_ENABLED', 146 | ]) 147 | 148 | if env['arch'] != 'armv7': 149 | env.Prepend(CXXFLAGS=['-fomit-frame-pointer']) 150 | else: 151 | env.Prepend(CXXFLAGS=[ 152 | '-O2', '-ftree-vectorize', 153 | '-DNDEBUG', '-DNS_BLOCK_ASSERTIONS=1', 154 | ]) 155 | 156 | if env['arch'] != 'armv7': 157 | env.Prepend(CXXFLAGS=['-fomit-frame-pointer']) 158 | else: 159 | print("No valid version to set flags for.") 160 | quit(); 161 | 162 | # Adding header files 163 | if env['version'] == '3.x': 164 | env.Append(CPPPATH=[ 165 | '.', 166 | 'godot', 167 | 'godot/platform/iphone', 168 | ]) 169 | else: 170 | env.Append(CPPPATH=[ 171 | '.', 172 | 'godot', 173 | 'godot/platform/ios', 174 | ]) 175 | 176 | # tweak this if you want to use different folders, or more folders, to store your source code in. 177 | sources = Glob('plugin/' + env['plugin'] + '/*.mm') 178 | # sources.append(Glob('plugin/' + env['plugin'] + '/*.mm')) 179 | # sources.append(Glob('plugin/' + env['plugin'] + '/*.m')) 180 | 181 | # lib.-..a 182 | library_platform = env["arch"] + "-" + ("simulator" if env["simulator"] else ("iphone" if env['version'] == '3.x' else "ios")) 183 | library_name = env['plugin'] + "." + library_platform + "." + env["target"] + ".a" 184 | library = env.StaticLibrary(target=env['target_path'] + library_name, source=sources) 185 | 186 | Default(library) 187 | 188 | # Generates help for the -h scons option. 189 | Help(opts.GenerateHelpText(env)) -------------------------------------------------------------------------------- /example/godot_3/export_presets.cfg: -------------------------------------------------------------------------------- 1 | [preset.0] 2 | 3 | name="Android" 4 | platform="Android" 5 | runnable=true 6 | custom_features="" 7 | export_filter="all_resources" 8 | include_filter="" 9 | exclude_filter="" 10 | export_path="../../../../../Downloads/Example.aab" 11 | script_export_mode=1 12 | script_encryption_key="" 13 | 14 | [preset.0.options] 15 | 16 | custom_template/debug="" 17 | custom_template/release="" 18 | custom_build/use_custom_build=true 19 | custom_build/export_format=1 20 | custom_build/min_sdk="24" 21 | custom_build/target_sdk="" 22 | plugins/Haptics=true 23 | architectures/armeabi-v7a=true 24 | architectures/arm64-v8a=true 25 | architectures/x86=false 26 | architectures/x86_64=false 27 | keystore/debug="" 28 | keystore/debug_user="" 29 | keystore/debug_password="" 30 | keystore/release="" 31 | keystore/release_user="" 32 | keystore/release_password="" 33 | one_click_deploy/clear_previous_install=false 34 | version/code=1 35 | version/name="1.0" 36 | package/unique_name="vn.kyoz.godot.haptics" 37 | package/name="Godot Haptics" 38 | package/signed=true 39 | package/classify_as_game=true 40 | package/retain_data_on_uninstall=false 41 | package/exclude_from_recents=false 42 | launcher_icons/main_192x192="" 43 | launcher_icons/adaptive_foreground_432x432="" 44 | launcher_icons/adaptive_background_432x432="" 45 | graphics/opengl_debug=false 46 | xr_features/xr_mode=0 47 | xr_features/hand_tracking=0 48 | xr_features/hand_tracking_frequency=0 49 | xr_features/passthrough=0 50 | screen/immersive_mode=true 51 | screen/support_small=true 52 | screen/support_normal=true 53 | screen/support_large=true 54 | screen/support_xlarge=true 55 | user_data_backup/allow=false 56 | command_line/extra_args="" 57 | apk_expansion/enable=false 58 | apk_expansion/SALT="" 59 | apk_expansion/public_key="" 60 | permissions/custom_permissions=PoolStringArray( ) 61 | permissions/access_checkin_properties=false 62 | permissions/access_coarse_location=false 63 | permissions/access_fine_location=false 64 | permissions/access_location_extra_commands=false 65 | permissions/access_mock_location=false 66 | permissions/access_network_state=false 67 | permissions/access_surface_flinger=false 68 | permissions/access_wifi_state=false 69 | permissions/account_manager=false 70 | permissions/add_voicemail=false 71 | permissions/authenticate_accounts=false 72 | permissions/battery_stats=false 73 | permissions/bind_accessibility_service=false 74 | permissions/bind_appwidget=false 75 | permissions/bind_device_admin=false 76 | permissions/bind_input_method=false 77 | permissions/bind_nfc_service=false 78 | permissions/bind_notification_listener_service=false 79 | permissions/bind_print_service=false 80 | permissions/bind_remoteviews=false 81 | permissions/bind_text_service=false 82 | permissions/bind_vpn_service=false 83 | permissions/bind_wallpaper=false 84 | permissions/bluetooth=false 85 | permissions/bluetooth_admin=false 86 | permissions/bluetooth_privileged=false 87 | permissions/brick=false 88 | permissions/broadcast_package_removed=false 89 | permissions/broadcast_sms=false 90 | permissions/broadcast_sticky=false 91 | permissions/broadcast_wap_push=false 92 | permissions/call_phone=false 93 | permissions/call_privileged=false 94 | permissions/camera=false 95 | permissions/capture_audio_output=false 96 | permissions/capture_secure_video_output=false 97 | permissions/capture_video_output=false 98 | permissions/change_component_enabled_state=false 99 | permissions/change_configuration=false 100 | permissions/change_network_state=false 101 | permissions/change_wifi_multicast_state=false 102 | permissions/change_wifi_state=false 103 | permissions/clear_app_cache=false 104 | permissions/clear_app_user_data=false 105 | permissions/control_location_updates=false 106 | permissions/delete_cache_files=false 107 | permissions/delete_packages=false 108 | permissions/device_power=false 109 | permissions/diagnostic=false 110 | permissions/disable_keyguard=false 111 | permissions/dump=false 112 | permissions/expand_status_bar=false 113 | permissions/factory_test=false 114 | permissions/flashlight=false 115 | permissions/force_back=false 116 | permissions/get_accounts=false 117 | permissions/get_package_size=false 118 | permissions/get_tasks=false 119 | permissions/get_top_activity_info=false 120 | permissions/global_search=false 121 | permissions/hardware_test=false 122 | permissions/inject_events=false 123 | permissions/install_location_provider=false 124 | permissions/install_packages=false 125 | permissions/install_shortcut=false 126 | permissions/internal_system_window=false 127 | permissions/internet=false 128 | permissions/kill_background_processes=false 129 | permissions/location_hardware=false 130 | permissions/manage_accounts=false 131 | permissions/manage_app_tokens=false 132 | permissions/manage_documents=false 133 | permissions/manage_external_storage=false 134 | permissions/master_clear=false 135 | permissions/media_content_control=false 136 | permissions/modify_audio_settings=false 137 | permissions/modify_phone_state=false 138 | permissions/mount_format_filesystems=false 139 | permissions/mount_unmount_filesystems=false 140 | permissions/nfc=false 141 | permissions/persistent_activity=false 142 | permissions/process_outgoing_calls=false 143 | permissions/read_calendar=false 144 | permissions/read_call_log=false 145 | permissions/read_contacts=false 146 | permissions/read_external_storage=false 147 | permissions/read_frame_buffer=false 148 | permissions/read_history_bookmarks=false 149 | permissions/read_input_state=false 150 | permissions/read_logs=false 151 | permissions/read_phone_state=false 152 | permissions/read_profile=false 153 | permissions/read_sms=false 154 | permissions/read_social_stream=false 155 | permissions/read_sync_settings=false 156 | permissions/read_sync_stats=false 157 | permissions/read_user_dictionary=false 158 | permissions/reboot=false 159 | permissions/receive_boot_completed=false 160 | permissions/receive_mms=false 161 | permissions/receive_sms=false 162 | permissions/receive_wap_push=false 163 | permissions/record_audio=false 164 | permissions/reorder_tasks=false 165 | permissions/restart_packages=false 166 | permissions/send_respond_via_message=false 167 | permissions/send_sms=false 168 | permissions/set_activity_watcher=false 169 | permissions/set_alarm=false 170 | permissions/set_always_finish=false 171 | permissions/set_animation_scale=false 172 | permissions/set_debug_app=false 173 | permissions/set_orientation=false 174 | permissions/set_pointer_speed=false 175 | permissions/set_preferred_applications=false 176 | permissions/set_process_limit=false 177 | permissions/set_time=false 178 | permissions/set_time_zone=false 179 | permissions/set_wallpaper=false 180 | permissions/set_wallpaper_hints=false 181 | permissions/signal_persistent_processes=false 182 | permissions/status_bar=false 183 | permissions/subscribed_feeds_read=false 184 | permissions/subscribed_feeds_write=false 185 | permissions/system_alert_window=false 186 | permissions/transmit_ir=false 187 | permissions/uninstall_shortcut=false 188 | permissions/update_device_stats=false 189 | permissions/use_credentials=false 190 | permissions/use_sip=false 191 | permissions/vibrate=false 192 | permissions/wake_lock=false 193 | permissions/write_apn_settings=false 194 | permissions/write_calendar=false 195 | permissions/write_call_log=false 196 | permissions/write_contacts=false 197 | permissions/write_external_storage=false 198 | permissions/write_gservices=false 199 | permissions/write_history_bookmarks=false 200 | permissions/write_profile=false 201 | permissions/write_secure_settings=false 202 | permissions/write_settings=false 203 | permissions/write_sms=false 204 | permissions/write_social_stream=false 205 | permissions/write_sync_settings=false 206 | permissions/write_user_dictionary=false 207 | 208 | [preset.1] 209 | 210 | name="iOS" 211 | platform="iOS" 212 | runnable=true 213 | custom_features="" 214 | export_filter="all_resources" 215 | include_filter="" 216 | exclude_filter="" 217 | export_path="exported/ios/Example.ipa" 218 | script_export_mode=1 219 | script_encryption_key="" 220 | 221 | [preset.1.options] 222 | 223 | custom_template/debug="" 224 | custom_template/release="" 225 | architectures/armv7=false 226 | architectures/arm64=true 227 | application/app_store_team_id="123456" 228 | application/provisioning_profile_uuid_debug="" 229 | application/code_sign_identity_debug="" 230 | application/export_method_debug=1 231 | application/provisioning_profile_uuid_release="" 232 | application/code_sign_identity_release="" 233 | application/export_method_release=0 234 | application/targeted_device_family=2 235 | application/name="Godot Example" 236 | application/info="Made with Godot Engine" 237 | application/identifier="vn.kyoz.godot.example" 238 | application/signature="Kyoz" 239 | application/short_version="1.0" 240 | application/version="1.0" 241 | application/copyright="" 242 | plugins/Haptics=true 243 | plugins/Flashlight=false 244 | capabilities/access_wifi=false 245 | capabilities/push_notifications=false 246 | user_data/accessible_from_files_app=false 247 | user_data/accessible_from_itunes_sharing=false 248 | privacy/camera_usage_description="" 249 | privacy/microphone_usage_description="" 250 | privacy/photolibrary_usage_description="" 251 | icons/iphone_120x120="" 252 | icons/iphone_180x180="" 253 | icons/ipad_76x76="" 254 | icons/ipad_152x152="" 255 | icons/ipad_167x167="" 256 | icons/app_store_1024x1024="res://icon.png" 257 | icons/spotlight_40x40="" 258 | icons/spotlight_80x80="" 259 | storyboard/use_launch_screen_storyboard=false 260 | storyboard/image_scale_mode=0 261 | storyboard/custom_image@2x="" 262 | storyboard/custom_image@3x="" 263 | storyboard/use_custom_bg_color=false 264 | storyboard/custom_bg_color=Color( 0, 0, 0, 1 ) 265 | landscape_launch_screens/iphone_2436x1125="" 266 | landscape_launch_screens/iphone_2208x1242="" 267 | landscape_launch_screens/ipad_1024x768="" 268 | landscape_launch_screens/ipad_2048x1536="" 269 | portrait_launch_screens/iphone_640x960="" 270 | portrait_launch_screens/iphone_640x1136="" 271 | portrait_launch_screens/iphone_750x1334="" 272 | portrait_launch_screens/iphone_1125x2436="" 273 | portrait_launch_screens/ipad_768x1024="" 274 | portrait_launch_screens/ipad_1536x2048="" 275 | portrait_launch_screens/iphone_1242x2208="" 276 | -------------------------------------------------------------------------------- /example/godot_4/export_presets.cfg: -------------------------------------------------------------------------------- 1 | [preset.0] 2 | 3 | name="Android" 4 | platform="Android" 5 | runnable=true 6 | custom_features="" 7 | export_filter="all_resources" 8 | include_filter="" 9 | exclude_filter="" 10 | export_path="../../../../../Downloads/Example.aab" 11 | script_export_mode=1 12 | script_encryption_key="" 13 | 14 | [preset.0.options] 15 | 16 | custom_template/debug="" 17 | custom_template/release="" 18 | custom_build/use_custom_build=true 19 | custom_build/export_format=1 20 | custom_build/min_sdk="24" 21 | custom_build/target_sdk="" 22 | plugins/Haptics=true 23 | architectures/armeabi-v7a=true 24 | architectures/arm64-v8a=true 25 | architectures/x86=false 26 | architectures/x86_64=false 27 | keystore/debug="" 28 | keystore/debug_user="" 29 | keystore/debug_password="" 30 | keystore/release="" 31 | keystore/release_user="" 32 | keystore/release_password="" 33 | one_click_deploy/clear_previous_install=false 34 | version/code=1 35 | version/name="1.0" 36 | package/unique_name="vn.kyoz.godot.haptics" 37 | package/name="Godot Haptics" 38 | package/signed=true 39 | package/classify_as_game=true 40 | package/retain_data_on_uninstall=false 41 | package/exclude_from_recents=false 42 | launcher_icons/main_192x192="" 43 | launcher_icons/adaptive_foreground_432x432="" 44 | launcher_icons/adaptive_background_432x432="" 45 | graphics/opengl_debug=false 46 | xr_features/xr_mode=0 47 | xr_features/hand_tracking=0 48 | xr_features/hand_tracking_frequency=0 49 | xr_features/passthrough=0 50 | screen/immersive_mode=true 51 | screen/support_small=true 52 | screen/support_normal=true 53 | screen/support_large=true 54 | screen/support_xlarge=true 55 | user_data_backup/allow=false 56 | command_line/extra_args="" 57 | apk_expansion/enable=false 58 | apk_expansion/SALT="" 59 | apk_expansion/public_key="" 60 | permissions/custom_permissions=PoolStringArray( ) 61 | permissions/access_checkin_properties=false 62 | permissions/access_coarse_location=false 63 | permissions/access_fine_location=false 64 | permissions/access_location_extra_commands=false 65 | permissions/access_mock_location=false 66 | permissions/access_network_state=false 67 | permissions/access_surface_flinger=false 68 | permissions/access_wifi_state=false 69 | permissions/account_manager=false 70 | permissions/add_voicemail=false 71 | permissions/authenticate_accounts=false 72 | permissions/battery_stats=false 73 | permissions/bind_accessibility_service=false 74 | permissions/bind_appwidget=false 75 | permissions/bind_device_admin=false 76 | permissions/bind_input_method=false 77 | permissions/bind_nfc_service=false 78 | permissions/bind_notification_listener_service=false 79 | permissions/bind_print_service=false 80 | permissions/bind_remoteviews=false 81 | permissions/bind_text_service=false 82 | permissions/bind_vpn_service=false 83 | permissions/bind_wallpaper=false 84 | permissions/bluetooth=false 85 | permissions/bluetooth_admin=false 86 | permissions/bluetooth_privileged=false 87 | permissions/brick=false 88 | permissions/broadcast_package_removed=false 89 | permissions/broadcast_sms=false 90 | permissions/broadcast_sticky=false 91 | permissions/broadcast_wap_push=false 92 | permissions/call_phone=false 93 | permissions/call_privileged=false 94 | permissions/camera=false 95 | permissions/capture_audio_output=false 96 | permissions/capture_secure_video_output=false 97 | permissions/capture_video_output=false 98 | permissions/change_component_enabled_state=false 99 | permissions/change_configuration=false 100 | permissions/change_network_state=false 101 | permissions/change_wifi_multicast_state=false 102 | permissions/change_wifi_state=false 103 | permissions/clear_app_cache=false 104 | permissions/clear_app_user_data=false 105 | permissions/control_location_updates=false 106 | permissions/delete_cache_files=false 107 | permissions/delete_packages=false 108 | permissions/device_power=false 109 | permissions/diagnostic=false 110 | permissions/disable_keyguard=false 111 | permissions/dump=false 112 | permissions/expand_status_bar=false 113 | permissions/factory_test=false 114 | permissions/flashlight=false 115 | permissions/force_back=false 116 | permissions/get_accounts=false 117 | permissions/get_package_size=false 118 | permissions/get_tasks=false 119 | permissions/get_top_activity_info=false 120 | permissions/global_search=false 121 | permissions/hardware_test=false 122 | permissions/inject_events=false 123 | permissions/install_location_provider=false 124 | permissions/install_packages=false 125 | permissions/install_shortcut=false 126 | permissions/internal_system_window=false 127 | permissions/internet=false 128 | permissions/kill_background_processes=false 129 | permissions/location_hardware=false 130 | permissions/manage_accounts=false 131 | permissions/manage_app_tokens=false 132 | permissions/manage_documents=false 133 | permissions/manage_external_storage=false 134 | permissions/master_clear=false 135 | permissions/media_content_control=false 136 | permissions/modify_audio_settings=false 137 | permissions/modify_phone_state=false 138 | permissions/mount_format_filesystems=false 139 | permissions/mount_unmount_filesystems=false 140 | permissions/nfc=false 141 | permissions/persistent_activity=false 142 | permissions/process_outgoing_calls=false 143 | permissions/read_calendar=false 144 | permissions/read_call_log=false 145 | permissions/read_contacts=false 146 | permissions/read_external_storage=false 147 | permissions/read_frame_buffer=false 148 | permissions/read_history_bookmarks=false 149 | permissions/read_input_state=false 150 | permissions/read_logs=false 151 | permissions/read_phone_state=false 152 | permissions/read_profile=false 153 | permissions/read_sms=false 154 | permissions/read_social_stream=false 155 | permissions/read_sync_settings=false 156 | permissions/read_sync_stats=false 157 | permissions/read_user_dictionary=false 158 | permissions/reboot=false 159 | permissions/receive_boot_completed=false 160 | permissions/receive_mms=false 161 | permissions/receive_sms=false 162 | permissions/receive_wap_push=false 163 | permissions/record_audio=false 164 | permissions/reorder_tasks=false 165 | permissions/restart_packages=false 166 | permissions/send_respond_via_message=false 167 | permissions/send_sms=false 168 | permissions/set_activity_watcher=false 169 | permissions/set_alarm=false 170 | permissions/set_always_finish=false 171 | permissions/set_animation_scale=false 172 | permissions/set_debug_app=false 173 | permissions/set_orientation=false 174 | permissions/set_pointer_speed=false 175 | permissions/set_preferred_applications=false 176 | permissions/set_process_limit=false 177 | permissions/set_time=false 178 | permissions/set_time_zone=false 179 | permissions/set_wallpaper=false 180 | permissions/set_wallpaper_hints=false 181 | permissions/signal_persistent_processes=false 182 | permissions/status_bar=false 183 | permissions/subscribed_feeds_read=false 184 | permissions/subscribed_feeds_write=false 185 | permissions/system_alert_window=false 186 | permissions/transmit_ir=false 187 | permissions/uninstall_shortcut=false 188 | permissions/update_device_stats=false 189 | permissions/use_credentials=false 190 | permissions/use_sip=false 191 | permissions/vibrate=false 192 | permissions/wake_lock=false 193 | permissions/write_apn_settings=false 194 | permissions/write_calendar=false 195 | permissions/write_call_log=false 196 | permissions/write_contacts=false 197 | permissions/write_external_storage=false 198 | permissions/write_gservices=false 199 | permissions/write_history_bookmarks=false 200 | permissions/write_profile=false 201 | permissions/write_secure_settings=false 202 | permissions/write_settings=false 203 | permissions/write_sms=false 204 | permissions/write_social_stream=false 205 | permissions/write_sync_settings=false 206 | permissions/write_user_dictionary=false 207 | 208 | [preset.1] 209 | 210 | name="iOS" 211 | platform="iOS" 212 | runnable=true 213 | custom_features="" 214 | export_filter="all_resources" 215 | include_filter="" 216 | exclude_filter="" 217 | export_path="exported/ios/Example.ipa" 218 | script_export_mode=1 219 | script_encryption_key="" 220 | 221 | [preset.1.options] 222 | 223 | custom_template/debug="" 224 | custom_template/release="" 225 | architectures/armv7=false 226 | architectures/arm64=true 227 | application/app_store_team_id="123456" 228 | application/provisioning_profile_uuid_debug="" 229 | application/code_sign_identity_debug="" 230 | application/export_method_debug=1 231 | application/provisioning_profile_uuid_release="" 232 | application/code_sign_identity_release="" 233 | application/export_method_release=0 234 | application/targeted_device_family=2 235 | application/name="Godot Example" 236 | application/info="Made with Godot Engine" 237 | application/identifier="vn.kyoz.godot.example" 238 | application/signature="Kyoz" 239 | application/short_version="1.0" 240 | application/version="1.0" 241 | application/copyright="" 242 | plugins/Haptics=true 243 | plugins/Flashlight=false 244 | capabilities/access_wifi=false 245 | capabilities/push_notifications=false 246 | user_data/accessible_from_files_app=false 247 | user_data/accessible_from_itunes_sharing=false 248 | privacy/camera_usage_description="" 249 | privacy/microphone_usage_description="" 250 | privacy/photolibrary_usage_description="" 251 | icons/iphone_120x120="" 252 | icons/iphone_180x180="" 253 | icons/ipad_76x76="" 254 | icons/ipad_152x152="" 255 | icons/ipad_167x167="" 256 | icons/app_store_1024x1024="res://icon.png" 257 | icons/spotlight_40x40="" 258 | icons/spotlight_80x80="" 259 | storyboard/use_launch_screen_storyboard=false 260 | storyboard/image_scale_mode=0 261 | storyboard/custom_image@2x="" 262 | storyboard/custom_image@3x="" 263 | storyboard/use_custom_bg_color=false 264 | storyboard/custom_bg_color=Color( 0, 0, 0, 1 ) 265 | landscape_launch_screens/iphone_2436x1125="" 266 | landscape_launch_screens/iphone_2208x1242="" 267 | landscape_launch_screens/ipad_1024x768="" 268 | landscape_launch_screens/ipad_2048x1536="" 269 | portrait_launch_screens/iphone_640x960="" 270 | portrait_launch_screens/iphone_640x1136="" 271 | portrait_launch_screens/iphone_750x1334="" 272 | portrait_launch_screens/iphone_1125x2436="" 273 | portrait_launch_screens/ipad_768x1024="" 274 | portrait_launch_screens/ipad_1536x2048="" 275 | portrait_launch_screens/iphone_1242x2208="" 276 | -------------------------------------------------------------------------------- /ios/plugin/haptics.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 56; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | BD8AECFD2A5744C000222717 /* haptics.mm in Sources */ = {isa = PBXBuildFile; fileRef = BD8AECFC2A5744C000222717 /* haptics.mm */; }; 11 | BD8AECFE2A5744C000222717 /* haptics.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = BD8AECFB2A5744C000222717 /* haptics.h */; }; 12 | BDF397C62A5BE8D50073C2AD /* haptics_module.mm in Sources */ = {isa = PBXBuildFile; fileRef = BDF397C52A5BE8D50073C2AD /* haptics_module.mm */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXCopyFilesBuildPhase section */ 16 | BD8AECF62A5744C000222717 /* CopyFiles */ = { 17 | isa = PBXCopyFilesBuildPhase; 18 | buildActionMask = 2147483647; 19 | dstPath = "include/$(PRODUCT_NAME)"; 20 | dstSubfolderSpec = 16; 21 | files = ( 22 | BD8AECFE2A5744C000222717 /* haptics.h in CopyFiles */, 23 | ); 24 | runOnlyForDeploymentPostprocessing = 0; 25 | }; 26 | /* End PBXCopyFilesBuildPhase section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | BD8AECF82A5744C000222717 /* libhaptics.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libhaptics.a; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | BD8AECFB2A5744C000222717 /* haptics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = haptics.h; sourceTree = ""; }; 31 | BD8AECFC2A5744C000222717 /* haptics.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; path = haptics.mm; sourceTree = ""; }; 32 | BDF397C22A5B4A5A0073C2AD /* haptics_module.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = haptics_module.h; sourceTree = ""; }; 33 | BDF397C52A5BE8D50073C2AD /* haptics_module.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; path = haptics_module.mm; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | BD8AECF52A5744C000222717 /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXFrameworksBuildPhase section */ 45 | 46 | /* Begin PBXGroup section */ 47 | BD8AECEF2A5744C000222717 = { 48 | isa = PBXGroup; 49 | children = ( 50 | BD8AECFA2A5744C000222717 /* haptics */, 51 | BD8AECF92A5744C000222717 /* Products */, 52 | ); 53 | sourceTree = ""; 54 | }; 55 | BD8AECF92A5744C000222717 /* Products */ = { 56 | isa = PBXGroup; 57 | children = ( 58 | BD8AECF82A5744C000222717 /* libhaptics.a */, 59 | ); 60 | name = Products; 61 | sourceTree = ""; 62 | }; 63 | BD8AECFA2A5744C000222717 /* haptics */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | BDF397C52A5BE8D50073C2AD /* haptics_module.mm */, 67 | BD8AECFB2A5744C000222717 /* haptics.h */, 68 | BD8AECFC2A5744C000222717 /* haptics.mm */, 69 | BDF397C22A5B4A5A0073C2AD /* haptics_module.h */, 70 | ); 71 | path = haptics; 72 | sourceTree = ""; 73 | }; 74 | /* End PBXGroup section */ 75 | 76 | /* Begin PBXNativeTarget section */ 77 | BD8AECF72A5744C000222717 /* haptics */ = { 78 | isa = PBXNativeTarget; 79 | buildConfigurationList = BD8AED012A5744C000222717 /* Build configuration list for PBXNativeTarget "haptics" */; 80 | buildPhases = ( 81 | BD8AECF42A5744C000222717 /* Sources */, 82 | BD8AECF52A5744C000222717 /* Frameworks */, 83 | BD8AECF62A5744C000222717 /* CopyFiles */, 84 | ); 85 | buildRules = ( 86 | ); 87 | dependencies = ( 88 | ); 89 | name = haptics; 90 | productName = haptics; 91 | productReference = BD8AECF82A5744C000222717 /* libhaptics.a */; 92 | productType = "com.apple.product-type.library.static"; 93 | }; 94 | /* End PBXNativeTarget section */ 95 | 96 | /* Begin PBXProject section */ 97 | BD8AECF02A5744C000222717 /* Project object */ = { 98 | isa = PBXProject; 99 | attributes = { 100 | BuildIndependentTargetsInParallel = 1; 101 | LastUpgradeCheck = 1420; 102 | TargetAttributes = { 103 | BD8AECF72A5744C000222717 = { 104 | CreatedOnToolsVersion = 14.2; 105 | }; 106 | }; 107 | }; 108 | buildConfigurationList = BD8AECF32A5744C000222717 /* Build configuration list for PBXProject "haptics" */; 109 | compatibilityVersion = "Xcode 14.0"; 110 | developmentRegion = en; 111 | hasScannedForEncodings = 0; 112 | knownRegions = ( 113 | en, 114 | Base, 115 | ); 116 | mainGroup = BD8AECEF2A5744C000222717; 117 | productRefGroup = BD8AECF92A5744C000222717 /* Products */; 118 | projectDirPath = ""; 119 | projectRoot = ""; 120 | targets = ( 121 | BD8AECF72A5744C000222717 /* haptics */, 122 | ); 123 | }; 124 | /* End PBXProject section */ 125 | 126 | /* Begin PBXSourcesBuildPhase section */ 127 | BD8AECF42A5744C000222717 /* Sources */ = { 128 | isa = PBXSourcesBuildPhase; 129 | buildActionMask = 2147483647; 130 | files = ( 131 | BD8AECFD2A5744C000222717 /* haptics.mm in Sources */, 132 | BDF397C62A5BE8D50073C2AD /* haptics_module.mm in Sources */, 133 | ); 134 | runOnlyForDeploymentPostprocessing = 0; 135 | }; 136 | /* End PBXSourcesBuildPhase section */ 137 | 138 | /* Begin XCBuildConfiguration section */ 139 | BD8AECFF2A5744C000222717 /* Debug */ = { 140 | isa = XCBuildConfiguration; 141 | buildSettings = { 142 | ALWAYS_SEARCH_USER_PATHS = NO; 143 | CLANG_ANALYZER_NONNULL = YES; 144 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 145 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 146 | CLANG_ENABLE_MODULES = YES; 147 | CLANG_ENABLE_OBJC_ARC = YES; 148 | CLANG_ENABLE_OBJC_WEAK = YES; 149 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 150 | CLANG_WARN_BOOL_CONVERSION = YES; 151 | CLANG_WARN_COMMA = YES; 152 | CLANG_WARN_CONSTANT_CONVERSION = YES; 153 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 154 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 155 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 156 | CLANG_WARN_EMPTY_BODY = YES; 157 | CLANG_WARN_ENUM_CONVERSION = YES; 158 | CLANG_WARN_INFINITE_RECURSION = YES; 159 | CLANG_WARN_INT_CONVERSION = YES; 160 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 161 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 162 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 163 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 164 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 165 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 166 | CLANG_WARN_STRICT_PROTOTYPES = YES; 167 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 168 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 169 | CLANG_WARN_UNREACHABLE_CODE = YES; 170 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 171 | COPY_PHASE_STRIP = NO; 172 | DEBUG_INFORMATION_FORMAT = dwarf; 173 | ENABLE_STRICT_OBJC_MSGSEND = YES; 174 | ENABLE_TESTABILITY = YES; 175 | GCC_C_LANGUAGE_STANDARD = gnu11; 176 | GCC_DYNAMIC_NO_PIC = NO; 177 | GCC_NO_COMMON_BLOCKS = YES; 178 | GCC_OPTIMIZATION_LEVEL = 0; 179 | GCC_PREPROCESSOR_DEFINITIONS = ( 180 | "DEBUG=1", 181 | "$(inherited)", 182 | ); 183 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 184 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 185 | GCC_WARN_UNDECLARED_SELECTOR = YES; 186 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 187 | GCC_WARN_UNUSED_FUNCTION = YES; 188 | GCC_WARN_UNUSED_VARIABLE = YES; 189 | IPHONEOS_DEPLOYMENT_TARGET = 16.2; 190 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 191 | MTL_FAST_MATH = YES; 192 | ONLY_ACTIVE_ARCH = YES; 193 | SDKROOT = iphoneos; 194 | }; 195 | name = Debug; 196 | }; 197 | BD8AED002A5744C000222717 /* Release */ = { 198 | isa = XCBuildConfiguration; 199 | buildSettings = { 200 | ALWAYS_SEARCH_USER_PATHS = NO; 201 | CLANG_ANALYZER_NONNULL = YES; 202 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 203 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 204 | CLANG_ENABLE_MODULES = YES; 205 | CLANG_ENABLE_OBJC_ARC = YES; 206 | CLANG_ENABLE_OBJC_WEAK = YES; 207 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 208 | CLANG_WARN_BOOL_CONVERSION = YES; 209 | CLANG_WARN_COMMA = YES; 210 | CLANG_WARN_CONSTANT_CONVERSION = YES; 211 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 212 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 213 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 214 | CLANG_WARN_EMPTY_BODY = YES; 215 | CLANG_WARN_ENUM_CONVERSION = YES; 216 | CLANG_WARN_INFINITE_RECURSION = YES; 217 | CLANG_WARN_INT_CONVERSION = YES; 218 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 219 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 220 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 221 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 222 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 223 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 224 | CLANG_WARN_STRICT_PROTOTYPES = YES; 225 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 226 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 227 | CLANG_WARN_UNREACHABLE_CODE = YES; 228 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 229 | COPY_PHASE_STRIP = NO; 230 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 231 | ENABLE_NS_ASSERTIONS = NO; 232 | ENABLE_STRICT_OBJC_MSGSEND = YES; 233 | GCC_C_LANGUAGE_STANDARD = gnu11; 234 | GCC_NO_COMMON_BLOCKS = YES; 235 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 236 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 237 | GCC_WARN_UNDECLARED_SELECTOR = YES; 238 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 239 | GCC_WARN_UNUSED_FUNCTION = YES; 240 | GCC_WARN_UNUSED_VARIABLE = YES; 241 | IPHONEOS_DEPLOYMENT_TARGET = 16.2; 242 | MTL_ENABLE_DEBUG_INFO = NO; 243 | MTL_FAST_MATH = YES; 244 | SDKROOT = iphoneos; 245 | VALIDATE_PRODUCT = YES; 246 | }; 247 | name = Release; 248 | }; 249 | BD8AED022A5744C000222717 /* Debug */ = { 250 | isa = XCBuildConfiguration; 251 | buildSettings = { 252 | CODE_SIGN_STYLE = Automatic; 253 | DEVELOPMENT_TEAM = X8AT4MS8ZQ; 254 | HEADER_SEARCH_PATHS = ( 255 | "${inherited}", 256 | "${SRCROOT}/../godot", 257 | "${SRCROOT}/../godot/platform/iphone", 258 | ); 259 | OTHER_LDFLAGS = "-ObjC"; 260 | PRODUCT_NAME = "$(TARGET_NAME)"; 261 | SKIP_INSTALL = YES; 262 | TARGETED_DEVICE_FAMILY = "1,2"; 263 | }; 264 | name = Debug; 265 | }; 266 | BD8AED032A5744C000222717 /* Release */ = { 267 | isa = XCBuildConfiguration; 268 | buildSettings = { 269 | CODE_SIGN_STYLE = Automatic; 270 | DEVELOPMENT_TEAM = X8AT4MS8ZQ; 271 | HEADER_SEARCH_PATHS = ( 272 | "${inherited}", 273 | "${SRCROOT}/../godot", 274 | "${SRCROOT}/../godot/platform/iphone", 275 | ); 276 | OTHER_LDFLAGS = "-ObjC"; 277 | PRODUCT_NAME = "$(TARGET_NAME)"; 278 | SKIP_INSTALL = YES; 279 | TARGETED_DEVICE_FAMILY = "1,2"; 280 | }; 281 | name = Release; 282 | }; 283 | /* End XCBuildConfiguration section */ 284 | 285 | /* Begin XCConfigurationList section */ 286 | BD8AECF32A5744C000222717 /* Build configuration list for PBXProject "haptics" */ = { 287 | isa = XCConfigurationList; 288 | buildConfigurations = ( 289 | BD8AECFF2A5744C000222717 /* Debug */, 290 | BD8AED002A5744C000222717 /* Release */, 291 | ); 292 | defaultConfigurationIsVisible = 0; 293 | defaultConfigurationName = Release; 294 | }; 295 | BD8AED012A5744C000222717 /* Build configuration list for PBXNativeTarget "haptics" */ = { 296 | isa = XCConfigurationList; 297 | buildConfigurations = ( 298 | BD8AED022A5744C000222717 /* Debug */, 299 | BD8AED032A5744C000222717 /* Release */, 300 | ); 301 | defaultConfigurationIsVisible = 0; 302 | defaultConfigurationName = Release; 303 | }; 304 | /* End XCConfigurationList section */ 305 | }; 306 | rootObject = BD8AECF02A5744C000222717 /* Project object */; 307 | } 308 | --------------------------------------------------------------------------------