From bb5fb4c01086ebe8159a60843de1566dff0cf73e Mon Sep 17 00:00:00 2001 From: Cengiz Date: Thu, 23 Apr 2026 17:28:46 +0600 Subject: [PATCH] Fixed frame rotation on iOS --- .github/ISSUE_TEMPLATE/bug_report.yaml | 4 +- .github/ISSUE_TEMPLATE/feature_request.yaml | 4 +- addon/addon-build.gradle.kts | 7 + android/android-build.gradle.kts | 19 ++ .../{build.gradle.kts => logic.gradle.kts} | 11 +- common/build-logic/settings.gradle.kts | 1 + .../src/main/{kotlin => java}/BuildConfig.kt | 0 .../src/main/{kotlin => java}/GodotConfig.kt | 0 .../src/main/{kotlin => java}/IosConfig.kt | 9 + .../src/main/{kotlin => java}/PluginConfig.kt | 0 .../{kotlin => java}/ProjectExtensions.kt | 0 .../src/main/java/SpmDependency.kt | 29 +++ .../base-conventions.gradle.kts | 1 + .../src/main/kotlin/SpmDependency.kt | 12 - docs/CONTRIBUTING.md | 212 +++++++++--------- docs/README.md | 33 ++- ios/config/ios.properties | 1 + ios/ios-build.gradle.kts | 14 +- ios/plugin.xcodeproj/project.pbxproj | 16 +- ios/src/NativeCamera.swift | 24 +- 20 files changed, 236 insertions(+), 161 deletions(-) rename common/build-logic/{build.gradle.kts => logic.gradle.kts} (76%) rename common/build-logic/src/main/{kotlin => java}/BuildConfig.kt (100%) rename common/build-logic/src/main/{kotlin => java}/GodotConfig.kt (100%) rename common/build-logic/src/main/{kotlin => java}/IosConfig.kt (94%) rename common/build-logic/src/main/{kotlin => java}/PluginConfig.kt (100%) rename common/build-logic/src/main/{kotlin => java}/ProjectExtensions.kt (100%) create mode 100644 common/build-logic/src/main/java/SpmDependency.kt rename common/build-logic/src/main/{kotlin => java}/base-conventions.gradle.kts (98%) delete mode 100644 common/build-logic/src/main/kotlin/SpmDependency.kt diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index c4ffcdb..d617334 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -78,10 +78,10 @@ body: label: Plugin Version description: What version of the plugin are you running? options: - - "1.0" - "1.1" + - "1.0" - Other - default: 1 + default: 0 validations: required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml index a8ae94a..1871540 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -40,10 +40,10 @@ body: label: Plugin Version description: What version of the plugin are you running? options: - - "1.0" - "1.1" + - "1.0" - Other - default: 1 + default: 0 validations: required: true - type: textarea diff --git a/addon/addon-build.gradle.kts b/addon/addon-build.gradle.kts index c318aa7..7a8f12b 100644 --- a/addon/addon-build.gradle.kts +++ b/addon/addon-build.gradle.kts @@ -152,6 +152,9 @@ tasks { @Suppress("UNCHECKED_CAST") val iosLinkerFlags = extra["iosLinkerFlags"] as List + @Suppress("UNCHECKED_CAST") + val iosBundleFiles = extra["iosBundleFiles"] as List + @Suppress("UNCHECKED_CAST") val iosSpmDependencies = extra["iosSpmDependencies"] as List @@ -209,6 +212,7 @@ tasks { put("iosFrameworks", iosFrameworks.toQuotedString()) put("iosEmbeddedFrameworks", iosEmbeddedFrameworks.toQuotedString()) put("iosLinkerFlags", iosLinkerFlags.toQuotedString()) + put("iosBundleFiles", iosBundleFiles.toQuotedString()) put("spmDependencies", iosSpmDependencies.toGdscriptFormat()) } @@ -239,6 +243,7 @@ tasks { inputs.property("iosFrameworks", iosFrameworks.joinToString()) inputs.property("iosEmbeddedFrameworks", iosEmbeddedFrameworks.joinToString()) inputs.property("iosLinkerFlags", iosLinkerFlags.joinToString()) + inputs.property("iosBundleFiles", iosBundleFiles.joinToString()) inputs.property("iosSpmDependencies", iosSpmDependencies.joinToString()) outputs.dir("$outputDir/addons/GMPShared") @@ -273,6 +278,7 @@ tasks { put("iosFrameworks", iosFrameworks.toQuotedString()) put("iosEmbeddedFrameworks", iosEmbeddedFrameworks.toQuotedString()) put("iosLinkerFlags", iosLinkerFlags.toQuotedString()) + put("iosBundleFiles", iosBundleFiles.toQuotedString()) put("spmDependencies", iosSpmDependencies.toGdscriptFormat()) } @@ -303,6 +309,7 @@ tasks { inputs.property("iosFrameworks", iosFrameworks.joinToString()) inputs.property("iosEmbeddedFrameworks", iosEmbeddedFrameworks.joinToString()) inputs.property("iosLinkerFlags", iosLinkerFlags.joinToString()) + inputs.property("iosBundleFiles", iosBundleFiles.joinToString()) inputs.property("iosSpmDependencies", iosSpmDependencies.joinToString()) outputs.dir("$outputDir/addons/${pluginConfig.pluginName}") diff --git a/android/android-build.gradle.kts b/android/android-build.gradle.kts index 653b7cf..d0af75f 100644 --- a/android/android-build.gradle.kts +++ b/android/android-build.gradle.kts @@ -336,12 +336,31 @@ val testRuntimeOnlyDependencies = .map { findLibrary(it).get().get() } } +val artifactType = Attribute.of("artifactType", String::class.java) + dependencies { "rewrite"(libs.rewrite.static.analysis) implementation("godot:godot-lib:${godotConfig.godotVersion}.${godotConfig.godotReleaseType}@aar") androidDependencies.forEach { implementation(it) } testDependencies.forEach { testImplementation(it) } testRuntimeOnlyDependencies.forEach { testRuntimeOnly(it) } + + attributesSchema { + attribute(artifactType) { + disambiguationRules.add(JarFirstRule::class.java) + } + } +} + +// Helper class to prioritize JARs when multiple variants match +abstract class JarFirstRule : AttributeDisambiguationRule { + override fun execute(details: MultipleCandidatesDetails) { + if (details.candidateValues.contains("jar")) { + details.closestMatch("jar") + } else if (details.candidateValues.contains("android-classes-jar")) { + details.closestMatch("android-classes-jar") + } + } } // -- Helpers ------------------------------------------------------------------- diff --git a/common/build-logic/build.gradle.kts b/common/build-logic/logic.gradle.kts similarity index 76% rename from common/build-logic/build.gradle.kts rename to common/build-logic/logic.gradle.kts index 9e01622..d464869 100644 --- a/common/build-logic/build.gradle.kts +++ b/common/build-logic/logic.gradle.kts @@ -3,7 +3,7 @@ // // Compiles all convention plugins (precompiled script plugins) in -// src/main/kotlin/*.gradle.kts and makes them - together with their +// src/main/java/*.gradle.kts and makes them - together with their // runtime dependencies - available to every subproject that applies them. // // Versions are kept in sync with gradle/libs.versions.toml via the @@ -26,3 +26,12 @@ sourceSets { java.srcDirs("src/main/kotlin") } } + +kotlin { + jvmToolchain(17) +} + +tasks.withType().configureEach { + targetCompatibility = "17" + sourceCompatibility = "17" +} diff --git a/common/build-logic/settings.gradle.kts b/common/build-logic/settings.gradle.kts index 68a0842..94547d1 100644 --- a/common/build-logic/settings.gradle.kts +++ b/common/build-logic/settings.gradle.kts @@ -20,3 +20,4 @@ dependencyResolutionManagement { } rootProject.name = "build-logic" +rootProject.buildFileName = "logic.gradle.kts" diff --git a/common/build-logic/src/main/kotlin/BuildConfig.kt b/common/build-logic/src/main/java/BuildConfig.kt similarity index 100% rename from common/build-logic/src/main/kotlin/BuildConfig.kt rename to common/build-logic/src/main/java/BuildConfig.kt diff --git a/common/build-logic/src/main/kotlin/GodotConfig.kt b/common/build-logic/src/main/java/GodotConfig.kt similarity index 100% rename from common/build-logic/src/main/kotlin/GodotConfig.kt rename to common/build-logic/src/main/java/GodotConfig.kt diff --git a/common/build-logic/src/main/kotlin/IosConfig.kt b/common/build-logic/src/main/java/IosConfig.kt similarity index 94% rename from common/build-logic/src/main/kotlin/IosConfig.kt rename to common/build-logic/src/main/java/IosConfig.kt index cd67d35..faabb1c 100644 --- a/common/build-logic/src/main/kotlin/IosConfig.kt +++ b/common/build-logic/src/main/java/IosConfig.kt @@ -39,6 +39,7 @@ import kotlinx.serialization.decodeFromString * | `frameworks` | [frameworks] | System framework names to link, e.g. `["Foundation.framework"]` | * | `embedded_frameworks` | [embeddedFrameworks] | Frameworks to embed in the app bundle (may be empty) | * | `flags` | [linkerFlags] | Extra linker flags, e.g. `["-ObjC"]` | + * | `bundle_files` | [bundleFiles] | Files to include in the app bundle, e.g. `["res://afile.task"]` | * * Comma-separated properties (`frameworks`, `embedded_frameworks`, `flags`) are * split into [List]s at load time - blank entries are dropped - so consumers never @@ -91,6 +92,13 @@ data class IosConfig( * Empty when no extra flags are required. */ val linkerFlags: List, + /** + * Files to include in the app bundle. + * + * Parsed from the comma-separated `bundle_files` key in `ios.properties`. + * Empty when no extra files are required. + */ + val bundleFiles: List, /** * Swift Package Manager dependencies decoded from `ios/config/spm_dependencies.json`. * @@ -155,6 +163,7 @@ data class IosConfig( frameworks = props.splitList("frameworks"), embeddedFrameworks = props.splitList("embedded_frameworks"), linkerFlags = props.splitList("flags"), + bundleFiles = props.splitList("bundle_files"), spmDependencies = spmDependencies, testPlatform = props.require("test_platform"), testDestinationName = props.require("test_destination_name"), diff --git a/common/build-logic/src/main/kotlin/PluginConfig.kt b/common/build-logic/src/main/java/PluginConfig.kt similarity index 100% rename from common/build-logic/src/main/kotlin/PluginConfig.kt rename to common/build-logic/src/main/java/PluginConfig.kt diff --git a/common/build-logic/src/main/kotlin/ProjectExtensions.kt b/common/build-logic/src/main/java/ProjectExtensions.kt similarity index 100% rename from common/build-logic/src/main/kotlin/ProjectExtensions.kt rename to common/build-logic/src/main/java/ProjectExtensions.kt diff --git a/common/build-logic/src/main/java/SpmDependency.kt b/common/build-logic/src/main/java/SpmDependency.kt new file mode 100644 index 0000000..fc51c4a --- /dev/null +++ b/common/build-logic/src/main/java/SpmDependency.kt @@ -0,0 +1,29 @@ +// +// © 2026-present https://github.com/cengiz-pz +// + +import kotlinx.serialization.Serializable + +/** + * Represents a single Swift Package Manager dependency entry decoded from + * `ios/config/spm_dependencies.json`. + * + * JSON shape: + * ```json + * { + * "url": "https://github.com/owner/repo", + * "version": "1.2.3", + * "products": ["ProductOne", "ProductTwo"] + * } + * ``` + * + * @property url Git repository URL of the Swift package. + * @property version Minimum version (passed to `spm_manager.rb` as the package requirement). + * @property products List of SPM product names to link against. + */ +@Serializable +data class SpmDependency( + val url: String, + val version: String, + val products: List, +) diff --git a/common/build-logic/src/main/kotlin/base-conventions.gradle.kts b/common/build-logic/src/main/java/base-conventions.gradle.kts similarity index 98% rename from common/build-logic/src/main/kotlin/base-conventions.gradle.kts rename to common/build-logic/src/main/java/base-conventions.gradle.kts index fc09821..8de7c6f 100644 --- a/common/build-logic/src/main/kotlin/base-conventions.gradle.kts +++ b/common/build-logic/src/main/java/base-conventions.gradle.kts @@ -63,6 +63,7 @@ project.extra["iosSwiftVersion"] = iosConfig.swiftVersion project.extra["iosFrameworks"] = iosConfig.frameworks // List project.extra["iosEmbeddedFrameworks"] = iosConfig.embeddedFrameworks // List project.extra["iosLinkerFlags"] = iosConfig.linkerFlags // List +project.extra["iosBundleFiles"] = iosConfig.bundleFiles // List project.extra["iosSpmDependencies"] = iosConfig.spmDependencies // List // -- Shared directory layout (replaces common.gradle.kts) --------------------- diff --git a/common/build-logic/src/main/kotlin/SpmDependency.kt b/common/build-logic/src/main/kotlin/SpmDependency.kt deleted file mode 100644 index 9e11d5b..0000000 --- a/common/build-logic/src/main/kotlin/SpmDependency.kt +++ /dev/null @@ -1,12 +0,0 @@ -// -// © 2026-present https://github.com/cengiz-pz -// - -import kotlinx.serialization.Serializable - -@Serializable -data class SpmDependency( - val url: String, - val version: String, - val products: List, -) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index e7a6e8e..c2024a8 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -28,104 +28,104 @@ Thank you for your interest in contributing to the Godot NativeCamera Plugin! Th ```text . -├── addon/ # GDScript interface module -│ ├── addon-build.gradle.kts # Gradle build configuration for addon module -│ ├── ?.gradle.kts # Any extra addon-specific Gradle configuration (configured in +├-- addon/ # GDScript interface module +│ ├-- addon-build.gradle.kts # Gradle build configuration for addon module +│ ├-- ?.gradle.kts # Any extra addon-specific Gradle configuration (configured in │ │ # addon/config/addon-build.properties) for the plugin goes here -│ ├── build/ -│ │ └── output/ # Generated GDScript code +│ ├-- build/ +│ │ └-- output/ # Generated GDScript code │ │ -│ ├── config/ -│ │ └── addon-build.properties # Gradle build customization for addon module +│ ├-- config/ +│ │ └-- addon-build.properties # Gradle build customization for addon module │ │ -│ └── src/ -│ ├── main # Main GDScript templates -│ └── shared # GDScript templates in common with other plugins, if any +│ └-- src/ +│ ├-- main # Main GDScript templates +│ └-- shared # GDScript templates in common with other plugins, if any │ -├── android/ # Android platform module -│ ├── android-build.gradle.kts # Android build configuration -│ ├── ?.gradle.kts # Any extra Android-specific Gradle configuration (configured in +├-- android/ # Android platform module +│ ├-- android-build.gradle.kts # Android build configuration +│ ├-- ?.gradle.kts # Any extra Android-specific Gradle configuration (configured in │ │ # android/config/android-build.properties) for the plugin goes here │ │ -│ ├── build/ -│ │ └── outputs/ # Generated Android AAR files +│ ├-- build/ +│ │ └-- outputs/ # Generated Android AAR files │ │ -│ ├── config/ -│ │ └── android-build.properties # Gradle build customization for android module +│ ├-- config/ +│ │ └-- android-build.properties # Gradle build customization for android module │ │ -│ ├── libs/ # Godot library for Android (default location; configurable via local.properties) -│ └── src/ -│ ├── main # Android source code -│ └── test # Android test code +│ ├-- libs/ # Godot library for Android (default location; configurable via local.properties) +│ └-- src/ +│ ├-- main # Android source code +│ └-- test # Android test code │ -├── common/ # Gradle root - shared build configuration -│ ├── build.gradle.kts # Root build configuration -│ ├── ?.gradle.kts # Any extra Gradle configuration (configured in +├-- common/ # Gradle root - shared build configuration +│ ├-- build.gradle.kts # Root build configuration +│ ├-- ?.gradle.kts # Any extra Gradle configuration (configured in │ │ # common/config/build.properties) for the plugin goes here │ │ -│ ├── gradle.properties # Gradle properties -│ ├── local.properties # Local machine config (gitignored) -│ ├── settings.gradle.kts # Gradle settings -│ ├── build/ -│ │ ├── archive/ # Generated archives -│ │ ├── plugin/ # Built plugin files -│ │ └── reports/ # Build reports +│ ├-- gradle.properties # Gradle properties +│ ├-- local.properties # Local machine config (gitignored) +│ ├-- settings.gradle.kts # Gradle settings +│ ├-- build/ +│ │ ├-- archive/ # Generated archives +│ │ ├-- plugin/ # Built plugin files +│ │ └-- reports/ # Build reports │ │ -│ ├── build-logic/ # Convention plugin (precompiled script plugins) -│ │ ├── build.gradle.kts -│ │ ├── settings.gradle.kts -│ │ └── src/main/kotlin/ -│ │ ├── base-conventions.gradle.kts # Core convention plugin - applied by every module -│ │ ├── BuildConfig.kt # Reads build.properties + per-module *-build.properties -│ │ ├── GodotConfig.kt # Reads godot.properties -│ │ ├── IosConfig.kt # Reads ios/config/ios.properties -│ │ ├── PluginConfig.kt # Reads plugin.properties -│ │ ├── ProjectExtensions.kt # loadPluginConfig(), loadGodotConfig(), loadIosConfig(), loadBuildConfig() -│ │ └── SpmDependency.kt # Data class for spm_dependencies.json entries +│ ├-- build-logic/ # Convention plugin (precompiled script plugins) +│ │ ├-- build.gradle.kts +│ │ ├-- settings.gradle.kts +│ │ └-- src/main/java/ +│ │ ├-- base-conventions.gradle.kts # Core convention plugin - applied by every module +│ │ ├-- BuildConfig.kt # Reads build.properties + per-module *-build.properties +│ │ ├-- GodotConfig.kt # Reads godot.properties +│ │ ├-- IosConfig.kt # Reads ios/config/ios.properties +│ │ ├-- PluginConfig.kt # Reads plugin.properties +│ │ ├-- ProjectExtensions.kt # loadPluginConfig(), loadGodotConfig(), loadIosConfig(), loadBuildConfig() +│ │ └-- SpmDependency.kt # Data class for spm_dependencies.json entries │ │ -│ ├── config/ -│ │ ├── build.properties # Build-related property configuration & customization -│ │ ├── godot.properties # Godot version configuration -│ │ └── plugin.properties # Plugin configuration +│ ├-- config/ +│ │ ├-- build.properties # Build-related property configuration & customization +│ │ ├-- godot.properties # Godot version configuration +│ │ └-- plugin.properties # Plugin configuration │ │ -│ └── gradle/ # Gradle wrapper and version catalogs -│ └── libs.versions.toml # Dependencies and versions +│ └-- gradle/ # Gradle wrapper and version catalogs +│ └-- libs.versions.toml # Dependencies and versions │ -├── demo/ # Demo application -│ ├── addons/ # Installed plugin files -│ ├── ios/ # iOS-specific demo files -│ └── *.gd # Demo app scripts +├-- demo/ # Demo application +│ ├-- addons/ # Installed plugin files +│ ├-- ios/ # iOS-specific demo files +│ └-- *.gd # Demo app scripts │ -├── ios/ # iOS platform module -│ ├── ios-build.gradle.kts # iOS build configuration -│ ├── ?.gradle.kts # Any extra iOS-specific Gradle configuration (configured in +├-- ios/ # iOS platform module +│ ├-- ios-build.gradle.kts # iOS build configuration +│ ├-- ?.gradle.kts # Any extra iOS-specific Gradle configuration (configured in │ │ # ios/config/ios-build.properties) for the plugin goes here │ │ -│ ├── src/ # iOS platform code -│ ├── test/ # iOS test code -│ ├── plugin.xcodeproj/ # Xcode project -│ ├── build/ # iOS build outputs +│ ├-- src/ # iOS platform code +│ ├-- test/ # iOS test code +│ ├-- plugin.xcodeproj/ # Xcode project +│ ├-- build/ # iOS build outputs │ │ -│ ├── config/ -│ │ ├── ios.properties # iOS configuration -│ │ ├── ios-build.properties # Gradle build customization for ios module -│ │ ├── spm_dependencies.json # SPM dependency configuration -│ │ └── *.gdip # Godot iOS plugin config +│ ├-- config/ +│ │ ├-- ios.properties # iOS configuration +│ │ ├-- ios-build.properties # Gradle build customization for ios module +│ │ ├-- spm_dependencies.json # SPM dependency configuration +│ │ └-- *.gdip # Godot iOS plugin config │ │ -│ └── godot/ # Downloaded Godot source (default location; configurable via local.properties) +│ └-- godot/ # Downloaded Godot source (default location; configurable via local.properties) │ -├── script/ # Build and utility scripts -│ ├── build.sh # Main build script -│ ├── build_android.sh # Android build script -│ ├── build_ios.sh # iOS build script -│ ├── install.sh # Plugin installation script -│ ├── run_gradle_task.sh # Gradle task runner -│ ├── get_config_property.sh # Configuration reader -│ └── spm_manager.rb # Ruby script for managing SPM dependencies in Xcode project +├-- script/ # Build and utility scripts +│ ├-- build.sh # Main build script +│ ├-- build_android.sh # Android build script +│ ├-- build_ios.sh # iOS build script +│ ├-- install.sh # Plugin installation script +│ ├-- run_gradle_task.sh # Gradle task runner +│ ├-- get_config_property.sh # Configuration reader +│ └-- spm_manager.rb # Ruby script for managing SPM dependencies in Xcode project │ -├── docs/ # Documentation +├-- docs/ # Documentation │ -└── release/ # Final release archives +└-- release/ # Final release archives ``` --- @@ -226,13 +226,13 @@ Your Android SDK directory should contain: ```text android-sdk/ -├── build-tools/ -├── cmdline-tools/ -├── licenses/ -├── ndk/ -├── platform-tools/ -├── platforms/ -└── tools/ +├-- build-tools/ +├-- cmdline-tools/ +├-- licenses/ +├-- ndk/ +├-- platform-tools/ +├-- platforms/ +└-- tools/ ``` - Create `local.properties` file inside `./common` directory that locates the Android SDK installation directory @@ -289,33 +289,33 @@ The build files are static and shared across all GMP plugins. Any plugin-specifi ```text . -├── addon/ -│ ├── ?.gradle.kts # Any extra addon-specific Gradle configuration (configured in +├-- addon/ +│ ├-- ?.gradle.kts # Any extra addon-specific Gradle configuration (configured in │ │ # addon/config/addon-build.properties) for the plugin goes here -│ └── config/ -│ └── addon-build.properties # Gradle build customization for addon module +│ └-- config/ +│ └-- addon-build.properties # Gradle build customization for addon module │ -├── android/ -│ ├── android-build.gradle.kts # Android build configuration -│ ├── ?.gradle.kts # Any extra Android-specific Gradle configuration (configured in +├-- android/ +│ ├-- android-build.gradle.kts # Android build configuration +│ ├-- ?.gradle.kts # Any extra Android-specific Gradle configuration (configured in │ │ # android/config/android-build.properties) for the plugin goes here -│ └── config/ -│ └── android-build.properties # Gradle build customization for android module +│ └-- config/ +│ └-- android-build.properties # Gradle build customization for android module │ -├── common/ -│ ├── config/ -│ │ ├── build.properties # Build-related property configuration & customization -│ │ ├── godot.properties # Godot version configuration -│ │ └── plugin.properties # Plugin configuration +├-- common/ +│ ├-- config/ +│ │ ├-- build.properties # Build-related property configuration & customization +│ │ ├-- godot.properties # Godot version configuration +│ │ └-- plugin.properties # Plugin configuration │ │ -│ └── gradle/ -│ └── libs.versions.toml # Android dependencies and versions +│ └-- gradle/ +│ └-- libs.versions.toml # Android dependencies and versions │ -└── ios/ - └── config/ - ├── ios.properties # iOS configuration - ├── ios-build.properties # Gradle build customization for ios module - └── spm_dependencies.json # SPM dependency configuration +└-- ios/ + └-- config/ + ├-- ios.properties # iOS configuration + ├-- ios-build.properties # Gradle build customization for ios module + └-- spm_dependencies.json # SPM dependency configuration ``` ### Common Configuration @@ -466,9 +466,12 @@ embedded_frameworks=res://ios/framework/*.xcframework,... # Linker flags (comma-separated; may be empty) flags=-ObjC,-Wl,... + +# Files to include in the app bundle +bundle_files=res://assets/VisionPlugin/face_landmarker.task ``` -The `frameworks`, `embedded_frameworks`, and `flags` values are comma-separated lists. The build system parses them into typed lists at configuration time (`IosConfig.kt`) - blank entries are ignored. Values are used as-is for token replacement in GDScript templates and passed directly to `xcodebuild`. +The `frameworks`, `embedded_frameworks`, `flags`, and `bundle_files` values are comma-separated lists. The build system parses them into typed lists at configuration time (`IosConfig.kt`) - blank entries are ignored. Values are used as-is for token replacement in GDScript templates and passed directly to `xcodebuild`. GDScript templates may reference the following tokens for iOS values set in `ios.properties` and `spm_dependencies.json`: @@ -477,6 +480,7 @@ GDScript templates may reference the following tokens for iOS values set in `ios | `@iosFrameworks@` | `frameworks` (ios.properties) | quoted strings | | `@iosEmbeddedFrameworks@`| `embedded_frameworks` | quoted strings | | `@iosLinkerFlags@` | `flags` | quoted strings | +| `@iosBundleFiles@` | `bundle_files` | quoted strings | | `@spmDependencies@` | `spm_dependencies.json` | GDScript dicts | The `@spmDependencies@` token produces GDScript dictionary literals with StringName keys and no outer brackets (see [`IosConfig` SPM Dependencies](#iosconfig-spm-dependencies) for the exact format). diff --git a/docs/README.md b/docs/README.md index 60bca88..640163a 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,8 +1,8 @@ -

- -               - -

+
+ +![](https://raw.githubusercontent.com/godot-mobile-plugins/godot-native-camera/main/demo/assets/native-camera-android.png)       ![](https://raw.githubusercontent.com/godot-mobile-plugins/godot-native-camera/main/demo/assets/native-camera-ios.png) + +
@@ -269,18 +269,17 @@ Helpful resources: | ✦ | Plugin | Android | iOS | Latest Release | Downloads | Stars | | :--- | :--- | :---: | :---: | :---: | :---: | :---: | -| | [Admob](https://github.com/godot-sdk-integrations/godot-admob) | ✅ | ✅ | | | | -| | [Connection State](https://github.com/godot-mobile-plugins/godot-connection-state) | ✅ | ✅ | | | | -| | [Deeplink](https://github.com/godot-mobile-plugins/godot-deeplink) | ✅ | ✅ | | | | -| | [Firebase](https://github.com/godot-mobile-plugins/godot-firebase) | ⏰ | ⏰ | 🔜 | - | | -| | [In-App Review](https://github.com/godot-mobile-plugins/godot-inapp-review) | ✅ | ✅ | | | | -| | [Native Camera](https://github.com/godot-mobile-plugins/godot-native-camera) | ✅ | ✅ | | | | -| | [Notification Scheduler](https://github.com/godot-mobile-plugins/godot-notification-scheduler) | ✅ | ✅ | | | | -| | [OAuth 2.0](https://github.com/godot-mobile-plugins/godot-oauth2) | ✅ | ✅ | | | | -| | [QR](https://github.com/godot-mobile-plugins/godot-qr) | ✅ | ✅ | | | | -| | [Share](https://github.com/godot-mobile-plugins/godot-share) | ✅ | ✅ | | | | -| | [Vision](https://github.com/godot-mobile-plugins/godot-vision) | ⏰ | ⏰ | 🔜 | - | | -| | [Plugin Template](https://github.com/godot-mobile-plugins/godot-plugin-template) | ✅ | ✅ | - | - | | +| | [Admob](https://github.com/godot-sdk-integrations/godot-admob) | ✅ | ✅ | | | | +| | [Connection State](https://github.com/godot-mobile-plugins/godot-connection-state) | ✅ | ✅ | | | | +| | [Deeplink](https://github.com/godot-mobile-plugins/godot-deeplink) | ✅ | ✅ | | | | +| | [Firebase](https://github.com/godot-mobile-plugins/godot-firebase) | ⏰ | ⏰ | 🔜 | - | | +| | [In-App Review](https://github.com/godot-mobile-plugins/godot-inapp-review) | ✅ | ✅ | | | | +| | [Native Camera](https://github.com/godot-mobile-plugins/godot-native-camera) | ✅ | ✅ | | | | +| | [Notification Scheduler](https://github.com/godot-mobile-plugins/godot-notification-scheduler) | ✅ | ✅ | | | | +| | [OAuth 2.0](https://github.com/godot-mobile-plugins/godot-oauth2) | ✅ | ✅ | | | | +| | [QR](https://github.com/godot-mobile-plugins/godot-qr) | ✅ | ✅ | | | | +| | [Share](https://github.com/godot-mobile-plugins/godot-share) | ✅ | ✅ | | | | +| | [Vision](https://github.com/godot-mobile-plugins/godot-vision) | ✅ | ✅ | | | |
diff --git a/ios/config/ios.properties b/ios/config/ios.properties index ba5c2d7..b2052ee 100644 --- a/ios/config/ios.properties +++ b/ios/config/ios.properties @@ -7,6 +7,7 @@ swift_version=5.9 frameworks=Foundation.framework,AudioToolbox.framework embedded_frameworks= flags=-ObjC +bundle_files= # -- Test configuration -------------------------------------------------------- test_platform=iOS Simulator diff --git a/ios/ios-build.gradle.kts b/ios/ios-build.gradle.kts index c6f4b5e..de2c2d4 100644 --- a/ios/ios-build.gradle.kts +++ b/ios/ios-build.gradle.kts @@ -297,8 +297,10 @@ fun TaskContainerScope.registerSwiftFormatTask( doFirst { val sourceFiles = - fileTree(projectDir) { include("**/*.swift") } - .files + fileTree(projectDir) { + include("**/*.swift") + exclude("**/DerivedData/**") + }.files .map { it.relativeTo(projectDir).path } .sorted() @@ -1003,7 +1005,7 @@ tasks { """ xcrun simctl bootstatus $udid -b & BOOT_PID=$!; - (sleep 120 && kill ${'$'}BOOT_PID 2>/dev/null) & + (sleep 30 && kill ${'$'}BOOT_PID 2>/dev/null) & wait ${'$'}BOOT_PID """.trimIndent().replace("\n", " ") @@ -1069,7 +1071,7 @@ tasks { "Result : \(.result // "Unknown")", "", "Configurations:", - "───────────────", + "---------------", (.devicesAndConfigurations[]? | " • \(.device.deviceName) (\(.device.osVersion))" + " | Passed: \(.passedTests) | Failed: \(.failedTests)" @@ -1078,7 +1080,7 @@ tasks { echo "" echo "📦 Test Suites" - echo "───────────────" + echo "---------------" xcrun xcresulttool get test-results tests \ --path "${'$'}BUNDLE" --format json 2>/dev/null \ | jq -r ' @@ -1088,7 +1090,7 @@ tasks { echo "" echo "🧪 Code Coverage" - echo "───────────────" + echo "---------------" xcrun xccov view --report --json "${'$'}BUNDLE" 2>/dev/null \ | jq -r ' (.targets // [])[] | diff --git a/ios/plugin.xcodeproj/project.pbxproj b/ios/plugin.xcodeproj/project.pbxproj index af60fb2..a14763a 100644 --- a/ios/plugin.xcodeproj/project.pbxproj +++ b/ios/plugin.xcodeproj/project.pbxproj @@ -362,6 +362,10 @@ ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "$(GODOT_DIR)/bin/libgodot.ios.template_debug.$(CURRENT_ARCH).simulator.a", + ); OTHER_CFLAGS = ( "-g", "-DDEBUG", @@ -410,10 +414,6 @@ "-isystem", "$(GODOT_DIR)/platform/ios", ); - OTHER_LDFLAGS = ( - "$(inherited)", - "$(GODOT_DIR)/bin/libgodot.ios.template_debug.$(CURRENT_ARCH).simulator.a", - ); PRODUCT_BUNDLE_IDENTIFIER = "org.godotengine.plugin.native-camera-unit-tests"; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = NO; @@ -460,6 +460,10 @@ ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "$(GODOT_DIR)/bin/libgodot.ios.template_debug.$(CURRENT_ARCH).simulator.a", + ); OTHER_CFLAGS = ( "-fmodules", "-fobjc-arc", @@ -499,10 +503,6 @@ "-isystem", "$(GODOT_DIR)/platform/ios", ); - OTHER_LDFLAGS = ( - "$(inherited)", - "$(GODOT_DIR)/bin/libgodot.ios.template_debug.$(CURRENT_ARCH).simulator.a", - ); PRODUCT_BUNDLE_IDENTIFIER = "org.godotengine.plugin.native-camera-unit-tests"; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = NO; diff --git a/ios/src/NativeCamera.swift b/ios/src/NativeCamera.swift index 0e0bc2f..0c2f6e7 100644 --- a/ios/src/NativeCamera.swift +++ b/ios/src/NativeCamera.swift @@ -61,16 +61,23 @@ import UIKit } @objc public func start(cameraId: String, width: Int, height: Int, skip: Int, rot: Int, gray: Bool) { - stop() // Ensure clean start + // Dispatch everything onto sessionQueue so stop() fully completes + // before we reconfigure, AND so variable writes are on the same + // queue that captureOutput reads them from — no data race. + sessionQueue.async { + self.captureSession?.stopRunning() + self.captureSession = nil + self.videoOutput = nil - self.targetWidth = width - self.targetHeight = height - self.framesToSkip = skip - self.rotation = rot - self.isGrayscale = gray - self.frameCounter = 0 + // Set instance vars inside sessionQueue, so captureOutput + // (also on sessionQueue) always sees a consistent, written value. + self.targetWidth = width + self.targetHeight = height + self.framesToSkip = skip + self.rotation = rot + self.isGrayscale = gray + self.frameCounter = 0 - sessionQueue.async { let session = AVCaptureSession() session.beginConfiguration() @@ -80,7 +87,6 @@ import UIKit if session.canAddInput(input) { session.addInput(input) } let output = AVCaptureVideoDataOutput() - // We request BGRA for color or Y (Luma) for grayscale via the delegate output.videoSettings = [ kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA ]