diff --git a/.github/workflows/build-on-push.yml b/.github/workflows/build-on-push.yml
index 9781fd1..dd330f1 100644
--- a/.github/workflows/build-on-push.yml
+++ b/.github/workflows/build-on-push.yml
@@ -17,20 +17,23 @@ jobs:
matrix:
include:
# Unsupported platforms are commented out.
- #- name: π§ Linux (GCC)
- # os: ubuntu-20.04
- # platform: linux
- # artifact-name: gdtiltfive.linux
- # artifact-path: build/bin/libgdtiltfive.linux.*
+ - name: π§ Linux (GCC)
+ os: ubuntu-20.04
+ platform: linux
+ artifact-name: gdtiltfive.linux
+ artifact-path: |
+ build/bin/linux/x86_64/libgdtiltfive.linux.template_debug.x86_64.so
+ build/bin/linux/x86_64/libgdtiltfive.linux.template_release.x86_64.so
+ extension/TiltFiveNDK/lib/linux/x86_64/libTiltFiveNative.so
- name: π Windows (x86_64, MSVC)
os: windows-2019
platform: windows
artifact-name: gdtiltfive.windows
artifact-path: |
- build/bin/libgdtiltfive.windows.template_debug.x86_64.dll
- build/bin/libgdtiltfive.windows.template_release.x86_64.dll
- extension/TiltFiveNDK/lib/win/x86_64/TiltFiveNative.dll
+ build/bin/windows/x86_64/libgdtiltfive.windows.template_debug.x86_64.dll
+ build/bin/windows/x86_64/libgdtiltfive.windows.template_release.x86_64.dll
+ extension/TiltFiveNDK/lib/win/x86_64/TiltFiveNative.dll
#- name: π macOS (universal)
# os: macos-11
@@ -39,12 +42,14 @@ jobs:
# artifact-name: gdtiltfive.macos
# artifact-path: build/bin/libgdtiltfive.macos.*
- #- name: π€ Android (arm64)
- # os: ubuntu-20.04
- # platform: android
- # flags: ANDROID_NDK_ROOT=$ANDROID_NDK_LATEST_HOME arch=arm64
- # artifact-name: gdtiltfive.android
- # artifact-path: build/bin/libgdtiltfive.android.*
+ - name: π€ Android (arm64)
+ os: ubuntu-20.04
+ platform: android
+ #flags: ANDROID_NDK_ROOT=$ANDROID_NDK_LATEST_HOME arch=arm64
+ artifact-name: gdtiltfive.android
+ artifact-path: |
+ build/bin/android/arm64/libgdtiltfive.android.*
+ androidplugin/plugin/build/outputs/aar/gdtiltfive*
#- name: π iOS (arm64)
# os: macos-11
@@ -72,17 +77,52 @@ jobs:
sudo apt-get update -qq
sudo apt-get install -qqq build-essential pkg-config
+ - name: Set up GCC
+ if: ${{ matrix.platform == 'linux' }}
+ uses: egor-tensin/setup-gcc@v1
+ with:
+ version: 11
+ platform: x64
+
+ - name: Android dependencies
+ if: ${{ matrix.platform == 'android' }}
+ uses: nttld/setup-ndk@v1
+ id: setup-ndk
+ with:
+ ndk-version: r26c
+ add-to-path: false
+
- name: Install scons
run: |
- python -m pip install scons==4.0.0
+ python -m pip install scons==4.0.0
- name: Build debug build
run: |
- scons platform=${{ matrix.platform }} target=template_debug ${{ matrix.flags }}
+ scons platform=${{ matrix.platform }} target=template_debug ${{ matrix.flags }} --no-gradle
+ env:
+ ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }}
- name: Build release build
run: |
- scons platform=${{ matrix.platform }} target=template_release ${{ matrix.flags }}
+ scons platform=${{ matrix.platform }} target=template_release ${{ matrix.flags }} --no-gradle
+ env:
+ ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }}
+
+ - name: Set up Java
+ if: ${{ matrix.platform == 'android' }}
+ uses: actions/setup-java@v4
+ with:
+ distribution: 'zulu' # See 'Supported distributions' for available options
+ java-version: '17'
+
+ - name: Gradle build
+ if: ${{ matrix.platform == 'android' }}
+ run: |
+ mkdir plugin/libs
+ cp ../extension/TiltFiveNDK/lib/android/TiltFiveAndroidClient.jar plugin/libs/TiltFiveAndroidClient.jar
+ chmod +x ./gradlew
+ ./gradlew build
+ working-directory: ./androidplugin
- name: Upload artifact
uses: actions/upload-artifact@v3
@@ -117,12 +157,20 @@ jobs:
cp source/CONTRIBUTORS.md plugin/addons/tiltfive
cp source/CHANGES.md plugin/addons/tiltfive
mkdir plugin/addons/tiltfive/bin
- # cp gdtiltfive.linux/*.so plugin/addons/tiltfive/bin/
- cp gdtiltfive.windows/build/bin/*.dll plugin/addons/tiltfive/bin/
- cp gdtiltfive.windows/extension/TiltFiveNDK/lib/win/x86_64/*.dll plugin/addons/tiltfive/bin/
- # cp gdtiltfive.android/*.so plugin/addons/tiltfive/bin/
- # cp gdtiltfive.ios/*.dylib plugin/addons/tiltfive/bin/
- # cp -R gdtiltfive.macos/libgdtiltfive.macos.* plugin/addons/tiltfive/bin/
+ mkdir plugin/addons/tiltfive/bin/linux
+ mkdir plugin/addons/tiltfive/bin/linux/x86_64
+ mkdir plugin/addons/tiltfive/bin/windows
+ mkdir plugin/addons/tiltfive/bin/windows/x86_64
+ mkdir plugin/addons/tiltfive/bin/android/
+ mkdir plugin/addons/tiltfive/bin/android/arm64
+ cp gdtiltfive.linux/build/bin/linux/x86_64/*.so plugin/addons/tiltfive/bin/linux/x86_64/
+ cp gdtiltfive.linux/extension/TiltFiveNDK/lib/linux/x86_64/*.so plugin/addons/tiltfive/bin/linux/x86_64/
+ cp gdtiltfive.windows/build/bin/windows/x86_64/*.dll plugin/addons/tiltfive/bin/windows/x86_64/
+ cp gdtiltfive.windows/extension/TiltFiveNDK/lib/win/x86_64/*.dll plugin/addons/tiltfive/bin/windows/x86_64/
+ cp gdtiltfive.android/build/bin/android/arm64/*.so plugin/addons/tiltfive/bin/android/arm64/
+ cp source/extension/TiltFiveNDK/lib/android/arm64-v8a/*.so plugin/addons/tiltfive/bin/android/arm64/
+ cp gdtiltfive.android/androidplugin/plugin/build/outputs/aar/gdtiltfive-debug.aar plugin/addons/tiltfive/bin/android
+ cp gdtiltfive.android/androidplugin/plugin/build/outputs/aar/gdtiltfive-release.aar plugin/addons/tiltfive/bin/android
- name: Copy files to destination for csharp
run: |
mkdir plugin_cs
@@ -132,12 +180,20 @@ jobs:
cp source/CONTRIBUTORS.md plugin_cs/addons/tiltfive
cp source/CHANGES.md plugin_cs/addons/tiltfive
mkdir plugin_cs/addons/tiltfive/bin
- # cp gdtiltfive.linux/*.so plugin_cs/addons/tiltfive/bin/
- cp gdtiltfive.windows/build/bin/*.dll plugin_cs/addons/tiltfive/bin/
- cp gdtiltfive.windows/extension/TiltFiveNDK/lib/win/x86_64/*.dll plugin_cs/addons/tiltfive/bin/
- # cp gdtiltfive.android/*.so plugin_cs/addons/tiltfive/bin/
- # cp gdtiltfive.ios/*.dylib plugin_cs/addons/tiltfive/bin/
- # cp -R gdtiltfive.macos/libgdtiltfive.macos.* plugin_cs/addons/tiltfive/bin/
+ mkdir plugin_cs/addons/tiltfive/bin/linux
+ mkdir plugin_cs/addons/tiltfive/bin/linux/x86_64
+ mkdir plugin_cs/addons/tiltfive/bin/windows
+ mkdir plugin_cs/addons/tiltfive/bin/windows/x86_64
+ mkdir plugin_cs/addons/tiltfive/bin/android/
+ mkdir plugin_cs/addons/tiltfive/bin/android/arm64
+ cp gdtiltfive.linux/build/bin/linux/x86_64/*.so plugin_cs/addons/tiltfive/bin/linux/x86_64/
+ cp gdtiltfive.linux/extension/TiltFiveNDK/lib/linux/x86_64/*.so plugin_cs/addons/tiltfive/bin/linux/x86_64/
+ cp gdtiltfive.windows/build/bin/windows/x86_64/*.dll plugin_cs/addons/tiltfive/bin/windows/x86_64/
+ cp gdtiltfive.windows/extension/TiltFiveNDK/lib/win/x86_64/*.dll plugin_cs/addons/tiltfive/bin/windows/x86_64/
+ cp gdtiltfive.android/build/bin/android/arm64/*.so plugin_cs/addons/tiltfive/bin/android/arm64/
+ cp source/extension/TiltFiveNDK/lib/android/arm64-v8a/*.so plugin_cs/addons/tiltfive/bin/android/arm64/
+ cp gdtiltfive.android/androidplugin/plugin/build/outputs/aar/gdtiltfive-debug.aar plugin_cs/addons/tiltfive/bin/android
+ cp gdtiltfive.android/androidplugin/plugin/build/outputs/aar/gdtiltfive-release.aar plugin_cs/addons/tiltfive/bin/android
- name: Calculate GIT short ref
run: |
cd source
@@ -172,4 +228,4 @@ jobs:
omitBodyDuringUpdate: true
omitPrereleaseDuringUpdate : true
token: ${{ secrets.GITHUB_TOKEN }}
- if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 51f4e69..d9e4c62 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,5 +26,12 @@ build
*.includes
*.idb
*.exp
+*.aar
+# project specific ignores
!extension/TiltFiveNDK/lib/*/*/*
+
+example.gd/android/
+example.gd/export_presets.cfg
+example.csharp/android/
+example.csharp/export_presets.cfg
diff --git a/README.md b/README.md
index fe027eb..94abedf 100644
--- a/README.md
+++ b/README.md
@@ -6,11 +6,11 @@ TiltFiveGodot4 isΒ **GDExtension**Β for the Godot 4 engine to connect to theΒ [T
| | Renderer Forward+ | Renderer Mobile | Renderer Compatibility |
| - | - | - | - |
-| Windows |β
| β
| β
|
-| Linux1 | ✓ |✓ | ✓ |
-| Android | | ❌ | |
+| Windows | β
| β
| β
|
+| Linux1 | β
|β
| β
|
+| Android1 |❌| ❌ | β
|
-1. [Experimental Version](https://github.com/patrickdown/TiltFiveGodot4/releases/tag/1.1.0-linux-experimental3)
+ 1. Experimental Support
## Usage
@@ -26,15 +26,16 @@ Please refer to this [documentation](https://patrickdown.github.io/godot/tilt-fi
### Prerequisites
-This extension requires a C++20 capable compiler.
+This extension requires a C++20 capable compiler. To build for Android you will need Java 17 and the Android SDK along with the r26c NDK.
Things you will need to know how to do.
* Use [scons](https://scons.org/)
* [Build GDExtensions](https://docs.godotengine.org/en/stable/tutorials/scripting/gdextension/gdextension_cpp_example.html)
+* Install the Android SDK and NDK (For android builds)
### Building the extension
-To build the plugin invoke `scons` from the root directory of the project. The build product will in `build\bin`. Invoking `scons example` will build the product and copy the binaries to the `example.gd\addons\tilt-five\bin` and `example.csharp\addons\tilt-five\bin` directories.
+To build the plugin invoke `scons` from the root directory of the project. The build product will in `build\bin`. Invoking `scons --assemble` will build the product and copy the binaries to the `example.gd\addons\tilt-five\bin` and `example.csharp\addons\tilt-five\bin` directories.
## Using the build products
diff --git a/SConstruct b/SConstruct
index fb8e654..07ab724 100644
--- a/SConstruct
+++ b/SConstruct
@@ -1,16 +1,56 @@
#!/usr/bin/env python
import os
import sys
+from pprint import pprint
+env = SConscript('godot-cpp/SConstruct')
+
+AddOption(
+ '--no-gradle',
+ dest='no_gradle',
+ action='store_true',
+ help='no not spawn gradle to build the android plugin')
+
+AddOption(
+ '--assemble',
+ dest='assemble_example',
+ action='store_true',
+ help='assemble the plugin files into the example project')
+
+AddOption(
+ '--gd-install-dir',
+ dest='gd_install_dir',
+ type='string',
+ nargs=1,
+ action='store',
+ metavar='DIR',
+ help='godot project directory to copy the gdscript plugin to')
+AddOption(
+ '--cs-install-dir',
+ dest='cs_install_dir',
+ type='string',
+ nargs=1,
+ action='store',
+ metavar='DIR',
+ help='godot project directory to copy the c# plugin to')
+
+gd_install_dir = GetOption('gd_install_dir')
+cs_install_dir = GetOption('cs_install_dir')
+
+assemble_example = GetOption('assemble_example') or gd_install_dir or cs_install_dir
+
+build_aar_library = not GetOption('no_gradle') and env['platform'] == 'android'
VariantDir('build/src','extension/src', duplicate=False)
VariantDir('build/T5Integration','extension/T5Integration', duplicate=False)
-env = SConscript('godot-cpp/SConstruct')
tilt_five_headers_path = 'extension/TiltFiveNDK/include'
tilt_five_library_path = 'extension/TiltFiveNDK/lib/' + { 'windows' : 'win/x86_64', 'linux' : 'linux/x86_64', 'android' : 'android/arm64-v8a'}[env["platform"]]
-tilt_five_library = {'windows' : 'TiltFiveNative.dll.if', 'linux' : 'libTiltFiveNative.so', 'android' : 'libTiltFiveNative.so'}[env["platform"]]
+tilt_five_library = {'windows' : 'TiltFiveNative.dll.if', 'linux' : 'libTiltFiveNative.so', 'android' : 'TiltFiveNative'}[env["platform"]]
+tilt_five_jar = 'extension/TiltFiveNDK/lib/android/TiltFiveAndroidClient.jar'
+
+bin_path = "{}/{}".format(env['platform'], env['arch'])
# For the reference:
# - CCFLAGS are compilation flags shared between C and C++
@@ -25,6 +65,7 @@ env.Append(CPPPATH=['extension/src/','extension/T5Integration/',tilt_five_header
sources = Glob('build/src/*.cpp')
sources += Glob('build/T5Integration/*.cpp')
+
env.Append(LIBPATH=[tilt_five_library_path])
env.Append(LIBS=[tilt_five_library])
@@ -33,36 +74,50 @@ if env['platform'] == 'windows':
env['CXXFLAGS'].remove('/std:c++17')
env.Append(CXXFLAGS=['/std:c++20'])
env.Append(CXXFLAGS=['/Zc:__cplusplus'])
- library = env.SharedLibrary(
- 'build/bin/libgdtiltfive{}{}'.format(env['suffix'], env['SHLIBSUFFIX']),
- source=sources,
- )
elif env['platform'] == 'linux':
env['t5_shared_lib'] = 'libTiltFiveNative.so'
env['CXXFLAGS'].remove('-std=c++17')
env.Append(CXXFLAGS=['-std=c++20'])
env.Append(RPATH=env.Literal('\\$$ORIGIN' ))
- library = env.SharedLibrary(
- 'build/bin/libgdtiltfive{}{}'.format(env['suffix'], env['SHLIBSUFFIX']),
- source=sources,
- )
elif env['platform'] == 'android':
- env['t5_shared_lib'] = 'libTiltFiveNative.so'
+ env['t5_shared_lib'] = 'lib{}.so'.format(tilt_five_library)
env['CXXFLAGS'].remove('-std=c++17')
env.Append(CXXFLAGS=['-std=c++20'])
- env.Append(CXXFLAGS=['-stdlib=libc++'])
- env.Append(CCFLAGS=['-fPIC'])
+ #env.Append(CPPDEFINES = ['ANDROID_CPP'])
env.Append(RPATH=env.Literal('\\$$ORIGIN' ))
- library = env.SharedLibrary(
- 'build/bin/libgdtiltfive{}{}'.format(env['suffix'], env['SHLIBSUFFIX']),
- source=sources,
- )
-f1 = env.Command('example.gd/addons/tiltfive/bin/libgdtiltfive{}{}'.format(env['suffix'], env['SHLIBSUFFIX']), library, Copy('$TARGET', '$SOURCE') )
-f2 = env.Command('example.gd/addons/tiltfive/bin/{}'.format(env['t5_shared_lib']), tilt_five_library_path + '/{}'.format(env['t5_shared_lib']), Copy('$TARGET', '$SOURCE') )
-f3 = env.Command('example.csharp/addons/tiltfive/bin/libgdtiltfive{}{}'.format(env['suffix'], env['SHLIBSUFFIX']), library, Copy('$TARGET', '$SOURCE') )
-f4 = env.Command('example.csharp/addons/tiltfive/bin/{}'.format(env['t5_shared_lib']), tilt_five_library_path + '/{}'.format(env['t5_shared_lib']), Copy('$TARGET', '$SOURCE') )
+library = env.SharedLibrary(
+ 'build/bin/{}/libgdtiltfive{}{}'.format(bin_path,env['suffix'], env['SHLIBSUFFIX']),
+ source=sources,
+)
+
+things_to_build = [library]
+
+if build_aar_library:
+ print("Building Android AAR library...")
+ Execute(Copy('androidplugin/plugin/libs/TiltFiveAndroidClient.jar', tilt_five_jar))
+ SConscript('androidplugin/SConstruct', exports="env")
+
+if assemble_example:
+ f1 = env.Command('example.gd/addons/tiltfive/bin/{}/libgdtiltfive{}{}'.format(bin_path,env['suffix'], env['SHLIBSUFFIX']), library, Copy('$TARGET', '$SOURCE') )
+ f2 = env.Command('example.gd/addons/tiltfive/bin/{}/{}'.format(bin_path,env['t5_shared_lib']), tilt_five_library_path + '/{}'.format(env['t5_shared_lib']), Copy('$TARGET', '$SOURCE') )
+ f3 = env.Command('example.csharp/addons/tiltfive/bin/{}/libgdtiltfive{}{}'.format(bin_path,env['suffix'], env['SHLIBSUFFIX']), library, Copy('$TARGET', '$SOURCE') )
+ f4 = env.Command('example.csharp/addons/tiltfive/bin/{}/{}'.format(bin_path,env['t5_shared_lib']), tilt_five_library_path + '/{}'.format(env['t5_shared_lib']), Copy('$TARGET', '$SOURCE') )
+ things_to_build += [f1, f2, f3, f4]
+ if build_aar_library:
+ f5 = env.Command('example.gd/addons/tiltfive/bin/android/gdtiltfive-debug.aar', 'androidplugin/plugin/build/outputs/aar/gdtiltfive-debug.aar', Copy('$TARGET', '$SOURCE') )
+ f6 = env.Command('example.gd/addons/tiltfive/bin/android/gdtiltfive-release.aar', 'androidplugin/plugin/build/outputs/aar/gdtiltfive-release.aar', Copy('$TARGET', '$SOURCE') )
+ f7 = env.Command('example.csharp/addons/tiltfive/bin/android/gdtiltfive-debug.aar', 'androidplugin/plugin/build/outputs/aar/gdtiltfive-debug.aar', Copy('$TARGET', '$SOURCE') )
+ f8 = env.Command('example.csharp/addons/tiltfive/bin/android/gdtiltfive-release.aar', 'androidplugin/plugin/build/outputs/aar/gdtiltfive-release.aar', Copy('$TARGET', '$SOURCE') )
+ things_to_build += [f5, f6, f7, f8]
+
+if gd_install_dir:
+ inst1 = env.Install("{}/addons".format(gd_install_dir) , "example.gd/addons/tiltfive")
+ things_to_build += [inst1]
+
+if cs_install_dir:
+ inst2 = env.Install("{}/addons".format(cs_install_dir) , "example.csharp/addons/tiltfive")
+ things_to_build += [inst2]
-env.Alias('example', [f1, f2, f3, f4])
+Default(things_to_build)
-Default(library)
diff --git a/androidplugin/.gitignore b/androidplugin/.gitignore
new file mode 100644
index 0000000..ad2d0e9
--- /dev/null
+++ b/androidplugin/.gitignore
@@ -0,0 +1,34 @@
+# Gradle files
+.gradle/
+build/
+libs/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Log/OS Files
+*.log
+
+# Android Studio generated files and folders
+captures/
+.externalNativeBuild/
+.cxx/
+*.apk
+output.json
+
+# IntelliJ
+*.iml
+.idea/
+misc.xml
+deploymentTargetDropDown.xml
+render.experimental.xml
+
+# Keystore files
+*.jks
+*.keystore
+
+# Google Services (e.g. APIs or Firebase)
+google-services.json
+
+# Android Profiling
+*.hprof
diff --git a/androidplugin/README.md b/androidplugin/README.md
new file mode 100644
index 0000000..04fd16e
--- /dev/null
+++ b/androidplugin/README.md
@@ -0,0 +1,5 @@
+# Tilt Five Godot Android ARR
+
+This is a small project that builds the Java parts that are
+required by the Tile Five client. It's only callable functions
+are used by the c++ parts of the plugin.
diff --git a/androidplugin/SConstruct b/androidplugin/SConstruct
new file mode 100644
index 0000000..c2731da
--- /dev/null
+++ b/androidplugin/SConstruct
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+import os
+import sys
+
+Import("env")
+
+def gradle_build(target, source, env):
+ os.system('gradlew build --no-daemon')
+
+android_outputs = ['plugin/build/outputs/aar/gdtiltfive-debug.aar', 'plugin/build/outputs/aar/gdtiltfive-release.aar']
+android_inputs = ['plugin/libs/TiltFiveAndroidClient.jar', 'plugin/src/main/java/org/tiltfivegodot/plugin/GodotAndroidPlugin.java']
+Default(env.Command(android_outputs, android_inputs, gradle_build))
+
diff --git a/androidplugin/build.gradle.kts b/androidplugin/build.gradle.kts
new file mode 100644
index 0000000..83658ce
--- /dev/null
+++ b/androidplugin/build.gradle.kts
@@ -0,0 +1,5 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+ id("com.android.library") version "7.4.1" apply false
+ id("org.jetbrains.kotlin.android") version "1.8.0" apply false
+}
diff --git a/androidplugin/gradle.properties b/androidplugin/gradle.properties
new file mode 100644
index 0000000..2cbd6d1
--- /dev/null
+++ b/androidplugin/gradle.properties
@@ -0,0 +1,23 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
+# Enables namespacing of each library's R class so that its R class includes only the
+# resources declared in the library itself and none from the library's dependencies,
+# thereby reducing the size of the R class for that library
+android.nonTransitiveRClass=true
diff --git a/androidplugin/gradle/wrapper/gradle-wrapper.jar b/androidplugin/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..e708b1c
Binary files /dev/null and b/androidplugin/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/androidplugin/gradle/wrapper/gradle-wrapper.properties b/androidplugin/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..0017edf
--- /dev/null
+++ b/androidplugin/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Aug 25 21:04:51 PDT 2023
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/androidplugin/gradlew b/androidplugin/gradlew
new file mode 100644
index 0000000..4f906e0
--- /dev/null
+++ b/androidplugin/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/androidplugin/gradlew.bat b/androidplugin/gradlew.bat
new file mode 100644
index 0000000..dbc0684
--- /dev/null
+++ b/androidplugin/gradlew.bat
@@ -0,0 +1,90 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+
+if exist "%JAVA_EXE%" goto execute
+echo %JAVA_HOME%
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/androidplugin/plugin/.gitignore b/androidplugin/plugin/.gitignore
new file mode 100644
index 0000000..273b322
--- /dev/null
+++ b/androidplugin/plugin/.gitignore
@@ -0,0 +1,2 @@
+/build
+/demo
\ No newline at end of file
diff --git a/androidplugin/plugin/build.gradle.kts b/androidplugin/plugin/build.gradle.kts
new file mode 100644
index 0000000..347b597
--- /dev/null
+++ b/androidplugin/plugin/build.gradle.kts
@@ -0,0 +1,44 @@
+import com.android.build.gradle.internal.tasks.factory.dependsOn
+
+plugins {
+ id("com.android.library")
+ id("org.jetbrains.kotlin.android")
+}
+
+// TODO: Update value to your plugin's name.
+val pluginName = "gdtiltfive"
+
+// TODO: Update value to match your plugin's package name.
+val pluginPackageName = "org.tiltfivegodot.plugin"
+
+android {
+ namespace = pluginPackageName
+ compileSdk = 33
+
+ buildFeatures {
+ buildConfig = true
+ }
+
+ defaultConfig {
+ minSdk = 21
+
+ manifestPlaceholders["godotPluginName"] = pluginName
+ manifestPlaceholders["godotPluginPackageName"] = pluginPackageName
+ buildConfigField("String", "GODOT_PLUGIN_NAME", "\"${pluginName}\"")
+ setProperty("archivesBaseName", pluginName)
+ }
+
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = "17"
+ }
+}
+
+dependencies {
+ implementation("org.godotengine:godot:4.2.0.stable")
+ implementation(files("libs/TiltFiveAndroidClient.jar"))
+}
+
diff --git a/androidplugin/plugin/src/main/AndroidManifest.xml b/androidplugin/plugin/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..765c0a7
--- /dev/null
+++ b/androidplugin/plugin/src/main/AndroidManifest.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/androidplugin/plugin/src/main/java/org/tiltfivegodot/plugin/GodotAndroidPlugin.java b/androidplugin/plugin/src/main/java/org/tiltfivegodot/plugin/GodotAndroidPlugin.java
new file mode 100644
index 0000000..72f977e
--- /dev/null
+++ b/androidplugin/plugin/src/main/java/org/tiltfivegodot/plugin/GodotAndroidPlugin.java
@@ -0,0 +1,41 @@
+package org.tiltfivegodot.plugin;
+
+import com.tiltfive.client.TiltFiveClient;
+import org.godotengine.godot.Godot;
+import org.godotengine.godot.plugin.GodotPlugin;
+import org.godotengine.godot.plugin.UsedByGodot;
+import android.util.Log;
+
+public class GodotAndroidPlugin extends GodotPlugin {
+
+ private TiltFiveClient tiltFiveClient;
+ private long platformContext = 0;
+
+ public GodotAndroidPlugin(Godot godot) {
+ super(godot);
+ }
+
+ @Override
+ public String getPluginName() {
+ return BuildConfig.GODOT_PLUGIN_NAME;
+ }
+
+ @Override
+ public void onGodotSetupCompleted() {
+ super.onGodotSetupCompleted();
+
+ tiltFiveClient = new TiltFiveClient(getActivity().getApplicationContext());
+ platformContext = tiltFiveClient.newPlatformContext();
+ }
+
+ @UsedByGodot
+ private String getPlatformContextString() {
+ return Long.toString(platformContext);
+ }
+
+ // Using this from gdscript will cause a crash
+ @UsedByGodot
+ private long getPlatformContext() {
+ return platformContext;
+ }
+}
\ No newline at end of file
diff --git a/androidplugin/settings.gradle.kts b/androidplugin/settings.gradle.kts
new file mode 100644
index 0000000..9debf0d
--- /dev/null
+++ b/androidplugin/settings.gradle.kts
@@ -0,0 +1,20 @@
+pluginManagement {
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ maven("https://plugins.gradle.org/m2/")
+ maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
+ }
+}
+
+// TODO: Update project's name.
+rootProject.name = "gdtiltfive"
+include(":plugin")
diff --git a/example.csharp/addons/tiltfive/T5Interface.cs b/example.csharp/addons/tiltfive/T5Interface.cs
index 30e1527..f717712 100644
--- a/example.csharp/addons/tiltfive/T5Interface.cs
+++ b/example.csharp/addons/tiltfive/T5Interface.cs
@@ -45,7 +45,38 @@ class XRRigState {
public override void _EnterTree()
{
base._EnterTree();
+ CreateXRInterface();
+ }
+
+ public override void _ExitTree()
+ {
+ DestroyXRInterface();
+ base._ExitTree();
+ }
+
+ public override void _Notification(int what)
+ {
+ if (what == NotificationApplicationPaused)
+ {
+ DestroyXRInterface();
+ }
+ else if (what == NotificationApplicationResumed)
+ {
+ CreateXRInterface();
+
+ if(!xrInterface.IsInitialized())
+ {
+ xrInterface.Initialize();
+ }
+ }
+ }
+ private void CreateXRInterface()
+ {
+ if (xrInterface != null)
+ {
+ return;
+ }
xrInterface = ClassDB.Instantiate("TiltFiveXRInterface").As();
xrInterface.Set("application_id", T5ProjectSettings.ApplicationID);
@@ -59,8 +90,12 @@ public override void _EnterTree()
xrInterface.Connect("service_event", Callable.From(_OnServiceEvent));
}
- public override void _ExitTree()
+ private void DestroyXRInterface()
{
+ if (xrInterface == null)
+ {
+ return;
+ }
xrInterface.Disconnect("service_event", Callable.From(_OnServiceEvent));
xrInterface.Disconnect("glasses_event", Callable.From(_OnGlassesEvent));
@@ -69,8 +104,8 @@ public override void _ExitTree()
xrInterface.Call("uninitialize");
}
XRServer.RemoveInterface(xrInterface as XRInterface);
-
- base._ExitTree();
+ xrInterface = null;
+ glassesDictionary.Clear();
}
public override void _Ready()
diff --git a/example.csharp/addons/tiltfive/plugin.cs b/example.csharp/addons/tiltfive/plugin.cs
index 8839ab2..2ca8d3e 100644
--- a/example.csharp/addons/tiltfive/plugin.cs
+++ b/example.csharp/addons/tiltfive/plugin.cs
@@ -1,5 +1,6 @@
#if TOOLS
using Godot;
+using Godot.Collections;
using System;
[Tool]
@@ -7,6 +8,8 @@ public partial class plugin : EditorPlugin
{
static bool isInitialized = false;
+ AndroidExportPlugin _androidExportPlugin;
+
private void Setup()
{
if (!isInitialized)
@@ -20,8 +23,15 @@ private void Setup()
public override void _EnterTree()
{
T5ProjectSettings.setup_properties();
+ _androidExportPlugin = new AndroidExportPlugin();
+ AddExportPlugin(_androidExportPlugin);
Setup();
+ }
+ public override void _ExitTree()
+ {
+ RemoveExportPlugin(_androidExportPlugin);
+ _androidExportPlugin = null;
}
public override void _EnablePlugin()
@@ -40,4 +50,32 @@ public override void _DisablePlugin()
}
}
}
+
+[Tool]
+public partial class AndroidExportPlugin : EditorExportPlugin
+{
+ static string _plugin_name = "gdtiltfive";
+
+ public override bool _SupportsPlatform(EditorExportPlatform platform) {
+ if(platform is EditorExportPlatformAndroid) {
+ return true;
+ }
+ return false;
+ }
+
+ public override string[] _GetAndroidLibraries(EditorExportPlatform platform, bool debug) {
+ if(platform is EditorExportPlatformAndroid) {
+ if(debug) {
+ return new string[] {"tiltfive/bin/android/" + _plugin_name + "-debug.aar"};
+ } else {
+ return new string[] {"tiltfive/bin/android/" + _plugin_name + "-release.aar"};
+ }
+ }
+ return null;
+ }
+
+ public override string _GetName() {
+ return _plugin_name;
+ }
+}
#endif
diff --git a/example.csharp/addons/tiltfive/tiltfive.gdextension b/example.csharp/addons/tiltfive/tiltfive.gdextension
index 96362ae..850895b 100644
--- a/example.csharp/addons/tiltfive/tiltfive.gdextension
+++ b/example.csharp/addons/tiltfive/tiltfive.gdextension
@@ -8,15 +8,32 @@ T5Gameboard = "res://addons/tiltfive/assets/board.svg"
[libraries]
-windows.x86_64.debug = "res://addons/tiltfive/bin/libgdtiltfive.windows.template_debug.x86_64.dll"
-windows.x86_64.release = "res://addons/tiltfive/bin/libgdtiltfive.windows.template_release.x86_64.dll"
+windows.x86_64.debug = "res://addons/tiltfive/bin/windows/x86_64/libgdtiltfive.windows.template_debug.x86_64.dll"
+windows.x86_64.release = "res://addons/tiltfive/bin/windows/x86_64/libgdtiltfive.windows.template_release.x86_64.dll"
+linux.x86_64.debug = "res://addons/tiltfive/bin/linux/x86_64/libgdtiltfive.linux.template_debug.x86_64.so"
+linux.x86_64.release = "res://addons/tiltfive/bin/linux/x86_64/libgdtiltfive.linux.template_release.x86_64.so"
+android.debug.arm64 = "res://addons/tiltfive/bin/android/arm64/libgdtiltfive.android.template_debug.arm64.so"
+android.release.arm64 = "res://addons/tiltfive/bin/android/arm64/libgdtiltfive.android.template_release.arm64.so"
+
[dependencies]
windows.x86_64.debug = {
- "res://addons/tiltfive/bin/TiltFiveNative.dll" : ""
+ "res://addons/tiltfive/bin/windows/x86_64/TiltFiveNative.dll" : ""
}
windows.x86_64.release = {
- "res://addons/tiltfive/bin/TiltFiveNative.dll" : ""
+ "res://addons/tiltfive/bin/windows/x86_64/TiltFiveNative.dll" : ""
+}
+linux.x86_64.debug = {
+ "res://addons/tiltfive/bin/linux/x86_64/libTiltFiveNative.so" : ""
+}
+linux.x86_64.release = {
+ "res://addons/tiltfive/bin/linux/x86_64/libTiltFiveNative.so" : ""
+}
+android.arm64.debug = {
+ "res://addons/tiltfive/bin/android/arm64/libTiltFiveNative.so" : ""
+}
+android.arm64.release = {
+ "res://addons/tiltfive/bin/android/arm64/libTiltFiveNative.so" : ""
}
diff --git a/example.gd/addons/tiltfive/T5Interface.gd b/example.gd/addons/tiltfive/T5Interface.gd
index 3f7e5df..704aa1c 100644
--- a/example.gd/addons/tiltfive/T5Interface.gd
+++ b/example.gd/addons/tiltfive/T5Interface.gd
@@ -28,6 +28,23 @@ func get_tilt_five_xr_interface() -> TiltFiveXRInterface:
return tilt_five_xr_interface
func _enter_tree():
+ process_mode = Node.PROCESS_MODE_ALWAYS
+ _create_xr_interface()
+
+func _exit_tree():
+ _destroy_xr_interface()
+
+func _notification(what):
+ match what:
+ NOTIFICATION_APPLICATION_PAUSED:
+ _destroy_xr_interface()
+ NOTIFICATION_APPLICATION_RESUMED:
+ _create_xr_interface()
+ if !tilt_five_xr_interface.is_initialized():
+ tilt_five_xr_interface.initialize()
+
+func _create_xr_interface():
+ if (tilt_five_xr_interface): return
tilt_five_xr_interface = TiltFiveXRInterface.new()
if tilt_five_xr_interface:
tilt_five_xr_interface.application_id = T5ProjectSettings.application_id
@@ -39,7 +56,7 @@ func _enter_tree():
tilt_five_xr_interface.glasses_event.connect(_on_glasses_event)
tilt_five_xr_interface.service_event.connect(_on_service_event)
-func _exit_tree():
+func _destroy_xr_interface():
if tilt_five_xr_interface:
tilt_five_xr_interface.service_event.disconnect(_on_service_event)
tilt_five_xr_interface.glasses_event.disconnect(_on_glasses_event)
@@ -48,6 +65,7 @@ func _exit_tree():
XRServer.remove_interface(tilt_five_xr_interface)
tilt_five_xr_interface = null
+ id_to_state.clear()
func _ready():
if not t5_manager:
diff --git a/example.gd/addons/tiltfive/plugin.gd b/example.gd/addons/tiltfive/plugin.gd
index 942637c..bdf8921 100644
--- a/example.gd/addons/tiltfive/plugin.gd
+++ b/example.gd/addons/tiltfive/plugin.gd
@@ -3,21 +3,43 @@ extends EditorPlugin
static var _initialized := false
+var export_plugin: AndroidExportPlugin
+
func _setup():
if not _initialized:
- #add_custom_type("T5Manager", "Node", preload("res://addons/tiltfive/T5Manager.gd"), preload("res://addons/tiltfive/assets/glasses.svg"))
add_autoload_singleton("T5Interface", "res://addons/tiltfive/T5Interface.gd")
_initialized = true
func _enter_tree():
+ export_plugin = AndroidExportPlugin.new()
+ add_export_plugin(export_plugin)
T5ProjectSettings.setup_properties()
_setup()
+func _exit_tree():
+ remove_export_plugin(export_plugin)
+ export_plugin = null
+
func _enable_plugin():
_setup()
func _disable_plugin():
if _initialized:
- #remove_custom_type("T5Manager")
remove_autoload_singleton("T5Interface")
+class AndroidExportPlugin extends EditorExportPlugin:
+ var _plugin_name = "gdtiltfive"
+
+ func _supports_platform(platform):
+ if platform is EditorExportPlatformAndroid:
+ return true
+ return false
+
+ func _get_android_libraries(platform, debug):
+ if debug:
+ return PackedStringArray(["tiltfive/bin/android/" + _plugin_name + "-debug.aar"])
+ else:
+ return PackedStringArray(["tiltfive/bin/android/" + _plugin_name + "-release.aar"])
+
+ func _get_name():
+ return _plugin_name
diff --git a/example.gd/addons/tiltfive/tiltfive.gdextension b/example.gd/addons/tiltfive/tiltfive.gdextension
index aa4e9e7..850895b 100644
--- a/example.gd/addons/tiltfive/tiltfive.gdextension
+++ b/example.gd/addons/tiltfive/tiltfive.gdextension
@@ -8,24 +8,32 @@ T5Gameboard = "res://addons/tiltfive/assets/board.svg"
[libraries]
-windows.x86_64.debug = "res://addons/tiltfive/bin/libgdtiltfive.windows.template_debug.x86_64.dll"
-windows.x86_64.release = "res://addons/tiltfive/bin/libgdtiltfive.windows.template_release.x86_64.dll"
-linux.x86_64.debug = "res://addons/tiltfive/bin/libgdtiltfive.linux.template_debug.x86_64.so"
-linux.x86_64.release = "res://addons/tiltfive/bin/libgdtiltfive.linux.template_release.x86_64.so"
+windows.x86_64.debug = "res://addons/tiltfive/bin/windows/x86_64/libgdtiltfive.windows.template_debug.x86_64.dll"
+windows.x86_64.release = "res://addons/tiltfive/bin/windows/x86_64/libgdtiltfive.windows.template_release.x86_64.dll"
+linux.x86_64.debug = "res://addons/tiltfive/bin/linux/x86_64/libgdtiltfive.linux.template_debug.x86_64.so"
+linux.x86_64.release = "res://addons/tiltfive/bin/linux/x86_64/libgdtiltfive.linux.template_release.x86_64.so"
+android.debug.arm64 = "res://addons/tiltfive/bin/android/arm64/libgdtiltfive.android.template_debug.arm64.so"
+android.release.arm64 = "res://addons/tiltfive/bin/android/arm64/libgdtiltfive.android.template_release.arm64.so"
[dependencies]
windows.x86_64.debug = {
- "res://addons/tiltfive/bin/TiltFiveNative.dll" : ""
+ "res://addons/tiltfive/bin/windows/x86_64/TiltFiveNative.dll" : ""
}
windows.x86_64.release = {
- "res://addons/tiltfive/bin/TiltFiveNative.dll" : ""
+ "res://addons/tiltfive/bin/windows/x86_64/TiltFiveNative.dll" : ""
}
linux.x86_64.debug = {
- "res://addons/tiltfive/bin/libTiltFiveNative.so" : ""
+ "res://addons/tiltfive/bin/linux/x86_64/libTiltFiveNative.so" : ""
}
linux.x86_64.release = {
- "res://addons/tiltfive/bin/libTiltFiveNative.so" : ""
+ "res://addons/tiltfive/bin/linux/x86_64/libTiltFiveNative.so" : ""
+}
+android.arm64.debug = {
+ "res://addons/tiltfive/bin/android/arm64/libTiltFiveNative.so" : ""
+}
+android.arm64.release = {
+ "res://addons/tiltfive/bin/android/arm64/libTiltFiveNative.so" : ""
}
diff --git a/extension/T5Integration/T5Service.cpp b/extension/T5Integration/T5Service.cpp
index 2cb8874..4045794 100644
--- a/extension/T5Integration/T5Service.cpp
+++ b/extension/T5Integration/T5Service.cpp
@@ -20,7 +20,7 @@ T5Service::~T5Service() {
stop_service();
}
-bool T5Service::start_service(const std::string_view application_id, std::string_view application_version, uint8_t sdk_type) {
+bool T5Service::start_service(const std::string_view application_id, std::string_view application_version, uint8_t sdk_type, void* platform_context) {
if (_state.is_current(T5ServiceState::RUNNING))
return true;
if (_state.set_and_was_toggled(T5ServiceState::STARTING)) {
@@ -34,7 +34,7 @@ bool T5Service::start_service(const std::string_view application_id, std::string
clientInfo.applicationVersion = application_version.data();
clientInfo.sdkType = sdk_type;
- auto result = t5CreateContext(&_context, &clientInfo, nullptr);
+ auto result = t5CreateContext(&_context, &clientInfo, platform_context);
if (result != T5_SUCCESS) {
LOG_T5_ERROR(result);
diff --git a/extension/T5Integration/T5Service.h b/extension/T5Integration/T5Service.h
index e570d88..84c3a58 100644
--- a/extension/T5Integration/T5Service.h
+++ b/extension/T5Integration/T5Service.h
@@ -59,7 +59,7 @@ class T5Service {
T5Service();
virtual ~T5Service();
- bool start_service(const std::string_view applicationID, std::string_view applicationVersion, uint8_t sdk_type = 0);
+ bool start_service(const std::string_view applicationID, std::string_view applicationVersion, uint8_t sdk_type = 0, void* platform_context = nullptr);
void stop_service();
bool is_service_started();
diff --git a/extension/T5Integration/Wand.cpp b/extension/T5Integration/Wand.cpp
index 343c1aa..05f470d 100644
--- a/extension/T5Integration/Wand.cpp
+++ b/extension/T5Integration/Wand.cpp
@@ -75,7 +75,7 @@ bool WandService::start(T5_Glasses handle) {
_glasses_handle = handle;
_last_wand_error = T5_SUCCESS;
_running = true;
- _thread = std::jthread([this](std::stop_token s_token) { monitor_wands(s_token); });
+ _thread = jthrd::jthread([this](jthrd::stop_token s_token) { monitor_wands(s_token); });
return _running;
}
@@ -122,7 +122,7 @@ T5_Result WandService::get_last_error() {
return tmp;
}
-void WandService::monitor_wands(std::stop_token s_token) {
+void WandService::monitor_wands(jthrd::stop_token s_token) {
if (!configure_wand_tracking(true))
return;
diff --git a/extension/T5Integration/Wand.h b/extension/T5Integration/Wand.h
index dc59afd..a3e773a 100644
--- a/extension/T5Integration/Wand.h
+++ b/extension/T5Integration/Wand.h
@@ -1,9 +1,12 @@
#pragma once
#include
#include
+#include
#include
#include
+#include
+
using namespace std::chrono_literals;
namespace T5Integration {
@@ -66,12 +69,12 @@ class WandService {
private:
bool configure_wand_tracking(bool enable);
- void monitor_wands(std::stop_token s_token);
+ void monitor_wands(jthrd::stop_token s_token);
T5_Glasses _glasses_handle;
WandList _wand_list;
- std::jthread _thread;
+ jthrd::jthread _thread;
std::mutex _list_access;
std::atomic_bool _running;
diff --git a/extension/T5Integration/jthread.cpp b/extension/T5Integration/jthread.cpp
new file mode 100644
index 0000000..712c44f
--- /dev/null
+++ b/extension/T5Integration/jthread.cpp
@@ -0,0 +1,169 @@
+#include "jthread.h"
+
+#ifndef __cpp_lib_jthread
+#include
+#include
+#include
+#include
+
+namespace jthrd {
+struct StopState {
+ std::atomic request_stop = false;
+
+ // this is not efficient, but it only needs to be correct
+ std::mutex callbacks_mutex;
+ std::vector callbacks;
+
+ void add_callback(stop_callback* callback) {
+ auto lk = std::unique_lock(callbacks_mutex);
+ if (!request_stop) {
+ callbacks.push_back(callback);
+ } else {
+ callback->callback();
+ }
+ }
+
+ void remove_callback(stop_callback* callback) {
+ auto lk = std::unique_lock(callbacks_mutex);
+ auto i = std::find(begin(callbacks), end(callbacks), callback);
+ if (i != end(callbacks)) {
+ callbacks.erase(i);
+ }
+ }
+
+ void exec_callbacks() {
+ auto lk = std::unique_lock(callbacks_mutex);
+ for (const auto& cb : callbacks) {
+ assert(cb->callback);
+ cb->callback();
+ }
+ callbacks.clear();
+ }
+};
+
+stop_token::stop_token() = default;
+
+stop_token::stop_token(std::shared_ptr s) :
+ state(s) {}
+
+stop_token::stop_token(const stop_token& other) noexcept = default;
+stop_token::stop_token(stop_token&& other) noexcept = default;
+stop_token::~stop_token() = default;
+
+stop_token& stop_token::operator=(const stop_token& other) noexcept = default;
+stop_token& stop_token::operator=(stop_token&& other) noexcept = default;
+
+bool stop_token::stop_requested() noexcept {
+ if (state) {
+ return state->request_stop;
+ }
+ return false;
+}
+
+bool stop_token::stop_possible() const noexcept {
+ return static_cast(state);
+}
+
+void stop_token::swap(stop_token& other) noexcept {
+ state.swap(other.state);
+}
+
+stop_source::stop_source() :
+ state(std::make_shared()) {}
+
+stop_source::stop_source(nostopstate_t nss) noexcept {}
+
+stop_source::stop_source(const stop_source& other) noexcept = default;
+stop_source::stop_source(stop_source&& other) noexcept = default;
+stop_source::~stop_source() = default;
+
+stop_source& stop_source::operator=(const stop_source& other) noexcept = default;
+stop_source& stop_source::operator=(stop_source&& other) noexcept = default;
+
+stop_token stop_source::get_token() const noexcept {
+ return stop_token{ state };
+}
+
+bool stop_source::request_stop() noexcept {
+ if (state && (state->request_stop.exchange(true) == false)) {
+ state->exec_callbacks();
+ return true;
+ }
+ return false;
+}
+
+bool stop_source::stop_possible() const noexcept {
+ return static_cast(state);
+}
+
+void stop_source::swap(stop_source& other) noexcept {
+ state.swap(other.state);
+}
+
+stop_callback::~stop_callback() {
+ if (token.state) {
+ token.state->remove_callback(this);
+ }
+}
+
+void stop_callback::self_register() {
+ if (token.state) {
+ token.state->add_callback(this);
+ } else {
+ callback();
+ }
+}
+
+jthread::jthread() noexcept
+ :
+ stop{ nostopstate } {}
+
+jthread::jthread(jthread&& other) noexcept = default;
+
+jthread::~jthread() {
+ if (joinable()) {
+ request_stop();
+ join();
+ }
+}
+
+jthread& jthread::operator=(jthread&& other) noexcept = default;
+
+jthread::id jthread::get_id() const noexcept {
+ return impl.get_id();
+}
+
+bool jthread::joinable() const noexcept {
+ return impl.joinable();
+}
+
+void jthread::join() {
+ impl.join();
+}
+
+void jthread::detach() {
+ impl.detach();
+}
+
+stop_source jthread::get_stop_source() noexcept {
+ if (joinable()) {
+ return stop;
+ } else {
+ return stop_source{ nostopstate };
+ }
+}
+
+stop_token jthread::get_stop_token() noexcept {
+ return get_stop_source().get_token();
+}
+
+bool jthread::request_stop() noexcept {
+ return stop.request_stop();
+}
+
+void jthread::swap(jthread& other) noexcept {
+ stop.swap(other.stop);
+ impl.swap(other.impl);
+}
+} //namespace jthrd
+#endif
\ No newline at end of file
diff --git a/extension/T5Integration/jthread.h b/extension/T5Integration/jthread.h
new file mode 100644
index 0000000..219b780
--- /dev/null
+++ b/extension/T5Integration/jthread.h
@@ -0,0 +1,158 @@
+/* This provides a drop in replacement for std::jthread, std::stop_token,
+ * std::stop_source, and std::stop_callback for compilers that do not yet
+ * support them. This was pulled from a reference implementation of the
+ * jthread proposal
+ */
+#ifndef _JTHREAD_H_
+#define _JTHREAD_H_
+
+#include
+#include
+#include
+
+namespace jthrd {
+#ifdef __cpp_lib_jthread
+// If jthread is available, pull it into this namespace
+using std::jthread;
+using std::nostopstate;
+using std::stop_callback;
+using std::stop_source;
+using std::stop_token;
+#else
+// otherwise, implement a drop in replacement in this namespace
+struct StopState;
+
+struct nostopstate_t {};
+constexpr auto nostopstate = nostopstate_t{};
+
+class stop_token {
+public:
+ stop_token();
+ explicit stop_token(std::shared_ptr state);
+ stop_token(const stop_token& other) noexcept;
+ stop_token(stop_token&& other) noexcept;
+ ~stop_token();
+
+ stop_token& operator=(const stop_token& other) noexcept;
+ stop_token& operator=(stop_token&& other) noexcept;
+
+ [[nodiscard]] bool stop_requested() noexcept;
+ [[nodiscard]] bool stop_possible() const noexcept;
+
+ void swap(stop_token& other) noexcept;
+
+private:
+ std::shared_ptr state;
+
+ friend class stop_callback;
+};
+
+inline void swap(stop_token& lhs, stop_token& rhs) noexcept {
+ lhs.swap(rhs);
+}
+
+class stop_source {
+public:
+ stop_source();
+ explicit stop_source(nostopstate_t nss) noexcept;
+ stop_source(const stop_source& other) noexcept;
+ stop_source(stop_source&& other) noexcept;
+ ~stop_source();
+
+ stop_source& operator=(const stop_source& other) noexcept;
+ stop_source& operator=(stop_source&& other) noexcept;
+
+ [[nodiscard]] stop_token get_token() const noexcept;
+
+ bool request_stop() noexcept;
+ [[nodiscard]] bool stop_possible() const noexcept;
+
+ void swap(stop_source& other) noexcept;
+
+private:
+ std::shared_ptr state;
+};
+
+inline void swap(stop_source& lhs, stop_source& rhs) noexcept {
+ lhs.swap(rhs);
+}
+
+class stop_callback {
+public:
+ template
+ explicit stop_callback(const stop_token& st, C&& cb) :
+ token(st), callback(cb) {
+ self_register();
+ }
+
+ template
+ explicit stop_callback(stop_token&& st, C&& cb) :
+ token(std::forward(st)), callback(cb) {
+ self_register();
+ }
+
+ ~stop_callback();
+
+private:
+ stop_token token;
+ std::function callback;
+
+ void self_register();
+
+ stop_callback(const stop_callback&) = delete;
+ stop_callback(stop_callback&&) = delete;
+ stop_callback& operator=(const stop_callback& other) noexcept = delete;
+ stop_callback& operator=(stop_callback&& other) noexcept = delete;
+
+ friend struct StopState;
+};
+
+class jthread {
+public:
+ using id = std::thread::id;
+
+ jthread() noexcept;
+ jthread(jthread&& other) noexcept;
+
+ template
+ requires std::is_invocable_v, std::decay_t...>
+ explicit jthread(Function&& f, Args&&... args) :
+ impl(std::forward(f), std::forward(args)...) {}
+
+ template
+ requires std::is_invocable_v, stop_token, std::decay_t...>
+ explicit jthread(Function&& f, Args&&... args) :
+ stop(),
+ impl(std::forward(f), stop.get_token(), std::forward(args)...) {}
+
+ ~jthread();
+
+ jthread& operator=(jthread&& other) noexcept;
+
+ [[nodiscard]] id get_id() const noexcept;
+ [[nodiscard]] bool joinable() const noexcept;
+
+ void join();
+ void detach();
+
+ [[nodiscard]] stop_source get_stop_source() noexcept;
+ [[nodiscard]] stop_token get_stop_token() noexcept;
+ bool request_stop() noexcept;
+
+ void swap(jthread& other) noexcept;
+
+private:
+ stop_source stop = {};
+ std::thread impl;
+
+ jthread(const jthread&) = delete;
+ jthread& operator=(const jthread& other) noexcept = delete;
+};
+
+inline void swap(jthread& lhs, jthread& rhs) noexcept {
+ lhs.swap(rhs);
+}
+#endif
+} //namespace jthrd
+
+#endif //_JTHREAD_H_
\ No newline at end of file
diff --git a/extension/src/TiltFiveXRInterface.cpp b/extension/src/TiltFiveXRInterface.cpp
index f40d36b..5a7e523 100644
--- a/extension/src/TiltFiveXRInterface.cpp
+++ b/extension/src/TiltFiveXRInterface.cpp
@@ -1,4 +1,5 @@
#include "TiltFiveXRInterface.h"
+#include
#include
#include
#include
@@ -139,6 +140,23 @@ TiltFiveXRInterface::GlassesIndexEntry* TiltFiveXRInterface::lookup_glasses_by_v
return nullptr;
}
+bool TiltFiveXRInterface::setup_android() {
+ if (OS::get_singleton()->get_name() == "Android") {
+ if (Engine::get_singleton()->has_singleton("gdtiltfive")) {
+ auto gdtiltfive = Engine::get_singleton()->get_singleton("gdtiltfive");
+ String pc_string = gdtiltfive->call("getPlatformContextString");
+ _platform_context = pc_string.to_int();
+ LOG_MESSAGE("Platform context: ", _platform_context);
+ } else {
+ LOG_ERROR("gdtiltfive plugin was not found and is required for Tilt Five to work on Android");
+ return false;
+ }
+ } else {
+ _platform_context = 0;
+ }
+ return true;
+}
+
bool TiltFiveXRInterface::_is_initialized() const {
return _initialised;
}
@@ -155,6 +173,8 @@ bool TiltFiveXRInterface::_initialize() {
t5_service = GodotT5ObjectRegistry::service();
ERR_FAIL_COND_V_MSG(!t5_service, false, "Couldn't obtain GodotT5Service singleton");
+ ERR_FAIL_COND_V_MSG(!setup_android(), false, "Couldn't setup Android platform context");
+
RenderingServer* rendering_server = RenderingServer::get_singleton();
ERR_FAIL_NULL_V(rendering_server, false);
RenderingDevice* rendering_device = rendering_server->get_rendering_device();
@@ -167,7 +187,11 @@ bool TiltFiveXRInterface::_initialize() {
auto ai = application_id.ascii();
auto av = application_version.ascii();
- bool is_started = t5_service->start_service(ai.get_data(), av.get_data(), kSdkTypeCommunityGodot);
+ // I don't like this but long is how it is returned from the T5 Java API.
+ auto platform_context = reinterpret_cast(_platform_context);
+ LOG_MESSAGE("Platform context: ", _platform_context);
+
+ bool is_started = t5_service->start_service(ai.get_data(), av.get_data(), kSdkTypeCommunityGodot, platform_context);
ERR_FAIL_COND_V_MSG(!is_started, false, "Couldn't start T5 Service");
_initialised = true;
diff --git a/extension/src/TiltFiveXRInterface.h b/extension/src/TiltFiveXRInterface.h
index 98b9ef8..ad03d42 100644
--- a/extension/src/TiltFiveXRInterface.h
+++ b/extension/src/TiltFiveXRInterface.h
@@ -146,6 +146,8 @@ class TiltFiveXRInterface : public XRInterfaceExtension {
~TiltFiveXRInterface();
protected:
+ bool setup_android();
+
static void _bind_methods();
void _start_display(GlassesIndexEntry &entry, SubViewport *viewport, T5Origin3D *xr_origin);
@@ -166,6 +168,7 @@ class TiltFiveXRInterface : public XRInterfaceExtension {
String application_version;
float _trigger_click_threshold = 0.5;
bool _is_debug_logging = false;
+ long _platform_context = 0;
std::vector _glasses_index;
std::vector _glasses_events;