├── .gitignore ├── .idea └── .gitignore ├── .vscode └── settings.json ├── README.md ├── example ├── .eslintrc.js ├── .gitignore ├── .prettierrc.js ├── .watchmanconfig ├── README.md ├── android │ ├── app │ │ ├── build.gradle │ │ ├── debug.keystore │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── ReactNativeFlipper.java │ │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── assets │ │ │ │ └── custom │ │ │ │ │ ├── cube.pck │ │ │ │ │ └── earth.pck │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── example │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ │ ├── drawable │ │ │ │ └── rn_edit_text_material.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ │ └── values │ │ │ │ ├── strings.xml │ │ │ │ └── styles.xml │ │ │ └── release │ │ │ └── java │ │ │ └── com │ │ │ └── example │ │ │ └── ReactNativeFlipper.java │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── link-assets-manifest.json │ └── settings.gradle ├── app.json ├── babel.config.js ├── index.js ├── ios │ ├── .bundle │ │ └── config │ ├── .xcode.env │ ├── Gemfile │ ├── Gemfile.lock │ ├── Podfile │ ├── Podfile.lock │ ├── example-Bridging-Header.h │ ├── example.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── example.xcscheme │ ├── example.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── example │ │ ├── AppDelegate.swift │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── CALICO.png │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Info.plist │ │ ├── LaunchScreen.storyboard │ │ └── PrivacyInfo.xcprivacy │ ├── link-assets-manifest.json │ └── project.godot ├── metro.config.js ├── package.json ├── react-native.config.js ├── src │ ├── App.tsx │ ├── Root.tsx │ ├── Routes.tsx │ ├── Screens │ │ ├── CubesExample.tsx │ │ ├── EarthExample.tsx │ │ └── Home.tsx │ ├── Utils │ │ ├── SolarCalculator.ts │ │ └── withPreventGoBack.tsx │ └── assets │ │ ├── cube.pck │ │ └── earth.pck ├── tsconfig.json └── yarn.lock ├── export_presets.cfg ├── gen-pck.sh ├── package ├── .gitignore ├── android │ ├── .gitignore │ ├── .settings │ │ └── org.eclipse.buildship.core.prefs │ ├── build.gradle │ ├── gradle.properties │ └── src │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── AndroidManifestNew.xml │ │ ├── cpp │ │ ├── CMakeLists.txt │ │ └── native-lib.cpp │ │ └── java │ │ └── games │ │ └── calico │ │ ├── EngineJsiModule.java │ │ └── EngineJsiPackage.java ├── index.ts ├── ios │ └── GodotModule.mm ├── libs │ ├── android │ │ └── .gitkeep │ └── ios │ │ └── .gitkeep ├── package.json ├── react-native-godot-utils.rb ├── react-native-godot.podspec ├── src │ ├── GodotProvider.tsx │ ├── index.ts │ ├── specs │ │ ├── GodotViewNativeComponent.ts │ │ └── NativeGodotModule.ts │ ├── types │ │ ├── Node.tsx │ │ └── index.ts │ ├── variants │ │ ├── AABB.ts │ │ ├── Basis.ts │ │ ├── Color.ts │ │ ├── Plane.ts │ │ ├── Projection.ts │ │ ├── Quaternion.ts │ │ ├── Rect2.ts │ │ ├── Rect2i.ts │ │ ├── Transform2D.ts │ │ ├── Transform3D.ts │ │ ├── Vector2.ts │ │ ├── Vector2i.ts │ │ ├── Vector3.ts │ │ ├── Vector3i.ts │ │ ├── Vector4.ts │ │ └── Vector4i.ts │ └── views │ │ ├── Godot.tsx │ │ ├── GodotView.tsx │ │ ├── GodotViewNativeId.ts │ │ ├── api.ts │ │ ├── index.ts │ │ └── types.ts ├── tsconfig.json └── yarn.lock ├── screenshots ├── screenshot1.jpeg ├── screenshot2.jpeg └── screenshot3.png └── static └── banner.png /.gitignore: -------------------------------------------------------------------------------- 1 | Derived 2 | target 3 | build 4 | .DS_Store 5 | volumes 6 | *.zip 7 | *.tgz 8 | *.ipa 9 | *.pb 10 | node_modules 11 | *.xcodeproj 12 | *.xcframework 13 | *.so -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.tabSize": 2, 3 | "[swift]": { 4 | "editor.tabSize": 4 5 | }, 6 | "[objective-c]": { 7 | "editor.tabSize": 4 8 | }, 9 | "[objective-cpp]": { 10 | "editor.tabSize": 4 11 | }, 12 | "[java]": { 13 | "editor.tabSize": 4 14 | }, 15 | "files.associations": { 16 | "memory": "cpp" 17 | }, 18 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | react-native-godot 3 | 4 | 5 |
6 | 7 | Bring **Godot** to **React Native** 🔮. 8 | Create immersive 3D experiences or interactive games directly within React Native, allowing for high-performance graphics and responsive interactions. 9 | 10 | [![npm version](https://img.shields.io/npm/v/react-native-godot.svg?style=flat)](https://www.npmjs.com/package/react-native-godot) 11 | [![godot engine](https://img.shields.io/badge/Godot-4.4.1-blue)](https://godotengine.org/download) 12 | 13 | ## Screenshots 📸 14 | 15 | [Multiple Cubes demo](screenshots/screenshot1.jpeg) 16 | [Earth demo](screenshots/screenshot2.jpeg) 17 | 18 | ### Features 🚀 19 | 20 | * 🏎️ Native C++ JSI performance 21 | * 🔥 GPU-accelerated by Metal and OpenGL/Vulkan 22 | * ✅ Supports old and new arch 23 | * 🙂 Supports Godot Variants in React Native 24 | * 🧨 Call GDScript methods in React Native 25 | * 📦 Easy import of your Godot projects 26 | 27 | ## Device Support 📱 28 | 29 | iOS support is implemented, full support for Android is almost ready. 30 | We'll ship that soon 😊 31 | 32 | | Platform | Supported | 33 | | ---------------- | --------- | 34 | | iOS Device | ✅ | 35 | | iOS Simulator | ❌ | 36 | | Android Emulator | 🚧 | 37 | | Android Device | 🚧 | 38 | 39 | ## Requirements 🥸 40 | 41 | * Godot 4.4.1 ([https://godotengine.org/](https://godotengine.org/)) 42 | 43 | ## Installation 🚀 44 | 45 | ```sh 46 | npm install react-native-godot 47 | 48 | or 49 | 50 | yarn add react-native-godot 51 | ``` 52 | 53 | ## Usage 👇 54 | 55 | Take a look at the `example` folder for a full implem 👀. 56 | 57 | ### React Native <-> Godot Communication 📡 58 | 59 | You can send messages from React Native to Godot and receive messages from Godot in React Native. 60 | 61 | * **React Native -> Godot**: You can send messages from React Native to Godot using the `emitMessage` method. 62 | * **Godot -> React Native**: You can receive messages from Godot in React Native using the `onMessage` prop. 63 | 64 | ```tsx 65 | // ⚠️ IMPORTANT ⚠️ 66 | // GodotProvider is required to initalize Godot properly 67 | // (See in the example folder for more details) 68 | // 69 | // 70 | // 71 | // 72 | // 73 | // It should be at the root of your app. 74 | // The highest level is recommended. e.g. App.tsx 75 | 76 | import React, {useRef} from 'react'; 77 | import {Godot, GodotView, GodotProvider, useGodot} from 'react-native-godot'; 78 | 79 | const Example = () => { 80 | const godotRef = useRef(null); 81 | const {Vector3, Vector2} = useGodot(); 82 | 83 | // Call gdsript method from React Native 84 | useEffect(() => { 85 | if (!godotRef.current || !godotRef.current?.isReady) { 86 | return; 87 | } 88 | 89 | // Emit a message to Godot from React Native 90 | godotRef.current?.emitMessage({ 91 | message: 'Hello from React Native!', 92 | position: Vector3(1, 2, 3), 93 | }); 94 | 95 | // Use Godot Vector3 and Vector2 variants 96 | // All methods and properties are available too :) 97 | console.log('Vector3 y:', Vector3(1, 2, 3).y); 98 | console.log('Length', Vector2(3, 1).length()); 99 | 100 | // Retrieve a node from your scene 101 | const node = godotRef.current?.getRoot()?.getNode('MySuperNode'); 102 | if (!node) { 103 | return; 104 | } 105 | 106 | // Call method `hello_world` from the gdscript attached to the node in your scene 107 | node.hello_world(); 108 | 109 | // You can also call your method and return a value with any supported types 110 | const something = node.method_that_returns_something(); 111 | console.log('Something:', something); 112 | }, [godotRef.current?.isReady]); 113 | 114 | return ( 115 | console.log('Godot message:', message)} 122 | /> 123 | ); 124 | }; 125 | ``` 126 | 127 | ### Godot implementation (GDScript) 🧙‍♂️ 128 | 129 | ```gdscript 130 | # This class is a demonstration of GDScript with React Native. 131 | 132 | extends Node 133 | 134 | func _ready() -> void: 135 | if Engine.has_singleton("ReactNative"): # Always check if the ReactNative singleton exists 136 | Engine.get_singleton("ReactNative").on_message(_on_message) 137 | 138 | func _on_message(message: Dictionary) -> void: 139 | print("React Native message:", message) 140 | 141 | func _input(event: InputEvent) -> void: 142 | if "position" not in event: 143 | return 144 | 145 | var adjusted_position = adjust_for_window(event.position) 146 | 147 | if Engine.has_singleton("ReactNative"): 148 | # Emit a message to React Native 149 | Engine.get_singleton("ReactNative").emit_message({ 150 | "message": "Input event position", 151 | "pos": adjusted_position, 152 | }) 153 | 154 | func hello_world() -> void: 155 | print("Hello World!") 156 | 157 | func method_that_returns_something() -> int: 158 | return 42 159 | 160 | ## This function is used to adjust the screen position for the window. 161 | func adjust_for_window(pos: Vector2) -> Vector2: 162 | var window = get_viewport().get_window() 163 | var window_id = window.get_window_id() 164 | 165 | if window_id == DisplayServer.MAIN_WINDOW_ID or window_id == DisplayServer.INVALID_WINDOW_ID: 166 | return pos 167 | 168 | var window_position = Vector2() 169 | 170 | if Engine.has_singleton("ReactNative"): 171 | window_position = Engine.get_singleton("ReactNative").get_subwindow_position(window_id) 172 | 173 | return Vector2( 174 | pos.x + window_position.x, 175 | pos.y + window_position.y 176 | ) 177 | ``` 178 | 179 | ## Godot Variants 🍭 180 | 181 | Godot variants are available in React Native, here is the list: 182 | `AABB | Basis | Color | Plane | Projection | Quaternion | Rect2 | Rect2i | Transform2D | Transform3D | Vector2 | Vector2i | Vector3 | Vector3i | Vector4 | Vector4i`. 183 | 184 | For primitives like `int`, `float`, `bool`, `dictionary`, `array`, etc, you can use normal JS types and it will be automatically converted to Godot variants and vice versa. 185 | 186 | All methods and properties are available too, for instance, you can use `Vector3(1, 2, 3).length()`. 187 | Complete documentation is available at [https://docs.godotengine.org/en/stable/classes/index.html#variant-types](https://docs.godotengine.org/en/stable/classes/index.html#variant-types). 188 | 189 | ## Access any Godot Nodes from React Native 🎯 190 | 191 | You can retrieve a node from your scene in React Native and call methods on it. 192 | 193 | Current supported methods for a Node are: 194 | 195 | * getNode(name: string): Node | null 196 | * getParent(): Node | null 197 | * getChildren(): Node[] 198 | * getChildCount(): number 199 | 200 | (+ Any method you've defined in your gdscript 😌) 201 | 202 | ## Import your Godot Project (How to) 📥 203 | 204 | * To import your **Godot project** into React Native, you need to **generate a pck file** that basically packs up all your game assets, scripts etc. 205 | It's a convenient way to pack your game into a single file. 206 | 207 | * First, you need to add a `export_presets.cfg` in the directory of your Godot project. 208 | We provide a working example of this file at the root of this repository. 209 | 210 | * After that, you're now able to generate a pck file, just run `./gen-pck PROJECT_FOLDER_PATH`. 211 | Be sure you have `/Applications/Godot.app` set on your machine, if you're using another path or another OS than macOS, just modify this very simple shell at your convenience. 212 | 213 | * Then, you just need to move the pck file in your assets folder. 214 | 215 | * One last important thing, don't forget to add a `project.godot` in your XCode project, see in the example folder for more details. 216 | 217 | ## Metro Config 🚇 218 | 219 | * You need to add the following to your `metro.config.js` in order to treat `.pck` files as assets and exclude them from being treated as source files. 220 | 221 | ```js 222 | // Treat `.pck` files as assets 223 | assetExts: [...assetExts, 'pck'], 224 | // Exclude `.pck` from being treated as source files 225 | sourceExts: sourceExts.filter(ext => ext !== 'pck'), 226 | ``` 227 | 228 | And... 229 | 230 | ```js 231 | server: { 232 | enhanceMiddleware: (middleware) => { 233 | return (req, res, next) => { 234 | if (/\.pck$/.test(req.url)) { 235 | res.setHeader('Content-Type', 'application/octet-stream'); 236 | } 237 | return middleware(req, res, next); 238 | }; 239 | }, 240 | }, 241 | ``` 242 | 243 | ## Limitations & Known Issues 🚧 244 | 245 | * When importing a texture or 3D model, be sure you don't import them as `VRAM Compressed`, for some reason when exporting the pck file, it doesn't import the assets. Might be a mistake from our side.... (TBD) 😅 246 | 247 | [VRAM Compressed](screenshots/screenshot3.png) 248 | 249 | * **PCK Asset Swapping**: For now, you can't swap the pck asset at runtime properly, you need to reopen the app to load a new pck asset. It seems to be a limitation of the Godot engine itself, but we're investigating this as it would be super useful to debug on device in almost real-time. 250 | 251 | ## TODO 📝 252 | 253 | * [x] iOS support 254 | * [ ] Android support 255 | * [x] Improve library size 256 | * [x] Add support for all Godot variants 257 | * [ ] Investigate PCK asset swapping 258 | * [x] Add support for more Godot features 259 | 260 | ## Contributing 🤝 261 | 262 | We're open to any contributions. Feel free to open an issue if you want to help us improve this library. 263 | 264 | All the interesting stuff is located in a private repository so if you want to contribute, just send us an email at `team@calico.games`. 265 | You should have previous experiences of building the Godot Engine yourself, C++, and building blazing fast React Native libraries is a plus. 266 | [Bazel](https://github.com/bazelbuild/bazel) is also used internally to build the library fyk. 267 | 268 | ## Copyright / License 👨‍⚖️ 269 | 270 | Copyright **Calico Games** 2024. All rights reserved. 271 | 272 | This library is released under a **Custom License** with the following conditions: 273 | 274 | * **Free for non-commercial use**: You may freely use this library for personal, educational, or open-source projects. 275 | * **Commercial use by revenue-generating entities**: Any company or individual with an annual revenue exceeding $50,000 must obtain a commercial license to use this library. 276 | * **No Redistribution Allowed**: This library cannot be redistributed, repackaged, or resold. 277 | 278 | PS: We are pretty flexible atm and we would like to also support the Godot Foundation by giving them a share of the revenue generated by this library. 279 | 280 | For commercial licensing inquiries, please contact us at `team@calico.games`. 281 | 282 | ## Credits 🙏 283 | 284 | * Special thanks to all the contributors of the [Godot Engine](https://github.com/godotengine/godot). 285 | * A big shoutout to [Migeran](https://github.com/migeran) that helped us a lot to build this library. 286 | -------------------------------------------------------------------------------- /example/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: ['eslint:recommended', '@react-native', 'plugin:prettier/recommended'], 4 | plugins: ['prettier'], 5 | rules: { 6 | 'react/react-in-jsx-scope': 'off', 7 | 'react-native/no-inline-styles': 'off', 8 | 'react-hooks/exhaustive-deps': 'off', 9 | 'no-shadow': 'off', 10 | 'no-alert': 'off', 11 | 'prettier/prettier': 'error', 12 | '@typescript-eslint/no-unused-vars': 'warn', 13 | 'react-native/no-unused-styles': 1, 14 | }, 15 | requireConfigFile: false, 16 | }; 17 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | ios/.xcode.env.local 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | *.hprof 33 | .cxx/ 34 | *.keystore 35 | !debug.keystore 36 | 37 | # node.js 38 | # 39 | node_modules/ 40 | npm-debug.log 41 | yarn-error.log 42 | 43 | # fastlane 44 | # 45 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 46 | # screenshots whenever they are needed. 47 | # For more information about the recommended setup visit: 48 | # https://docs.fastlane.tools/best-practices/source-control/ 49 | 50 | **/fastlane/report.xml 51 | **/fastlane/Preview.html 52 | **/fastlane/screenshots 53 | **/fastlane/test_output 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # Ruby / CocoaPods 59 | /ios/Pods/ 60 | /ios/vendor/bundle/ 61 | 62 | # Temporary files created by Metro to check the health of the file watcher 63 | .metro-health-check* 64 | 65 | # testing 66 | /coverage 67 | 68 | # Godot 4+ specific ignores 69 | .godot/ -------------------------------------------------------------------------------- /example/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | arrowParens: 'avoid', 3 | bracketSameLine: true, 4 | bracketSpacing: false, 5 | singleQuote: true, 6 | trailingComma: 'all', 7 | tabWidth: 2, 8 | printWidth: 100, 9 | }; 10 | -------------------------------------------------------------------------------- /example/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # Example using React Native Godot 2 | 3 | ## Usage 4 | 5 | Use `yarn` for this example as we use a certain feature `link:...` to use the `react-native-godot` package locally. 6 | 7 | ```sh 8 | # To launch metro debugger 9 | $ yarn start 10 | # To launch the app for iOS 11 | $ yarn ios 12 | # To launch the app for Android 13 | $ yarn android 14 | # To pack your assets in the iOS/Android app (needed when updating assets) 15 | $ yarn asset 16 | ``` 17 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | apply plugin: "com.facebook.react" 3 | 4 | /** 5 | * This is the configuration block to customize your React Native Android app. 6 | * By default you don't need to apply any configuration, just uncomment the lines you need. 7 | */ 8 | react { 9 | /* Folders */ 10 | // The root of your project, i.e. where "package.json" lives. Default is '..' 11 | // root = file("../") 12 | // The folder where the react-native NPM package is. Default is ../node_modules/react-native 13 | // reactNativeDir = file("../node_modules/react-native") 14 | // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen 15 | // codegenDir = file("../node_modules/@react-native/codegen") 16 | // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js 17 | // cliFile = file("../node_modules/react-native/cli.js") 18 | 19 | /* Variants */ 20 | // The list of variants to that are debuggable. For those we're going to 21 | // skip the bundling of the JS bundle and the assets. By default is just 'debug'. 22 | // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. 23 | // debuggableVariants = ["liteDebug", "prodDebug"] 24 | 25 | /* Bundling */ 26 | // A list containing the node command and its flags. Default is just 'node'. 27 | // nodeExecutableAndArgs = ["node"] 28 | // 29 | // The command to run when bundling. By default is 'bundle' 30 | // bundleCommand = "ram-bundle" 31 | // 32 | // The path to the CLI configuration file. Default is empty. 33 | // bundleConfig = file(../rn-cli.config.js) 34 | // 35 | // The name of the generated asset file containing your JS bundle 36 | // bundleAssetName = "MyApplication.android.bundle" 37 | // 38 | // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' 39 | // entryFile = file("../js/MyApplication.android.js") 40 | // 41 | // A list of extra flags to pass to the 'bundle' commands. 42 | // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle 43 | // extraPackagerArgs = [] 44 | 45 | /* Hermes Commands */ 46 | // The hermes compiler command to run. By default it is 'hermesc' 47 | // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" 48 | // 49 | // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" 50 | // hermesFlags = ["-O", "-output-source-map"] 51 | } 52 | 53 | /** 54 | * Set this to true to Run Proguard on Release builds to minify the Java bytecode. 55 | */ 56 | def enableProguardInReleaseBuilds = false 57 | 58 | /** 59 | * The preferred build flavor of JavaScriptCore (JSC) 60 | * 61 | * For example, to use the international variant, you can use: 62 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` 63 | * 64 | * The international variant includes ICU i18n library and necessary data 65 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that 66 | * give correct results when using with locales other than en-US. Note that 67 | * this variant is about 6MiB larger per architecture than default. 68 | */ 69 | def jscFlavor = 'org.webkit:android-jsc:+' 70 | 71 | android { 72 | ndkVersion rootProject.ext.ndkVersion 73 | 74 | compileSdkVersion rootProject.ext.compileSdkVersion 75 | 76 | namespace "com.example" 77 | defaultConfig { 78 | applicationId "com.example" 79 | minSdkVersion rootProject.ext.minSdkVersion 80 | targetSdkVersion rootProject.ext.targetSdkVersion 81 | versionCode 1 82 | versionName "1.0" 83 | } 84 | signingConfigs { 85 | debug { 86 | storeFile file('debug.keystore') 87 | storePassword 'android' 88 | keyAlias 'androiddebugkey' 89 | keyPassword 'android' 90 | } 91 | } 92 | buildTypes { 93 | debug { 94 | signingConfig signingConfigs.debug 95 | } 96 | release { 97 | // Caution! In production, you need to generate your own keystore file. 98 | // see https://reactnative.dev/docs/signed-apk-android. 99 | signingConfig signingConfigs.debug 100 | minifyEnabled enableProguardInReleaseBuilds 101 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 102 | } 103 | } 104 | } 105 | 106 | dependencies { 107 | // The version of react-native is set by the React Native Gradle Plugin 108 | implementation("com.facebook.react:react-android") 109 | 110 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") 111 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { 112 | exclude group:'com.squareup.okhttp3', module:'okhttp' 113 | } 114 | 115 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") 116 | if (hermesEnabled.toBoolean()) { 117 | implementation("com.facebook.react:hermes-android") 118 | } else { 119 | implementation jscFlavor 120 | } 121 | } 122 | 123 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) -------------------------------------------------------------------------------- /example/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/android/app/debug.keystore -------------------------------------------------------------------------------- /example/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | -keep class com.facebook.hermes.unicode.** { *; } 13 | -keep class com.facebook.jni.** { *; } -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /example/android/app/src/debug/java/com/example/ReactNativeFlipper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | *

This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | package com.example; 8 | 9 | import android.content.Context; 10 | import com.facebook.flipper.android.AndroidFlipperClient; 11 | import com.facebook.flipper.android.utils.FlipperUtils; 12 | import com.facebook.flipper.core.FlipperClient; 13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; 14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; 15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; 16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping; 17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; 18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; 19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; 20 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; 21 | import com.facebook.react.ReactInstanceEventListener; 22 | import com.facebook.react.ReactInstanceManager; 23 | import com.facebook.react.bridge.ReactContext; 24 | import com.facebook.react.modules.network.NetworkingModule; 25 | import okhttp3.OkHttpClient; 26 | 27 | /** 28 | * Class responsible of loading Flipper inside your React Native application. This is the debug 29 | * flavor of it. Here you can add your own plugins and customize the Flipper setup. 30 | */ 31 | public class ReactNativeFlipper { 32 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 33 | if (FlipperUtils.shouldEnableFlipper(context)) { 34 | final FlipperClient client = AndroidFlipperClient.getInstance(context); 35 | 36 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); 37 | client.addPlugin(new DatabasesFlipperPlugin(context)); 38 | client.addPlugin(new SharedPreferencesFlipperPlugin(context)); 39 | client.addPlugin(CrashReporterPlugin.getInstance()); 40 | 41 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); 42 | NetworkingModule.setCustomClientBuilder( 43 | new NetworkingModule.CustomClientBuilder() { 44 | @Override 45 | public void apply(OkHttpClient.Builder builder) { 46 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); 47 | } 48 | }); 49 | client.addPlugin(networkFlipperPlugin); 50 | client.start(); 51 | 52 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized 53 | // Hence we run if after all native modules have been initialized 54 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); 55 | if (reactContext == null) { 56 | reactInstanceManager.addReactInstanceEventListener( 57 | new ReactInstanceEventListener() { 58 | @Override 59 | public void onReactContextInitialized(ReactContext reactContext) { 60 | reactInstanceManager.removeReactInstanceEventListener(this); 61 | reactContext.runOnNativeModulesQueueThread( 62 | new Runnable() { 63 | @Override 64 | public void run() { 65 | client.addPlugin(new FrescoFlipperPlugin()); 66 | } 67 | }); 68 | } 69 | }); 70 | } else { 71 | client.addPlugin(new FrescoFlipperPlugin()); 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /example/android/app/src/main/assets/custom/cube.pck: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/android/app/src/main/assets/custom/cube.pck -------------------------------------------------------------------------------- /example/android/app/src/main/assets/custom/earth.pck: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/android/app/src/main/assets/custom/earth.pck -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import com.facebook.react.ReactActivity; 4 | import com.facebook.react.ReactActivityDelegate; 5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; 6 | import com.facebook.react.defaults.DefaultReactActivityDelegate; 7 | 8 | public class MainActivity extends ReactActivity { 9 | 10 | /** 11 | * Returns the name of the main component registered from JavaScript. This is used to schedule 12 | * rendering of the component. 13 | */ 14 | @Override 15 | protected String getMainComponentName() { 16 | return "example"; 17 | } 18 | 19 | /** 20 | * Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link 21 | * DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React 22 | * (aka React 18) with two boolean flags. 23 | */ 24 | @Override 25 | protected ReactActivityDelegate createReactActivityDelegate() { 26 | return new DefaultReactActivityDelegate( 27 | this, 28 | getMainComponentName(), 29 | // If you opted-in for the New Architecture, we enable the Fabric Renderer. 30 | DefaultNewArchitectureEntryPoint.getFabricEnabled()); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/com/example/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.example; 2 | 3 | import android.app.Application; 4 | import com.facebook.react.PackageList; 5 | import com.facebook.react.ReactApplication; 6 | import com.facebook.react.ReactNativeHost; 7 | import com.facebook.react.ReactPackage; 8 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; 9 | import com.facebook.react.defaults.DefaultReactNativeHost; 10 | import com.facebook.soloader.SoLoader; 11 | import java.util.List; 12 | 13 | public class MainApplication extends Application implements ReactApplication { 14 | 15 | private final ReactNativeHost mReactNativeHost = 16 | new DefaultReactNativeHost(this) { 17 | @Override 18 | public boolean getUseDeveloperSupport() { 19 | return BuildConfig.DEBUG; 20 | } 21 | 22 | @Override 23 | protected List getPackages() { 24 | @SuppressWarnings("UnnecessaryLocalVariable") 25 | List packages = new PackageList(this).getPackages(); 26 | // Packages that cannot be autolinked yet can be added manually here, for example: 27 | // packages.add(new MyReactNativePackage()); 28 | return packages; 29 | } 30 | 31 | @Override 32 | protected String getJSMainModuleName() { 33 | return "index"; 34 | } 35 | 36 | @Override 37 | protected boolean isNewArchEnabled() { 38 | return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; 39 | } 40 | 41 | @Override 42 | protected Boolean isHermesEnabled() { 43 | return BuildConfig.IS_HERMES_ENABLED; 44 | } 45 | }; 46 | 47 | @Override 48 | public ReactNativeHost getReactNativeHost() { 49 | return mReactNativeHost; 50 | } 51 | 52 | @Override 53 | public void onCreate() { 54 | super.onCreate(); 55 | SoLoader.init(this, /* native exopackage */ false); 56 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 57 | // If you opted-in for the New Architecture, we load the native entry point for this app. 58 | DefaultNewArchitectureEntryPoint.load(); 59 | } 60 | ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 21 | 22 | 23 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | example 3 | 4 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /example/android/app/src/release/java/com/example/ReactNativeFlipper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. 3 | * 4 | *

This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | package com.example; 8 | 9 | import android.content.Context; 10 | import com.facebook.react.ReactInstanceManager; 11 | 12 | /** 13 | * Class responsible of loading Flipper inside your React Native application. This is the release 14 | * flavor of it so it's empty as we don't want to load Flipper. 15 | */ 16 | public class ReactNativeFlipper { 17 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 18 | // Do nothing as we don't want to initialize Flipper on Release. 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | buildToolsVersion = "33.0.0" 6 | minSdkVersion = 21 7 | compileSdkVersion = 33 8 | targetSdkVersion = 33 9 | 10 | // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP. 11 | ndkVersion = "23.1.7779620" 12 | } 13 | repositories { 14 | google() 15 | mavenCentral() 16 | maven { 17 | url "https://plugins.gradle.org/m2/" 18 | } 19 | } 20 | dependencies { 21 | classpath("com.android.tools.build:gradle") 22 | classpath("com.facebook.react:react-native-gradle-plugin") 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Version of flipper SDK to use with React Native 28 | FLIPPER_VERSION=0.182.0 29 | 30 | # Use this property to specify which architecture you want to build. 31 | # You can also override it from the CLI using 32 | # ./gradlew -PreactNativeArchitectures=x86_64 33 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 34 | 35 | # Use this property to enable support to the new architecture. 36 | # This will allow you to use TurboModules and the Fabric render in 37 | # your application. You should enable this flag either if you want 38 | # to write custom TurboModules/Fabric components OR use libraries that 39 | # are providing them. 40 | newArchEnabled=true 41 | 42 | # Use this property to enable or disable the Hermes JS engine. 43 | # If set to false, you will be using JSC instead. 44 | hermesEnabled=true 45 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip 4 | networkTimeout=10000 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /example/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original 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 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | ############################################################################## 22 | # 23 | # Gradle start up script for POSIX generated by Gradle. 24 | # 25 | # Important for running: 26 | # 27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 28 | # noncompliant, but you have some other compliant shell such as ksh or 29 | # bash, then to run this script, type that shell name before the whole 30 | # command line, like: 31 | # 32 | # ksh Gradle 33 | # 34 | # Busybox and similar reduced shells will NOT work, because this script 35 | # requires all of these POSIX shell features: 36 | # * functions; 37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 39 | # * compound commands having a testable exit status, especially «case»; 40 | # * various built-in commands including «command», «set», and «ulimit». 41 | # 42 | # Important for patching: 43 | # 44 | # (2) This script targets any POSIX shell, so it avoids extensions provided 45 | # by Bash, Ksh, etc; in particular arrays are avoided. 46 | # 47 | # The "traditional" practice of packing multiple parameters into a 48 | # space-separated string is a well documented source of bugs and security 49 | # problems, so this is (mostly) avoided, by progressively accumulating 50 | # options in "$@", and eventually passing that to Java. 51 | # 52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 54 | # see the in-line comments for details. 55 | # 56 | # There are tweaks for specific operating systems such as AIX, CygWin, 57 | # Darwin, MinGW, and NonStop. 58 | # 59 | # (3) This script is generated from the Groovy template 60 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 61 | # within the Gradle project. 62 | # 63 | # You can find Gradle at https://github.com/gradle/gradle/. 64 | # 65 | ############################################################################## 66 | 67 | # Attempt to set APP_HOME 68 | 69 | # Resolve links: $0 may be a link 70 | app_path=$0 71 | 72 | # Need this for daisy-chained symlinks. 73 | while 74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 75 | [ -h "$app_path" ] 76 | do 77 | ls=$( ls -ld "$app_path" ) 78 | link=${ls#*' -> '} 79 | case $link in #( 80 | /*) app_path=$link ;; #( 81 | *) app_path=$APP_HOME$link ;; 82 | esac 83 | done 84 | 85 | # This is normally unused 86 | # shellcheck disable=SC2034 87 | APP_BASE_NAME=${0##*/} 88 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit 89 | 90 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 91 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 92 | 93 | # Use the maximum available, or set MAX_FD != -1 to use that value. 94 | MAX_FD=maximum 95 | 96 | warn () { 97 | echo "$*" 98 | } >&2 99 | 100 | die () { 101 | echo 102 | echo "$*" 103 | echo 104 | exit 1 105 | } >&2 106 | 107 | # OS specific support (must be 'true' or 'false'). 108 | cygwin=false 109 | msys=false 110 | darwin=false 111 | nonstop=false 112 | case "$( uname )" in #( 113 | CYGWIN* ) cygwin=true ;; #( 114 | Darwin* ) darwin=true ;; #( 115 | MSYS* | MINGW* ) msys=true ;; #( 116 | NONSTOP* ) nonstop=true ;; 117 | esac 118 | 119 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 120 | 121 | 122 | # Determine the Java command to use to start the JVM. 123 | if [ -n "$JAVA_HOME" ] ; then 124 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 125 | # IBM's JDK on AIX uses strange locations for the executables 126 | JAVACMD=$JAVA_HOME/jre/sh/java 127 | else 128 | JAVACMD=$JAVA_HOME/bin/java 129 | fi 130 | if [ ! -x "$JAVACMD" ] ; then 131 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 132 | 133 | Please set the JAVA_HOME variable in your environment to match the 134 | location of your Java installation." 135 | fi 136 | else 137 | JAVACMD=java 138 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 139 | 140 | Please set the JAVA_HOME variable in your environment to match the 141 | location of your Java installation." 142 | fi 143 | 144 | # Increase the maximum file descriptors if we can. 145 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 146 | case $MAX_FD in #( 147 | max*) 148 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 149 | # shellcheck disable=SC3045 150 | MAX_FD=$( ulimit -H -n ) || 151 | warn "Could not query maximum file descriptor limit" 152 | esac 153 | case $MAX_FD in #( 154 | '' | soft) :;; #( 155 | *) 156 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 157 | # shellcheck disable=SC3045 158 | ulimit -n "$MAX_FD" || 159 | warn "Could not set maximum file descriptor limit to $MAX_FD" 160 | esac 161 | fi 162 | 163 | # Collect all arguments for the java command, stacking in reverse order: 164 | # * args from the command line 165 | # * the main class name 166 | # * -classpath 167 | # * -D...appname settings 168 | # * --module-path (only if needed) 169 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 170 | 171 | # For Cygwin or MSYS, switch paths to Windows format before running java 172 | if "$cygwin" || "$msys" ; then 173 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 174 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 175 | 176 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 177 | 178 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 179 | for arg do 180 | if 181 | case $arg in #( 182 | -*) false ;; # don't mess with options #( 183 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 184 | [ -e "$t" ] ;; #( 185 | *) false ;; 186 | esac 187 | then 188 | arg=$( cygpath --path --ignore --mixed "$arg" ) 189 | fi 190 | # Roll the args list around exactly as many times as the number of 191 | # args, so each arg winds up back in the position where it started, but 192 | # possibly modified. 193 | # 194 | # NB: a `for` loop captures its iteration list before it begins, so 195 | # changing the positional parameters here affects neither the number of 196 | # iterations, nor the values presented in `arg`. 197 | shift # remove old arg 198 | set -- "$@" "$arg" # push replacement arg 199 | done 200 | fi 201 | 202 | # Collect all arguments for the java command; 203 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of 204 | # shell script including quotes and variable substitutions, so put them in 205 | # double quotes to make sure that they get re-expanded; and 206 | # * put everything else in single quotes, so that it's not re-expanded. 207 | 208 | set -- \ 209 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 210 | -classpath "$CLASSPATH" \ 211 | org.gradle.wrapper.GradleWrapperMain \ 212 | "$@" 213 | 214 | # Stop when "xargs" is not available. 215 | if ! command -v xargs >/dev/null 2>&1 216 | then 217 | die "xargs is not available" 218 | fi 219 | 220 | # Use "xargs" to parse quoted args. 221 | # 222 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 223 | # 224 | # In Bash we could simply go: 225 | # 226 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 227 | # set -- "${ARGS[@]}" "$@" 228 | # 229 | # but POSIX shell has neither arrays nor command substitution, so instead we 230 | # post-process each arg (as a line of input to sed) to backslash-escape any 231 | # character that might be a shell metacharacter, then use eval to reverse 232 | # that process (while maintaining the separation between arguments), and wrap 233 | # the whole thing up as a single "set" statement. 234 | # 235 | # This will of course break if any of these variables contains a newline or 236 | # an unmatched quote. 237 | # 238 | 239 | eval "set -- $( 240 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 241 | xargs -n1 | 242 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 243 | tr '\n' ' ' 244 | )" '"$@"' 245 | 246 | exec "$JAVACMD" "$@" 247 | -------------------------------------------------------------------------------- /example/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 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 50 | echo. 51 | echo Please set the JAVA_HOME variable in your environment to match the 52 | echo location of your Java installation. 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 64 | echo. 65 | echo Please set the JAVA_HOME variable in your environment to match the 66 | echo location of your Java installation. 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /example/android/link-assets-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "migIndex": 1, 3 | "data": [ 4 | { 5 | "path": "src/assets/cube.pck", 6 | "sha1": "e55b073942e0cb05956c49b976eee6716c833d41" 7 | }, 8 | { 9 | "path": "src/assets/earth.pck", 10 | "sha1": "49cc7c2f10c2413a8c1d45199bc4904f4fdc783e" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'example' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | includeBuild('../node_modules/@react-native/gradle-plugin') 5 | -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "displayName": "Godot Example" 4 | } 5 | -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | const babelEnv = api.env(); 3 | 4 | api.cache(true); 5 | 6 | const plugins = [ 7 | [ 8 | 'module-resolver', 9 | { 10 | root: ['./'], 11 | alias: { 12 | '@': './src', 13 | }, 14 | extensions: ['.tsx', '.ts', '.js'], 15 | }, 16 | ], 17 | ]; 18 | 19 | if (babelEnv === 'production') { 20 | plugins.push(['babel-plugin-transform-remove-console', {exclude: ['error', 'warn']}]); 21 | } 22 | 23 | plugins.push(["@babel/plugin-proposal-decorators", { "legacy": true }]); 24 | 25 | plugins.push(["react-native-reanimated/plugin"]); 26 | 27 | return { 28 | presets: ['module:@react-native/babel-preset'], 29 | plugins, 30 | }; 31 | }; -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import {AppRegistry} from 'react-native'; 6 | import App from './src/App'; 7 | import {name as appName} from './app.json'; 8 | 9 | AppRegistry.registerComponent(appName, () => App); 10 | -------------------------------------------------------------------------------- /example/ios/.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /example/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /example/ios/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | # Exclude problematic versions of cocoapods and activesupport that causes build failures. 4 | gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1' 5 | gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0' 6 | gem 'xcodeproj', '< 1.26.0' 7 | gem 'concurrent-ruby', '< 1.3.4' -------------------------------------------------------------------------------- /example/ios/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (3.0.7) 5 | base64 6 | nkf 7 | rexml 8 | activesupport (7.1.3.4) 9 | base64 10 | bigdecimal 11 | concurrent-ruby (~> 1.0, >= 1.0.2) 12 | connection_pool (>= 2.2.5) 13 | drb 14 | i18n (>= 1.6, < 2) 15 | minitest (>= 5.1) 16 | mutex_m 17 | tzinfo (~> 2.0) 18 | addressable (2.8.6) 19 | public_suffix (>= 2.0.2, < 6.0) 20 | algoliasearch (1.27.5) 21 | httpclient (~> 2.8, >= 2.8.3) 22 | json (>= 1.5.1) 23 | atomos (0.1.3) 24 | base64 (0.2.0) 25 | bigdecimal (3.1.8) 26 | claide (1.1.0) 27 | cocoapods (1.15.2) 28 | addressable (~> 2.8) 29 | claide (>= 1.0.2, < 2.0) 30 | cocoapods-core (= 1.15.2) 31 | cocoapods-deintegrate (>= 1.0.3, < 2.0) 32 | cocoapods-downloader (>= 2.1, < 3.0) 33 | cocoapods-plugins (>= 1.0.0, < 2.0) 34 | cocoapods-search (>= 1.0.0, < 2.0) 35 | cocoapods-trunk (>= 1.6.0, < 2.0) 36 | cocoapods-try (>= 1.1.0, < 2.0) 37 | colored2 (~> 3.1) 38 | escape (~> 0.0.4) 39 | fourflusher (>= 2.3.0, < 3.0) 40 | gh_inspector (~> 1.0) 41 | molinillo (~> 0.8.0) 42 | nap (~> 1.0) 43 | ruby-macho (>= 2.3.0, < 3.0) 44 | xcodeproj (>= 1.23.0, < 2.0) 45 | cocoapods-core (1.15.2) 46 | activesupport (>= 5.0, < 8) 47 | addressable (~> 2.8) 48 | algoliasearch (~> 1.0) 49 | concurrent-ruby (~> 1.1) 50 | fuzzy_match (~> 2.0.4) 51 | nap (~> 1.0) 52 | netrc (~> 0.11) 53 | public_suffix (~> 4.0) 54 | typhoeus (~> 1.0) 55 | cocoapods-deintegrate (1.0.5) 56 | cocoapods-downloader (2.1) 57 | cocoapods-plugins (1.0.0) 58 | nap 59 | cocoapods-search (1.0.1) 60 | cocoapods-trunk (1.6.0) 61 | nap (>= 0.8, < 2.0) 62 | netrc (~> 0.11) 63 | cocoapods-try (1.2.0) 64 | colored2 (3.1.2) 65 | concurrent-ruby (1.3.2) 66 | connection_pool (2.4.1) 67 | drb (2.2.1) 68 | escape (0.0.4) 69 | ethon (0.16.0) 70 | ffi (>= 1.15.0) 71 | ffi (1.17.0) 72 | ffi (1.17.0-aarch64-linux-gnu) 73 | ffi (1.17.0-aarch64-linux-musl) 74 | ffi (1.17.0-arm-linux-gnu) 75 | ffi (1.17.0-arm-linux-musl) 76 | ffi (1.17.0-arm64-darwin) 77 | ffi (1.17.0-x86-linux-gnu) 78 | ffi (1.17.0-x86-linux-musl) 79 | ffi (1.17.0-x86_64-darwin) 80 | ffi (1.17.0-x86_64-linux-gnu) 81 | ffi (1.17.0-x86_64-linux-musl) 82 | fourflusher (2.3.1) 83 | fuzzy_match (2.0.4) 84 | gh_inspector (1.1.3) 85 | httpclient (2.8.3) 86 | i18n (1.14.5) 87 | concurrent-ruby (~> 1.0) 88 | json (2.7.2) 89 | minitest (5.23.1) 90 | molinillo (0.8.0) 91 | mutex_m (0.2.0) 92 | nanaimo (0.3.0) 93 | nap (1.1.0) 94 | netrc (0.11.0) 95 | nkf (0.2.0) 96 | public_suffix (4.0.7) 97 | rexml (3.2.8) 98 | strscan (>= 3.0.9) 99 | ruby-macho (2.5.1) 100 | strscan (3.1.0) 101 | typhoeus (1.4.1) 102 | ethon (>= 0.9.0) 103 | tzinfo (2.0.6) 104 | concurrent-ruby (~> 1.0) 105 | xcodeproj (1.24.0) 106 | CFPropertyList (>= 2.3.3, < 4.0) 107 | atomos (~> 0.1.3) 108 | claide (>= 1.0.2, < 2.0) 109 | colored2 (~> 3.1) 110 | nanaimo (~> 0.3.0) 111 | rexml (~> 3.2.4) 112 | 113 | PLATFORMS 114 | aarch64-linux-gnu 115 | aarch64-linux-musl 116 | arm-linux-gnu 117 | arm-linux-musl 118 | arm64-darwin 119 | ruby 120 | x86-linux-gnu 121 | x86-linux-musl 122 | x86_64-darwin 123 | x86_64-linux-gnu 124 | x86_64-linux-musl 125 | 126 | DEPENDENCIES 127 | activesupport (>= 6.1.7.5, != 7.1.0) 128 | cocoapods (>= 1.13, != 1.15.1, != 1.15.0) 129 | concurrent-ruby (< 1.3.4) 130 | xcodeproj (< 1.26.0) 131 | 132 | BUNDLED WITH 133 | 2.5.11 134 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | source 'https://cdn.cocoapods.org/' 2 | 3 | using_bundler = defined? Bundler 4 | unless using_bundler 5 | puts "\nPlease re-run using:".red 6 | puts " bundle exec pod install\n\n" 7 | exit(1) 8 | end 9 | 10 | ENV['RCT_NEW_ARCH_ENABLED'] = '1' 11 | 12 | # Resolve react_native_pods.rb with node to allow for hoisting 13 | require Pod::Executable.execute_command('node', ['-p', 14 | 'require.resolve( 15 | "react-native/scripts/react_native_pods.rb", 16 | {paths: [process.argv[1]]}, 17 | )', __dir__]).strip 18 | 19 | platform :ios, min_ios_version_supported 20 | prepare_react_native_project! 21 | 22 | target 'example' do 23 | config = use_native_modules! 24 | 25 | # Flags change depending on the env values. 26 | flags = get_default_flags() 27 | 28 | use_react_native!( 29 | :path => config[:reactNativePath], 30 | # An absolute path to your application root. 31 | :app_path => "#{Pod::Config.instance.installation_root}/.." 32 | ) 33 | 34 | post_install do |installer| 35 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 36 | react_native_post_install( 37 | installer, 38 | config[:reactNativePath], 39 | :mac_catalyst_enabled => false, 40 | :ccache_enabled => true 41 | ) 42 | 43 | # Fix issue with No template named 'unary_function' in namespace in XCode 15 44 | installer.pods_project.targets.each do |target| 45 | target.build_configurations.each do |config| 46 | config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)', '_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION'] 47 | end 48 | end 49 | end 50 | end -------------------------------------------------------------------------------- /example/ios/example-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | -------------------------------------------------------------------------------- /example/ios/example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 11 | 2D86C531EB428C1D7385AAF2 /* libPods-example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C992B1E8C02CE5C555DB33CB /* libPods-example.a */; }; 12 | 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; 13 | 96300DA62D99B50F0017B15C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96300DA52D99B50F0017B15C /* AppDelegate.swift */; }; 14 | 969790742D07FB5F0063149D /* project.godot in Resources */ = {isa = PBXBuildFile; fileRef = 969790732D07FB5F0063149D /* project.godot */; }; 15 | 96D697622CD34109008FC432 /* ReactNativeGodot.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96E79FFD2CD320C100270EE4 /* ReactNativeGodot.xcframework */; }; 16 | F2051D322750828A58F73D7C /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 6D6D63580D84DB476010F438 /* PrivacyInfo.xcprivacy */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 13B07F961A680F5B00A75B9A /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = example/Images.xcassets; sourceTree = ""; }; 22 | 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = example/Info.plist; sourceTree = ""; }; 23 | 3B4392A12AC88292D35C810B /* Pods-example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.debug.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.debug.xcconfig"; sourceTree = ""; }; 24 | 5709B34CF0A7D63546082F79 /* Pods-example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-example.release.xcconfig"; path = "Target Support Files/Pods-example/Pods-example.release.xcconfig"; sourceTree = ""; }; 25 | 6D6D63580D84DB476010F438 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = example/PrivacyInfo.xcprivacy; sourceTree = ""; }; 26 | 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = example/LaunchScreen.storyboard; sourceTree = ""; }; 27 | 96300DA52D99B50F0017B15C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = example/AppDelegate.swift; sourceTree = ""; }; 28 | 96300DA72D99B5110017B15C /* example-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "example-Bridging-Header.h"; sourceTree = ""; }; 29 | 96300DA82D9F91FE0017B15C /* MetalFX.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MetalFX.framework; path = System/Library/Frameworks/MetalFX.framework; sourceTree = SDKROOT; }; 30 | 969790732D07FB5F0063149D /* project.godot */ = {isa = PBXFileReference; lastKnownFileType = text; path = project.godot; sourceTree = ""; }; 31 | 96E772B42BF79BD600B09EE0 /* hermes.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = hermes.xcframework; path = "Pods/hermes-engine/destroot/Library/Frameworks/universal/hermes.xcframework"; sourceTree = ""; }; 32 | 96E79FFD2CD320C100270EE4 /* ReactNativeGodot.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = ReactNativeGodot.xcframework; path = "/Users/seb/Projects/react-native-godot/example/node_modules/react-native-godot/../../../package/libs/ios/ReactNativeGodot.xcframework"; sourceTree = ""; }; 33 | C992B1E8C02CE5C555DB33CB /* libPods-example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-example.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; 35 | /* End PBXFileReference section */ 36 | 37 | /* Begin PBXFrameworksBuildPhase section */ 38 | 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { 39 | isa = PBXFrameworksBuildPhase; 40 | buildActionMask = 2147483647; 41 | files = ( 42 | 96D697622CD34109008FC432 /* ReactNativeGodot.xcframework in Frameworks */, 43 | 2D86C531EB428C1D7385AAF2 /* libPods-example.a in Frameworks */, 44 | ); 45 | runOnlyForDeploymentPostprocessing = 0; 46 | }; 47 | /* End PBXFrameworksBuildPhase section */ 48 | 49 | /* Begin PBXGroup section */ 50 | 1325C79119A445E4BA5750C5 /* Resources */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | 969790732D07FB5F0063149D /* project.godot */, 54 | ); 55 | name = Resources; 56 | sourceTree = ""; 57 | }; 58 | 13B07FAE1A68108700A75B9A /* example */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 13B07FB51A68108700A75B9A /* Images.xcassets */, 62 | 13B07FB61A68108700A75B9A /* Info.plist */, 63 | 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, 64 | 96300DA52D99B50F0017B15C /* AppDelegate.swift */, 65 | 6D6D63580D84DB476010F438 /* PrivacyInfo.xcprivacy */, 66 | 96300DA72D99B5110017B15C /* example-Bridging-Header.h */, 67 | ); 68 | name = example; 69 | sourceTree = ""; 70 | }; 71 | 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 96300DA82D9F91FE0017B15C /* MetalFX.framework */, 75 | 96E79FFD2CD320C100270EE4 /* ReactNativeGodot.xcframework */, 76 | 96E772B42BF79BD600B09EE0 /* hermes.xcframework */, 77 | ED297162215061F000B7C4FE /* JavaScriptCore.framework */, 78 | C992B1E8C02CE5C555DB33CB /* libPods-example.a */, 79 | ); 80 | name = Frameworks; 81 | sourceTree = ""; 82 | }; 83 | 832341AE1AAA6A7D00B99B32 /* Libraries */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | ); 87 | name = Libraries; 88 | sourceTree = ""; 89 | }; 90 | 83CBB9F61A601CBA00E9B192 = { 91 | isa = PBXGroup; 92 | children = ( 93 | 13B07FAE1A68108700A75B9A /* example */, 94 | 832341AE1AAA6A7D00B99B32 /* Libraries */, 95 | 83CBBA001A601CBA00E9B192 /* Products */, 96 | 2D16E6871FA4F8E400B85C8A /* Frameworks */, 97 | BBD78D7AC51CEA395F1C20DB /* Pods */, 98 | 1325C79119A445E4BA5750C5 /* Resources */, 99 | ); 100 | indentWidth = 2; 101 | sourceTree = ""; 102 | tabWidth = 2; 103 | usesTabs = 0; 104 | }; 105 | 83CBBA001A601CBA00E9B192 /* Products */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 13B07F961A680F5B00A75B9A /* example.app */, 109 | ); 110 | name = Products; 111 | sourceTree = ""; 112 | }; 113 | BBD78D7AC51CEA395F1C20DB /* Pods */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | 3B4392A12AC88292D35C810B /* Pods-example.debug.xcconfig */, 117 | 5709B34CF0A7D63546082F79 /* Pods-example.release.xcconfig */, 118 | ); 119 | path = Pods; 120 | sourceTree = ""; 121 | }; 122 | /* End PBXGroup section */ 123 | 124 | /* Begin PBXNativeTarget section */ 125 | 13B07F861A680F5B00A75B9A /* example */ = { 126 | isa = PBXNativeTarget; 127 | buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */; 128 | buildPhases = ( 129 | C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */, 130 | FD10A7F022414F080027D42C /* Start Packager */, 131 | 13B07F871A680F5B00A75B9A /* Sources */, 132 | 13B07F8C1A680F5B00A75B9A /* Frameworks */, 133 | 13B07F8E1A680F5B00A75B9A /* Resources */, 134 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, 135 | 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */, 136 | E235C05ADACE081382539298 /* [CP] Copy Pods Resources */, 137 | ); 138 | buildRules = ( 139 | ); 140 | dependencies = ( 141 | ); 142 | name = example; 143 | productName = example; 144 | productReference = 13B07F961A680F5B00A75B9A /* example.app */; 145 | productType = "com.apple.product-type.application"; 146 | }; 147 | /* End PBXNativeTarget section */ 148 | 149 | /* Begin PBXProject section */ 150 | 83CBB9F71A601CBA00E9B192 /* Project object */ = { 151 | isa = PBXProject; 152 | attributes = { 153 | LastUpgradeCheck = 1210; 154 | TargetAttributes = { 155 | 13B07F861A680F5B00A75B9A = { 156 | LastSwiftMigration = 1600; 157 | }; 158 | }; 159 | }; 160 | buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "example" */; 161 | compatibilityVersion = "Xcode 12.0"; 162 | developmentRegion = en; 163 | hasScannedForEncodings = 0; 164 | knownRegions = ( 165 | en, 166 | Base, 167 | ); 168 | mainGroup = 83CBB9F61A601CBA00E9B192; 169 | productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; 170 | projectDirPath = ""; 171 | projectRoot = ""; 172 | targets = ( 173 | 13B07F861A680F5B00A75B9A /* example */, 174 | ); 175 | }; 176 | /* End PBXProject section */ 177 | 178 | /* Begin PBXResourcesBuildPhase section */ 179 | 13B07F8E1A680F5B00A75B9A /* Resources */ = { 180 | isa = PBXResourcesBuildPhase; 181 | buildActionMask = 2147483647; 182 | files = ( 183 | 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, 184 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 185 | F2051D322750828A58F73D7C /* PrivacyInfo.xcprivacy in Resources */, 186 | 969790742D07FB5F0063149D /* project.godot in Resources */, 187 | ); 188 | runOnlyForDeploymentPostprocessing = 0; 189 | }; 190 | /* End PBXResourcesBuildPhase section */ 191 | 192 | /* Begin PBXShellScriptBuildPhase section */ 193 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { 194 | isa = PBXShellScriptBuildPhase; 195 | buildActionMask = 2147483647; 196 | files = ( 197 | ); 198 | inputPaths = ( 199 | "$(SRCROOT)/.xcode.env.local", 200 | "$(SRCROOT)/.xcode.env", 201 | ); 202 | name = "Bundle React Native code and images"; 203 | outputPaths = ( 204 | ); 205 | runOnlyForDeploymentPostprocessing = 0; 206 | shellPath = /bin/sh; 207 | shellScript = "set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; 208 | }; 209 | 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = { 210 | isa = PBXShellScriptBuildPhase; 211 | buildActionMask = 2147483647; 212 | files = ( 213 | ); 214 | inputFileListPaths = ( 215 | "${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-input-files.xcfilelist", 216 | ); 217 | name = "[CP] Embed Pods Frameworks"; 218 | outputFileListPaths = ( 219 | "${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks-${CONFIGURATION}-output-files.xcfilelist", 220 | ); 221 | runOnlyForDeploymentPostprocessing = 0; 222 | shellPath = /bin/sh; 223 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-frameworks.sh\"\n"; 224 | showEnvVarsInLog = 0; 225 | }; 226 | C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = { 227 | isa = PBXShellScriptBuildPhase; 228 | buildActionMask = 2147483647; 229 | files = ( 230 | ); 231 | inputFileListPaths = ( 232 | ); 233 | inputPaths = ( 234 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 235 | "${PODS_ROOT}/Manifest.lock", 236 | ); 237 | name = "[CP] Check Pods Manifest.lock"; 238 | outputFileListPaths = ( 239 | ); 240 | outputPaths = ( 241 | "$(DERIVED_FILE_DIR)/Pods-example-checkManifestLockResult.txt", 242 | ); 243 | runOnlyForDeploymentPostprocessing = 0; 244 | shellPath = /bin/sh; 245 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 246 | showEnvVarsInLog = 0; 247 | }; 248 | E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = { 249 | isa = PBXShellScriptBuildPhase; 250 | buildActionMask = 2147483647; 251 | files = ( 252 | ); 253 | inputFileListPaths = ( 254 | "${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources-${CONFIGURATION}-input-files.xcfilelist", 255 | ); 256 | name = "[CP] Copy Pods Resources"; 257 | outputFileListPaths = ( 258 | "${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources-${CONFIGURATION}-output-files.xcfilelist", 259 | ); 260 | runOnlyForDeploymentPostprocessing = 0; 261 | shellPath = /bin/sh; 262 | shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-example/Pods-example-resources.sh\"\n"; 263 | showEnvVarsInLog = 0; 264 | }; 265 | FD10A7F022414F080027D42C /* Start Packager */ = { 266 | isa = PBXShellScriptBuildPhase; 267 | buildActionMask = 2147483647; 268 | files = ( 269 | ); 270 | inputFileListPaths = ( 271 | ); 272 | inputPaths = ( 273 | ); 274 | name = "Start Packager"; 275 | outputFileListPaths = ( 276 | ); 277 | outputPaths = ( 278 | ); 279 | runOnlyForDeploymentPostprocessing = 0; 280 | shellPath = /bin/sh; 281 | shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi\n"; 282 | showEnvVarsInLog = 0; 283 | }; 284 | /* End PBXShellScriptBuildPhase section */ 285 | 286 | /* Begin PBXSourcesBuildPhase section */ 287 | 13B07F871A680F5B00A75B9A /* Sources */ = { 288 | isa = PBXSourcesBuildPhase; 289 | buildActionMask = 2147483647; 290 | files = ( 291 | 96300DA62D99B50F0017B15C /* AppDelegate.swift in Sources */, 292 | ); 293 | runOnlyForDeploymentPostprocessing = 0; 294 | }; 295 | /* End PBXSourcesBuildPhase section */ 296 | 297 | /* Begin XCBuildConfiguration section */ 298 | 13B07F941A680F5B00A75B9A /* Debug */ = { 299 | isa = XCBuildConfiguration; 300 | baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-example.debug.xcconfig */; 301 | buildSettings = { 302 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 303 | CLANG_ENABLE_MODULES = YES; 304 | COMPRESS_PNG_FILES = NO; 305 | CURRENT_PROJECT_VERSION = 11; 306 | DEVELOPMENT_TEAM = 2TE7AHNP9P; 307 | ENABLE_BITCODE = NO; 308 | INFOPLIST_FILE = example/Info.plist; 309 | INFOPLIST_KEY_CFBundleDisplayName = "Godot Example"; 310 | LD_RUNPATH_SEARCH_PATHS = ( 311 | "$(inherited)", 312 | "@executable_path/Frameworks", 313 | ); 314 | MARKETING_VERSION = 1.0; 315 | OTHER_LDFLAGS = ( 316 | "$(inherited)", 317 | "-ObjC", 318 | "-lc++", 319 | ); 320 | PRODUCT_BUNDLE_IDENTIFIER = games.calico.godotExample; 321 | PRODUCT_NAME = example; 322 | STRIP_PNG_TEXT = NO; 323 | SWIFT_OBJC_BRIDGING_HEADER = "example-Bridging-Header.h"; 324 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 325 | SWIFT_VERSION = 5.0; 326 | VERSIONING_SYSTEM = "apple-generic"; 327 | }; 328 | name = Debug; 329 | }; 330 | 13B07F951A680F5B00A75B9A /* Release */ = { 331 | isa = XCBuildConfiguration; 332 | baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-example.release.xcconfig */; 333 | buildSettings = { 334 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 335 | CLANG_ENABLE_MODULES = YES; 336 | COMPRESS_PNG_FILES = NO; 337 | CURRENT_PROJECT_VERSION = 11; 338 | DEVELOPMENT_TEAM = 2TE7AHNP9P; 339 | INFOPLIST_FILE = example/Info.plist; 340 | INFOPLIST_KEY_CFBundleDisplayName = "Godot Example"; 341 | LD_RUNPATH_SEARCH_PATHS = ( 342 | "$(inherited)", 343 | "@executable_path/Frameworks", 344 | ); 345 | MARKETING_VERSION = 1.0; 346 | OTHER_LDFLAGS = ( 347 | "$(inherited)", 348 | "-ObjC", 349 | "-lc++", 350 | ); 351 | PRODUCT_BUNDLE_IDENTIFIER = games.calico.godotExample; 352 | PRODUCT_NAME = example; 353 | STRIP_PNG_TEXT = NO; 354 | SWIFT_OBJC_BRIDGING_HEADER = "example-Bridging-Header.h"; 355 | SWIFT_VERSION = 5.0; 356 | VERSIONING_SYSTEM = "apple-generic"; 357 | }; 358 | name = Release; 359 | }; 360 | 83CBBA201A601CBA00E9B192 /* Debug */ = { 361 | isa = XCBuildConfiguration; 362 | buildSettings = { 363 | ALWAYS_SEARCH_USER_PATHS = NO; 364 | CC = "$(REACT_NATIVE_PATH)/scripts/xcode/ccache-clang.sh"; 365 | CCACHE_BINARY = /opt/homebrew/bin/ccache; 366 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 367 | CLANG_CXX_LANGUAGE_STANDARD = "c++20"; 368 | CLANG_CXX_LIBRARY = "libc++"; 369 | CLANG_ENABLE_MODULES = YES; 370 | CLANG_ENABLE_OBJC_ARC = YES; 371 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 372 | CLANG_WARN_BOOL_CONVERSION = YES; 373 | CLANG_WARN_COMMA = YES; 374 | CLANG_WARN_CONSTANT_CONVERSION = YES; 375 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 376 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 377 | CLANG_WARN_EMPTY_BODY = YES; 378 | CLANG_WARN_ENUM_CONVERSION = YES; 379 | CLANG_WARN_INFINITE_RECURSION = YES; 380 | CLANG_WARN_INT_CONVERSION = YES; 381 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 382 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 383 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 384 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 385 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 386 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 387 | CLANG_WARN_STRICT_PROTOTYPES = YES; 388 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 389 | CLANG_WARN_UNREACHABLE_CODE = YES; 390 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 391 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 392 | COPY_PHASE_STRIP = NO; 393 | CXX = "$(REACT_NATIVE_PATH)/scripts/xcode/ccache-clang++.sh"; 394 | ENABLE_STRICT_OBJC_MSGSEND = YES; 395 | ENABLE_TESTABILITY = YES; 396 | "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; 397 | GCC_C_LANGUAGE_STANDARD = gnu99; 398 | GCC_DYNAMIC_NO_PIC = NO; 399 | GCC_NO_COMMON_BLOCKS = YES; 400 | GCC_OPTIMIZATION_LEVEL = 0; 401 | GCC_PREPROCESSOR_DEFINITIONS = ( 402 | "DEBUG=1", 403 | "$(inherited)", 404 | _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION, 405 | ); 406 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 407 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 408 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 409 | GCC_WARN_UNDECLARED_SELECTOR = YES; 410 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 411 | GCC_WARN_UNUSED_FUNCTION = YES; 412 | GCC_WARN_UNUSED_VARIABLE = YES; 413 | IPHONEOS_DEPLOYMENT_TARGET = 12.4; 414 | LD = "$(REACT_NATIVE_PATH)/scripts/xcode/ccache-clang.sh"; 415 | LDPLUSPLUS = "$(REACT_NATIVE_PATH)/scripts/xcode/ccache-clang++.sh"; 416 | LD_RUNPATH_SEARCH_PATHS = ( 417 | /usr/lib/swift, 418 | "$(inherited)", 419 | ); 420 | LIBRARY_SEARCH_PATHS = ( 421 | "\"$(SDKROOT)/usr/lib/swift\"", 422 | "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", 423 | "\"$(inherited)\"", 424 | ); 425 | MTL_ENABLE_DEBUG_INFO = YES; 426 | ONLY_ACTIVE_ARCH = YES; 427 | OTHER_CFLAGS = "$(inherited)"; 428 | OTHER_CPLUSPLUSFLAGS = ( 429 | "$(OTHER_CFLAGS)", 430 | "-DFOLLY_NO_CONFIG", 431 | "-DFOLLY_MOBILE=1", 432 | "-DFOLLY_USE_LIBCPP=1", 433 | ); 434 | OTHER_LDFLAGS = "$(inherited)"; 435 | REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; 436 | SDKROOT = iphoneos; 437 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; 438 | USE_HERMES = true; 439 | }; 440 | name = Debug; 441 | }; 442 | 83CBBA211A601CBA00E9B192 /* Release */ = { 443 | isa = XCBuildConfiguration; 444 | buildSettings = { 445 | ALWAYS_SEARCH_USER_PATHS = NO; 446 | CC = "$(REACT_NATIVE_PATH)/scripts/xcode/ccache-clang.sh"; 447 | CCACHE_BINARY = /opt/homebrew/bin/ccache; 448 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 449 | CLANG_CXX_LANGUAGE_STANDARD = "c++20"; 450 | CLANG_CXX_LIBRARY = "libc++"; 451 | CLANG_ENABLE_MODULES = YES; 452 | CLANG_ENABLE_OBJC_ARC = YES; 453 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 454 | CLANG_WARN_BOOL_CONVERSION = YES; 455 | CLANG_WARN_COMMA = YES; 456 | CLANG_WARN_CONSTANT_CONVERSION = YES; 457 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 458 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 459 | CLANG_WARN_EMPTY_BODY = YES; 460 | CLANG_WARN_ENUM_CONVERSION = YES; 461 | CLANG_WARN_INFINITE_RECURSION = YES; 462 | CLANG_WARN_INT_CONVERSION = YES; 463 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 464 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 465 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 466 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 467 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 468 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 469 | CLANG_WARN_STRICT_PROTOTYPES = YES; 470 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 471 | CLANG_WARN_UNREACHABLE_CODE = YES; 472 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 473 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 474 | COPY_PHASE_STRIP = YES; 475 | CXX = "$(REACT_NATIVE_PATH)/scripts/xcode/ccache-clang++.sh"; 476 | ENABLE_NS_ASSERTIONS = NO; 477 | ENABLE_STRICT_OBJC_MSGSEND = YES; 478 | "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; 479 | GCC_C_LANGUAGE_STANDARD = gnu99; 480 | GCC_NO_COMMON_BLOCKS = YES; 481 | GCC_PREPROCESSOR_DEFINITIONS = ( 482 | "$(inherited)", 483 | _LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION, 484 | ); 485 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 486 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 487 | GCC_WARN_UNDECLARED_SELECTOR = YES; 488 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 489 | GCC_WARN_UNUSED_FUNCTION = YES; 490 | GCC_WARN_UNUSED_VARIABLE = YES; 491 | IPHONEOS_DEPLOYMENT_TARGET = 12.4; 492 | LD = "$(REACT_NATIVE_PATH)/scripts/xcode/ccache-clang.sh"; 493 | LDPLUSPLUS = "$(REACT_NATIVE_PATH)/scripts/xcode/ccache-clang++.sh"; 494 | LD_RUNPATH_SEARCH_PATHS = ( 495 | /usr/lib/swift, 496 | "$(inherited)", 497 | ); 498 | LIBRARY_SEARCH_PATHS = ( 499 | "\"$(SDKROOT)/usr/lib/swift\"", 500 | "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", 501 | "\"$(inherited)\"", 502 | ); 503 | MTL_ENABLE_DEBUG_INFO = NO; 504 | OTHER_CFLAGS = "$(inherited)"; 505 | OTHER_CPLUSPLUSFLAGS = ( 506 | "$(OTHER_CFLAGS)", 507 | "-DFOLLY_NO_CONFIG", 508 | "-DFOLLY_MOBILE=1", 509 | "-DFOLLY_USE_LIBCPP=1", 510 | ); 511 | OTHER_LDFLAGS = "$(inherited)"; 512 | REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; 513 | SDKROOT = iphoneos; 514 | USE_HERMES = true; 515 | VALIDATE_PRODUCT = YES; 516 | }; 517 | name = Release; 518 | }; 519 | /* End XCBuildConfiguration section */ 520 | 521 | /* Begin XCConfigurationList section */ 522 | 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */ = { 523 | isa = XCConfigurationList; 524 | buildConfigurations = ( 525 | 13B07F941A680F5B00A75B9A /* Debug */, 526 | 13B07F951A680F5B00A75B9A /* Release */, 527 | ); 528 | defaultConfigurationIsVisible = 0; 529 | defaultConfigurationName = Release; 530 | }; 531 | 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "example" */ = { 532 | isa = XCConfigurationList; 533 | buildConfigurations = ( 534 | 83CBBA201A601CBA00E9B192 /* Debug */, 535 | 83CBBA211A601CBA00E9B192 /* Release */, 536 | ); 537 | defaultConfigurationIsVisible = 0; 538 | defaultConfigurationName = Release; 539 | }; 540 | /* End XCConfigurationList section */ 541 | }; 542 | rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; 543 | } 544 | -------------------------------------------------------------------------------- /example/ios/example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 54 | 56 | 62 | 63 | 64 | 65 | 71 | 73 | 79 | 80 | 81 | 82 | 84 | 85 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /example/ios/example.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/example/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import React 3 | import React_RCTAppDelegate 4 | import ReactAppDependencyProvider 5 | 6 | @main 7 | class AppDelegate: RCTAppDelegate { 8 | override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { 9 | self.moduleName = "example" 10 | self.dependencyProvider = RCTAppDependencyProvider() 11 | 12 | // You can add your custom initial props in the dictionary below. 13 | // They will be passed down to the ViewController used by React Native. 14 | self.initialProps = [:] 15 | 16 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 17 | } 18 | 19 | override func sourceURL(for bridge: RCTBridge) -> URL? { 20 | self.bundleURL() 21 | } 22 | 23 | override func bundleURL() -> URL? { 24 | #if DEBUG 25 | RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") 26 | #else 27 | Bundle.main.url(forResource: "main", withExtension: "jsbundle") 28 | #endif 29 | } 30 | } -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/CALICO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/ios/example/Images.xcassets/AppIcon.appiconset/CALICO.png -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "CALICO.png", 5 | "idiom" : "universal", 6 | "platform" : "ios", 7 | "size" : "1024x1024" 8 | } 9 | ], 10 | "info" : { 11 | "author" : "xcode", 12 | "version" : 1 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /example/ios/example/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CADisableMinimumFrameDurationOnPhone 6 | 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleDisplayName 10 | Godot Example 11 | CFBundleExecutable 12 | $(EXECUTABLE_NAME) 13 | CFBundleIdentifier 14 | $(PRODUCT_BUNDLE_IDENTIFIER) 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | $(PRODUCT_NAME) 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | $(MARKETING_VERSION) 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | $(CURRENT_PROJECT_VERSION) 27 | LSRequiresIPhoneOS 28 | 29 | NSAppTransportSecurity 30 | 31 | NSAllowsArbitraryLoads 32 | 33 | 34 | UIAppFonts 35 | 36 | UILaunchStoryboardName 37 | LaunchScreen 38 | UIRequiredDeviceCapabilities 39 | 40 | armv7 41 | 42 | UISupportedInterfaceOrientations 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | UIViewControllerBasedStatusBarAppearance 49 | 50 | ITSAppUsesNonExemptEncryption 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /example/ios/example/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /example/ios/example/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyAccessedAPITypes 6 | 7 | 8 | NSPrivacyAccessedAPIType 9 | NSPrivacyAccessedAPICategorySystemBootTime 10 | NSPrivacyAccessedAPITypeReasons 11 | 12 | 35F9.1 13 | 14 | 15 | 16 | NSPrivacyAccessedAPIType 17 | NSPrivacyAccessedAPICategoryUserDefaults 18 | NSPrivacyAccessedAPITypeReasons 19 | 20 | CA92.1 21 | 22 | 23 | 24 | NSPrivacyAccessedAPIType 25 | NSPrivacyAccessedAPICategoryFileTimestamp 26 | NSPrivacyAccessedAPITypeReasons 27 | 28 | C617.1 29 | 30 | 31 | 32 | NSPrivacyAccessedAPIType 33 | NSPrivacyAccessedAPICategoryDiskSpace 34 | NSPrivacyAccessedAPITypeReasons 35 | 36 | 85F4.1 37 | 38 | 39 | 40 | NSPrivacyCollectedDataTypes 41 | 42 | NSPrivacyTracking 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/ios/link-assets-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "migIndex": 1, 3 | "data": [ 4 | { 5 | "path": "src/assets/cube.pck", 6 | "sha1": "e55b073942e0cb05956c49b976eee6716c833d41" 7 | }, 8 | { 9 | "path": "src/assets/earth.pck", 10 | "sha1": "49cc7c2f10c2413a8c1d45199bc4904f4fdc783e" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /example/ios/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 | boot_splash/bg_color=Color(0, 0, 0, 1) 14 | boot_splash/show_image=false 15 | config/icon="res://icon.png" 16 | 17 | [rendering] 18 | 19 | environment/defaults/default_clear_color=Color(0, 0, 0, 1) -------------------------------------------------------------------------------- /example/metro.config.js: -------------------------------------------------------------------------------- 1 | // metro.config.js 2 | // 3 | // with multiple workarounds for this issue with symlinks: 4 | // https://github.com/facebook/metro/issues/1 5 | // 6 | // with thanks to @johnryan () 7 | // for the pointers to multiple workaround solutions here: 8 | // https://github.com/facebook/metro/issues/1#issuecomment-541642857 9 | // 10 | // see also this discussion: 11 | // https://github.com/brodybits/create-react-native-module/issues/232 12 | 13 | const {getDefaultConfig} = require('@react-native/metro-config'); 14 | const path = require('path'); 15 | const {mergeConfig} = require('metro-config'); 16 | const exclusionList = require('metro-config/src/defaults/exclusionList'); 17 | const glob = require('glob-to-regexp'); 18 | 19 | function getBlacklist() { 20 | const nodeModuleDirs = [ 21 | glob(`${path.resolve(__dirname, '../package')}/node_modules/*`), 22 | ]; 23 | return exclusionList(nodeModuleDirs); 24 | } 25 | 26 | const defaultConfig = getDefaultConfig(__dirname); 27 | 28 | const { 29 | resolver: {sourceExts, assetExts}, 30 | } = defaultConfig; 31 | 32 | const config = { 33 | // workaround for an issue with symlinks encountered starting with 34 | // metro@0.55 / React Native 0.61 35 | // (not needed with React Native 0.60 / metro@0.54) 36 | resolver: { 37 | extraNodeModules: new Proxy( 38 | {}, 39 | { get: (_, name) => path.resolve('.', 'node_modules', name) } 40 | ), 41 | // /dist\/.*/ 42 | blacklistRE: getBlacklist(), 43 | // Treat `.pck` files as assets 44 | assetExts: [...assetExts, 'pck'], 45 | // Exclude `.pck` from being treated as source files 46 | sourceExts: sourceExts.filter(ext => ext !== 'pck'), 47 | }, 48 | 49 | // quick workaround for another issue with symlinks 50 | watchFolders: [path.resolve('.'), path.resolve('../package')], 51 | 52 | transformer: { 53 | getTransformOptions: async () => ({ 54 | transform: { 55 | experimentalImportSupport: false, 56 | inlineRequires: true, 57 | }, 58 | }), 59 | }, 60 | 61 | server: { 62 | enhanceMiddleware: (middleware) => { 63 | return (req, res, next) => { 64 | if (/\.pck/.test(req.url)) { 65 | res.setHeader('Content-Type', 'application/octet-stream'); 66 | } 67 | return middleware(req, res, next); 68 | }; 69 | }, 70 | }, 71 | }; 72 | 73 | module.exports = mergeConfig(defaultConfig, config); -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "lint": "eslint .", 9 | "start": "react-native start", 10 | "asset": "npx react-native-asset", 11 | "pod-install": "cd ios && bundle exec pod install" 12 | }, 13 | "dependencies": { 14 | "@react-navigation/native": "^7.1.5", 15 | "@react-navigation/native-stack": "^7.3.9", 16 | "@react-navigation/stack": "^7.2.9", 17 | "axios": "^1.8.4", 18 | "babel-plugin-module-resolver": "^5.0.2", 19 | "date-fns": "^4.1.0", 20 | "react": "19.0.0", 21 | "react-native": "0.78.1", 22 | "react-native-device-info": "^14.0.4", 23 | "react-native-gesture-handler": "^2.25.0", 24 | "react-native-godot": "link:../package/", 25 | "react-native-haptic-feedback": "^2.3.3", 26 | "react-native-reanimated": "^3.17.3", 27 | "react-native-safe-area-context": "^5.3.0", 28 | "react-native-screens": "^4.10.0", 29 | "react-native-sound": "^0.11.2" 30 | }, 31 | "devDependencies": { 32 | "@babel/core": "^7.25.2", 33 | "@babel/plugin-proposal-decorators": "^7.25.9", 34 | "@babel/preset-env": "^7.25.3", 35 | "@babel/runtime": "^7.25.0", 36 | "@react-native-community/cli": "15.0.1", 37 | "@react-native-community/cli-platform-android": "15.0.1", 38 | "@react-native-community/cli-platform-ios": "15.0.1", 39 | "@react-native/babel-preset": "0.78.1", 40 | "@react-native/eslint-config": "0.78.1", 41 | "@react-native/metro-config": "0.78.1", 42 | "@react-native/typescript-config": "0.78.1", 43 | "@types/react": "^19.0.0", 44 | "babel-plugin-transform-remove-console": "^6.9.4", 45 | "eslint": "^9.23.0", 46 | "glob-to-regexp": "^0.4.1", 47 | "prettier": "3.5.3", 48 | "typescript": "5.0.4" 49 | }, 50 | "engines": { 51 | "node": ">=18" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /example/react-native.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | project: { 3 | ios: {}, 4 | android: {}, 5 | }, 6 | assets: ['./src/assets'], 7 | }; -------------------------------------------------------------------------------- /example/src/App.tsx: -------------------------------------------------------------------------------- 1 | import {JSX} from 'react'; 2 | import {enableScreens} from 'react-native-screens'; 3 | enableScreens(true); 4 | 5 | import Sound from 'react-native-sound'; 6 | Sound.setCategory('Ambient', true); 7 | 8 | import Root from '@/Root'; 9 | 10 | function App(): JSX.Element { 11 | return ; 12 | } 13 | 14 | export default App; 15 | -------------------------------------------------------------------------------- /example/src/Root.tsx: -------------------------------------------------------------------------------- 1 | import {useEffect, useRef} from 'react'; 2 | import {Platform, StatusBar, View, StyleSheet} from 'react-native'; 3 | import {createStaticNavigation, NavigationContainerRef, ParamListBase} from '@react-navigation/native'; 4 | import {createNativeStackNavigator} from '@react-navigation/native-stack'; 5 | import {SafeAreaProvider} from 'react-native-safe-area-context'; 6 | import {GestureHandlerRootView} from 'react-native-gesture-handler'; 7 | import withPreventGoBack from '@/Utils/withPreventGoBack'; 8 | import {Godot, GodotProvider, GodotView} from 'react-native-godot'; 9 | 10 | import Home from '@/Screens/Home.tsx'; 11 | import CubesExample from '@/Screens/CubesExample'; 12 | import EarthExample from '@/Screens/EarthExample.tsx'; 13 | 14 | const RootStack = createNativeStackNavigator({ 15 | initialRouteName: 'Home', 16 | screenOptions: { 17 | presentation: 'card', 18 | headerStyle: {backgroundColor: 'transparent'}, 19 | gestureEnabled: true, 20 | headerShown: false, 21 | }, 22 | screens: { 23 | Home: { 24 | screen: withPreventGoBack(Home), 25 | options: { 26 | animation: 'slide_from_bottom', 27 | headerLargeTitle: true, 28 | }, 29 | }, 30 | CubesExample: { 31 | screen: CubesExample, 32 | options: { 33 | animation: 'slide_from_right', 34 | }, 35 | }, 36 | EarthExample: { 37 | screen: EarthExample, 38 | options: { 39 | animation: 'slide_from_right', 40 | }, 41 | }, 42 | }, 43 | }); 44 | 45 | const Navigation = createStaticNavigation(RootStack as any); 46 | 47 | const Root = () => { 48 | const navigationRef = useRef | undefined>(undefined); 49 | const routeNameRef = useRef(null); 50 | const testingNavigation = useRef(true); 51 | 52 | useEffect(() => { 53 | if (!GodotView) { 54 | return; 55 | } 56 | GodotView.startDrawing(); 57 | 58 | return () => { 59 | GodotView.stopDrawing(); 60 | } 61 | }, []); 62 | 63 | return ( 64 | 65 | 66 | 67 | 68 | {Platform.OS === 'android' ? ( 69 | 70 | ) : ( 71 | 72 | )} 73 | {testingNavigation.current && ( 74 | { 77 | const root = navigationRef.current?.getCurrentRoute(); 78 | 79 | if (root) { 80 | routeNameRef.current = root.name; 81 | } 82 | }} 83 | onStateChange={async _state => { 84 | const previousRouteName = routeNameRef.current; 85 | const currentRouteName = 86 | navigationRef.current?.getCurrentRoute()?.name; 87 | 88 | if (previousRouteName !== currentRouteName) { 89 | console.log( 90 | `Route changed: ${previousRouteName} => ${currentRouteName}`, 91 | ); 92 | } 93 | routeNameRef.current = currentRouteName || null; 94 | }} 95 | /> 96 | )} 97 | {!testingNavigation.current && ( 98 | 99 | 103 | 104 | )} 105 | 106 | 107 | 108 | 109 | ); 110 | }; 111 | 112 | const styles = StyleSheet.create({ 113 | container: { 114 | flex: 1, 115 | }, 116 | }); 117 | 118 | export default Root; 119 | -------------------------------------------------------------------------------- /example/src/Routes.tsx: -------------------------------------------------------------------------------- 1 | export type Routes = { 2 | Home: undefined; 3 | CubesExample: undefined; 4 | EarthExample: undefined; 5 | }; 6 | -------------------------------------------------------------------------------- /example/src/Screens/CubesExample.tsx: -------------------------------------------------------------------------------- 1 | import React, {useEffect} from 'react'; 2 | import {StyleSheet, View} from 'react-native'; 3 | import {Godot, GodotView} from 'react-native-godot'; 4 | import {useNavigation} from '@react-navigation/native'; 5 | 6 | const CubesExample: React.FC = _props => { 7 | const navigation = useNavigation(); 8 | 9 | useEffect(() => { 10 | const unsubscribe = navigation.addListener('transitionStart', (e: any) => { 11 | if (e.data.closing) { 12 | GodotView.stopDrawing(); 13 | } 14 | }); 15 | 16 | return unsubscribe; 17 | }, [navigation]); 18 | 19 | useEffect(() => { 20 | const unsubscribe = navigation.addListener('transitionEnd', (e: any) => { 21 | if (!e.data.closing) { 22 | GodotView.startDrawing(); 23 | } 24 | }); 25 | 26 | return () => { 27 | unsubscribe(); 28 | } 29 | }, [navigation]); 30 | 31 | useEffect(() => { 32 | const unsubscribe = navigation.addListener('gestureCancel', () => { 33 | GodotView.startDrawing(); 34 | }); 35 | 36 | return unsubscribe; 37 | }, [navigation]); 38 | 39 | return ( 40 | 41 | 45 | 49 | 53 | 54 | ); 55 | }; 56 | 57 | const styles = StyleSheet.create({ 58 | cube: { 59 | flex: 1, 60 | }, 61 | }); 62 | 63 | export default CubesExample; 64 | -------------------------------------------------------------------------------- /example/src/Screens/EarthExample.tsx: -------------------------------------------------------------------------------- 1 | import React, {useCallback, useEffect, useRef, useState} from 'react'; 2 | import {StyleSheet, View, Text, ActivityIndicator} from 'react-native'; 3 | import {useNavigation} from '@react-navigation/native'; 4 | import {Godot, GodotView, useGodot} from 'react-native-godot'; 5 | import axios from 'axios'; 6 | import RNReactNativeHapticFeedback from 'react-native-haptic-feedback'; 7 | import SolarCalculator from '@/Utils/SolarCalculator'; 8 | import {addHours, addMinutes} from 'date-fns'; 9 | import { SafeAreaView } from 'react-native-safe-area-context'; 10 | 11 | type Coordinates = { 12 | lat: number | null; 13 | lon: number | null; 14 | }; 15 | 16 | const EarthExample: React.FC = _props => { 17 | const navigation = useNavigation(); 18 | 19 | const earthRef = useRef(null); 20 | 21 | const coordinates = useRef({ lat: null, lon: null }); 22 | const [country, setCountry] = useState(''); 23 | const [sunrise, setSunrise] = useState(null); 24 | const [sunset, setSunset] = useState(null); 25 | const defaultTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone; 26 | const [timezone, setTimezone] = useState(defaultTimezone); 27 | const [currentDate, setCurrentDate] = useState(null); 28 | const offset = useRef(0); 29 | 30 | const {Vector3, Vector2, Quaternion, Transform3D} = useGodot(); 31 | 32 | // Some examples 33 | useEffect(() => { 34 | const pos = Vector3(3, 0, 0); 35 | console.log('Position:', pos); 36 | pos.y = 5; 37 | console.log('New Position:', pos); 38 | console.log('Vector2:', Vector2(1, 1).normalized().isNormalized()); 39 | console.log('Length:', Vector2(3, 1).length()); 40 | console.log('Quaternion:', Quaternion(0, 0, 0, 1)); 41 | console.log('Transform3D origin:', Transform3D().origin); 42 | console.log('Vector3 y:', Vector3(1, 2, 3).y); 43 | }, []); 44 | 45 | const isReady = earthRef.current?.isReady || false; 46 | 47 | useEffect(() => { 48 | if (!earthRef.current || !isReady) { 49 | return; 50 | } 51 | 52 | console.log('Earth is Ready!'); 53 | 54 | const sun = earthRef.current?.getRoot()?.getNode('Sun'); 55 | if (!sun) { 56 | return; 57 | } 58 | 59 | console.log('Sun node:', sun); 60 | // Call get_info method from the Godot script attached to the Sun node!!! 61 | // console.log(sun?.get_info()); 62 | }, [isReady]); 63 | 64 | useEffect(() => { 65 | const unsubscribe = navigation.addListener('transitionStart', (e: any) => { 66 | if (e.data.closing) { 67 | GodotView.stopDrawing(); 68 | } 69 | }); 70 | 71 | return unsubscribe; 72 | }, [navigation]); 73 | 74 | useEffect(() => { 75 | const unsubscribe = navigation.addListener('transitionEnd', (e: any) => { 76 | if (!e.data.closing) { 77 | GodotView.startDrawing(); 78 | } 79 | }); 80 | 81 | return () => { 82 | unsubscribe(); 83 | } 84 | }, [navigation]); 85 | 86 | useEffect(() => { 87 | const unsubscribe = navigation.addListener('gestureCancel', () => { 88 | GodotView.startDrawing(); 89 | }); 90 | 91 | return unsubscribe; 92 | }, [navigation]); 93 | 94 | const onMessage = useCallback((message: any) => { 95 | if (message.lat === undefined || message.lon === undefined) { 96 | return; 97 | } 98 | 99 | const newLat = Math.round(message.lat * 10000) / 10000; 100 | const newLon = Math.round(message.lon * 10000) / 10000; 101 | 102 | const oldLat = Math.round((coordinates.current.lat ?? 0) * 10000) / 10000; 103 | const oldLon = Math.round((coordinates.current.lon ?? 0) * 10000) / 10000; 104 | 105 | if (newLat === oldLat && newLon === oldLon) { 106 | return; 107 | } 108 | 109 | console.log('Message received:', message); 110 | 111 | RNReactNativeHapticFeedback.trigger('impactHeavy'); 112 | 113 | setCurrentDate(null); 114 | setTimezone(null); 115 | 116 | coordinates.current = { 117 | lat: message.lat, 118 | lon: message.lon, 119 | }; 120 | }, []); 121 | 122 | const letterToLetterEmoji = (letter: string) => { 123 | return String.fromCodePoint(letter.toLowerCase().charCodeAt(0) + 127365); 124 | }; 125 | 126 | const countryCodeToFlagEmoji = (countryCode: string) => { 127 | return Array.from(countryCode).map(letterToLetterEmoji).join(''); 128 | }; 129 | 130 | const convertTZ = (date: Date, tzString: string) => { 131 | if (tzString === 'Asia/Kolkata') { 132 | tzString = 'Asia/Calcutta'; 133 | } 134 | 135 | try { 136 | const result = date.toLocaleString('en-US', {timeZone: tzString, hour12: false}).replace(/,/g, ""); 137 | const [month, day, year, hours, minutes, seconds] = (result.match(/\d+/g) || []) as number[]; 138 | return new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds)); 139 | } catch (error) { 140 | console.log('Error converting timezone:', error); 141 | return date; 142 | } 143 | } 144 | 145 | const convertDate = (date: Date, tz: string) => { 146 | const timezoneDate = convertTZ(date, tz); 147 | return addHours(timezoneDate, date.getTimezoneOffset() / 60); 148 | }; 149 | 150 | const computeSolarData = useCallback((tz: string) => { 151 | let utc = new Date(); 152 | utc.setMilliseconds(0); 153 | utc = addMinutes(utc, offset.current); 154 | offset.current += 0; 155 | 156 | setCurrentDate(convertDate(utc, tz)); 157 | 158 | const coords = coordinates.current; 159 | if (!coords.lat || !coords.lon) { 160 | return; 161 | } 162 | const solarData = SolarCalculator(utc, coords.lat, coords.lon); 163 | setSunrise(convertDate(solarData.sunrise, tz)); 164 | setSunset(convertDate(solarData.sunset, tz)); 165 | 166 | const message = { 167 | latitude: solarData.subsolarLatitude + 1, 168 | longitude: solarData.subsolarLongitude - 15, // Why -15? 169 | }; 170 | 171 | earthRef.current?.emitMessage(message); 172 | }, [earthRef.current, timezone]); 173 | 174 | useEffect(() => { 175 | const coords = coordinates.current; 176 | if (!coords.lat || !coords.lon) { 177 | return; 178 | } 179 | 180 | // Don't use this token in your app, it's for testing purposes only 😅 181 | const accessToken = 182 | 'pk.eyJ1IjoibXVnZWViIiwiYSI6ImNsZndnMWptdzBncHozYnM2Zzh3OXhnaDAifQ.LXTzWjHgMWiiyYppgQSwWQ'; 183 | const lat = coords.lat.toFixed(4); 184 | const lon = coords.lon.toFixed(4); 185 | 186 | async function getCountryInfo() { 187 | try { 188 | const url = `https://api.mapbox.com/search/geocode/v6/reverse?longitude=${lon}&latitude=${lat}&types=country&access_token=${accessToken}`; 189 | 190 | const resp = await axios.get(url); 191 | const data = resp.data; 192 | 193 | const feature = data?.features?.[0]; 194 | const countryContext = feature?.properties?.context?.country; 195 | 196 | const countryCode = countryContext?.country_code; 197 | 198 | if (!countryCode) { 199 | setCountry(''); 200 | return; 201 | } 202 | 203 | const countryName = countryContext?.name || 'Unknown'; 204 | const emoji = countryCodeToFlagEmoji(countryCode); 205 | setCountry(`${countryName} ${emoji}`); 206 | } catch (error) {} 207 | } 208 | 209 | async function getTimezone() { 210 | try { 211 | const url = `https://api.mapbox.com/v4/examples.4ze9z6tv/tilequery/${lon},${lat}.json?access_token=${accessToken}`; 212 | 213 | const resp = await axios.get(url); 214 | const data = resp.data; 215 | 216 | const feature = data?.features?.[0]; 217 | const timezone = feature?.properties?.TZID; 218 | 219 | if (!timezone) { 220 | setTimezone(null); 221 | return; 222 | } 223 | 224 | setTimezone(timezone); 225 | computeSolarData(timezone); 226 | } catch (error) { 227 | console.error('Error getting timezone:', error); 228 | } 229 | } 230 | 231 | getCountryInfo(); 232 | getTimezone(); 233 | }, [coordinates.current]); 234 | 235 | useEffect(() => { 236 | const interval = setInterval(() => { 237 | if (timezone) { 238 | computeSolarData(timezone); 239 | } 240 | }, 1000); 241 | 242 | return () => clearInterval(interval); 243 | }, [timezone, computeSolarData]); 244 | 245 | const formatTime = (date: Date, displaySeconds: boolean = false) => { 246 | if (displaySeconds) { 247 | return date 248 | .toLocaleTimeString([], {hour: '2-digit', minute: '2-digit', second: '2-digit'}) 249 | .toLowerCase(); 250 | } 251 | 252 | return date 253 | .toLocaleTimeString([], {hour: '2-digit', minute: '2-digit'}) 254 | .toLowerCase(); 255 | } 256 | 257 | return ( 258 | 259 | 266 | 267 | {country ? country : ''} 268 | {country && (<> 269 | {currentDate ? formatTime(currentDate, true) : 'Loading...'} 270 | 🌅 {sunrise && timezone ? formatTime(sunrise) : '00:00'} 271 | 🌃 {sunset && timezone ? formatTime(sunset) : '00:00'} 272 | )} 273 | 274 | {!isReady && ( 275 | 276 | 277 | 278 | )} 279 | 280 | ); 281 | }; 282 | 283 | const styles = StyleSheet.create({ 284 | container: { 285 | flex: 1, 286 | backgroundColor: 'black', 287 | }, 288 | earth: { 289 | flex: 1, 290 | }, 291 | countryInfo: { 292 | position: 'absolute', 293 | top: 0, 294 | left: 0, 295 | padding: 20, 296 | paddingRight: 20, 297 | }, 298 | countryName: { 299 | color: 'white', 300 | fontSize: 40, 301 | marginBottom: 10, 302 | paddingRight: 20, 303 | }, 304 | time: { 305 | color: 'white', 306 | fontSize: 26, 307 | marginTop: 2, 308 | }, 309 | loading: { 310 | position: 'absolute', 311 | top: 0, 312 | left: 0, 313 | right: 0, 314 | bottom: 0, 315 | justifyContent: 'center', 316 | alignItems: 'center', 317 | backgroundColor: 'rgb(20, 20, 20)', 318 | }, 319 | }); 320 | 321 | export default EarthExample; 322 | -------------------------------------------------------------------------------- /example/src/Screens/Home.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import {ScrollView, StyleSheet, Text, View} from 'react-native'; 3 | import {useNavigation} from '@react-navigation/native'; 4 | import {RectButton} from 'react-native-gesture-handler'; 5 | import type {NativeStackNavigationProp} from '@react-navigation/native-stack'; 6 | 7 | import type {Routes} from '@/Routes'; 8 | import { GodotView } from 'react-native-godot'; 9 | 10 | export const examples = [ 11 | { 12 | screen: 'CubesExample', 13 | title: '🔢 Cubes', 14 | }, 15 | { 16 | screen: 'EarthExample', 17 | title: '🌎 Earth', 18 | }, 19 | ] as const; 20 | 21 | const Home: React.FC = _props => { 22 | const {navigate} = useNavigation>(); 23 | 24 | const onPress = React.useCallback((screen: any) => { 25 | // Do not wait for the transition to finish to start drawing 26 | GodotView.startDrawing(); 27 | navigate(screen); 28 | }, [navigate]); 29 | 30 | return ( 31 | 35 | {examples.map(thumbnail => ( 36 | onPress(thumbnail.screen)}> 39 | 40 | {thumbnail.title} 41 | ➡️ 42 | 43 | 44 | ))} 45 | 46 | ); 47 | }; 48 | 49 | const styles = StyleSheet.create({ 50 | container: { 51 | backgroundColor: '#ebf5f7', 52 | }, 53 | content: { 54 | paddingBottom: 100, 55 | backgroundColor: 'clear', 56 | }, 57 | thumbnail: { 58 | backgroundColor: 'white', 59 | padding: 20, 60 | borderBottomWidth: 2, 61 | borderColor: '#afc8e0', 62 | flexDirection: 'row', 63 | justifyContent: 'space-between', 64 | alignItems: 'center', 65 | }, 66 | title: { 67 | fontSize: 24, 68 | fontWeight: 'bold', 69 | }, 70 | arrow: { 71 | fontSize: 32, 72 | }, 73 | }); 74 | 75 | export default Home; 76 | -------------------------------------------------------------------------------- /example/src/Utils/SolarCalculator.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Sources: 3 | * https://gml.noaa.gov/grad/solcalc/ 4 | * https://github.com/NASAWorldWind/WebWorldWind/blob/develop/src/util/SunPosition.js 5 | * https://github.com/arcticio/weather-simulation/blob/master/scripts/libs/orb2/solarsystem_v2r1.js 6 | * https://worldwind.earth/explorer/ 7 | * https://www.timeanddate.com/scripts/sunmap.php 8 | * 9 | * @param {Date} utcDate 10 | * @param {Number} lat 11 | * @param {Number} lng 12 | * @returns {undefined} 13 | */ 14 | 15 | const SolarCalculator = (utcDate: Date, lat: number, lng: number) => { 16 | 17 | /** 18 | * Returns the angle in the range 0 to 360 19 | * @param {Number} angle 20 | * @returns {Number} 21 | */ 22 | const roundAngle = (angle: number) => { 23 | if (angle > 360){ 24 | angle = angle % 360; 25 | } else if (angle < 0) { 26 | angle = angle % 360 + 360; 27 | } else { 28 | angle = angle; 29 | } 30 | 31 | return angle; 32 | } 33 | 34 | const normalizedDegreesLongitude = (degrees: number) => { 35 | const lon = degrees % 360; 36 | 37 | return lon > 180 ? lon - 360 : lon < -180 ? 360 + lon : lon; 38 | } 39 | 40 | /** 41 | * 42 | * @param {Number} jd 43 | * @returns {Number} 44 | */ 45 | const calcTimeJulianCent = (jd: number) => { 46 | const t = (jd - 2451545.0) / 36525.0; 47 | 48 | return t; 49 | }; 50 | 51 | /** 52 | * 53 | * @param {Number} t 54 | * @returns {Number} 55 | */ 56 | const calcJDFromJulianCent = (t: number) => { 57 | const jd = t * 36525 + 2451545; 58 | 59 | return jd; 60 | }; 61 | 62 | /** 63 | * 64 | * @param {Number} yr 65 | * @returns {Boolean} 66 | */ 67 | const isLeapYear = (yr: number) => { 68 | return ((yr % 4 == 0 && yr % 100 != 0) || yr % 400 == 0); 69 | }; 70 | 71 | /** 72 | * 73 | * @param {Number} jd 74 | * @returns {Number} 75 | */ 76 | const calcDoyFromJD = (jd: number) => { 77 | const z = Math.floor(jd + 0.5); 78 | const f = (jd + 0.5) - z; 79 | 80 | let A; 81 | if (z < 2299161) { 82 | A = z; 83 | } else { 84 | const alpha = Math.floor((z - 1867216.25) / 36524.25); 85 | A = z + 1 + alpha - Math.floor(alpha / 4); 86 | } 87 | 88 | const B = A + 1524; 89 | const C = Math.floor((B - 122.1) / 365.25); 90 | const D = Math.floor(365.25 * C); 91 | const E = Math.floor((B - D) / 30.6001); 92 | const day = B - D - Math.floor(30.6001 * E) + f; 93 | const month = (E < 14) ? E - 1 : E - 13; 94 | const year = (month > 2) ? C - 4716 : C - 4715; 95 | 96 | const k = (isLeapYear(year) ? 1 : 2); 97 | const doy = Math.floor((275 * month) / 9) - k * Math.floor((month + 9) / 12) + day - 30; 98 | 99 | return doy; 100 | }; 101 | 102 | /** 103 | * Converts an angle in radians to degrees 104 | * @param {Number} angleRad 105 | * @returns {Number} 106 | */ 107 | const radToDeg = (angleRad: number) => { 108 | return (180.0 * angleRad / Math.PI); 109 | }; 110 | 111 | /** 112 | * Converts an angle in degrees to radians 113 | * @param {Number} angleDeg 114 | * @returns {Number} 115 | */ 116 | const degToRad = (angleDeg: number) => { 117 | return (Math.PI * angleDeg / 180.0); 118 | }; 119 | 120 | /** 121 | * Returns the geometric mean longitude of the Sun in degrees 122 | * @param {Number} t 123 | * @returns {Number} 124 | */ 125 | const calcGeometricMeanLongitudeSun = (t: number) => { 126 | let longitude = 280.46646 + 36000.76983 * t + 0.0003032 * t * t; 127 | return roundAngle(longitude); 128 | }; 129 | 130 | /** 131 | * Returns the mean anomaly of the Sun 132 | * @param {Number} t 133 | * @returns {Number} 134 | */ 135 | const calcGeomMeanAnomalySun = (t: number) => { 136 | var M = 357.52911 + t * (35999.05029 - 0.0001537 * t); 137 | return M; // in degrees 138 | }; 139 | 140 | /** 141 | * Returns the eccentricity of the Earth's orbit 142 | * @param {Number} t 143 | * @returns {Number} 144 | */ 145 | const calcEccentricityEarthOrbit = (t: number) => { 146 | const eccentricity = 0.016708634 - t * (0.000042037 + 0.0000001267 * t); 147 | return eccentricity; // unitless 148 | }; 149 | 150 | /** 151 | * Returns the Sun's equation of center in degrees 152 | * @param {Number} Julian date century 153 | * @returns {Number} degrees 154 | */ 155 | const calcSunEquationOfCenter = (t: number) => { 156 | const meanAnomaly = calcGeomMeanAnomalySun(t); 157 | const meanRad = degToRad(meanAnomaly); 158 | const sinm = Math.sin(meanRad); 159 | const sin2m = Math.sin(meanRad + meanRad); 160 | const sin3m = Math.sin(meanRad + meanRad + meanRad); 161 | 162 | // Sun's equation of the center 163 | const equation = sinm * (1.914602 - t * (0.004817 + 0.000014 * t)) + sin2m * (0.019993 - 0.000101 * t) + sin3m * 0.000289; 164 | return equation; // in degrees 165 | }; 166 | 167 | /** 168 | * Returns the true longitude of the Sun in degrees 169 | * @param {Number} t 170 | * @returns {Number} 171 | */ 172 | const calcSunTrueLongitude = (t: number) => { 173 | const meanLongitude = calcGeometricMeanLongitudeSun(t); 174 | const equation = calcSunEquationOfCenter(t); 175 | const trueLongitude = meanLongitude + equation; 176 | 177 | return trueLongitude; 178 | }; 179 | 180 | /** 181 | * Returns the apparent longitude of the Sun in degrees 182 | * @param {Number} t 183 | * @returns {Number} 184 | */ 185 | const calcSunApparentLongitude = (t: number) => { 186 | const trueLongitude = calcSunTrueLongitude(t); 187 | // TODO: seenms the omega is not completly precise (https://github.com/arcticio/weather-simulation/blob/master/scripts/libs/orb2/solarsystem_v2r1.js#L21) 188 | const omega = 125.04452 - 1934.136261 * t; 189 | const lambda = trueLongitude - 0.00569 - 0.00478 * Math.sin(degToRad(omega)); 190 | 191 | return lambda; 192 | }; 193 | 194 | /** 195 | * Returns the mean obliquity of the ecliptic in degrees 196 | * @param {Number} t 197 | * @returns {Number} 198 | */ 199 | const calcMeanObliquityOfEcliptic = (t: number) => { 200 | const seconds = 21.448 - t * (46.8150 + t * (0.00059 - t * (0.001813))); 201 | const e0 = 23.0 + (26.0 + (seconds / 60.0)) / 60.0; 202 | 203 | return e0; 204 | }; 205 | 206 | /** 207 | * 208 | * @param {Number} t 209 | * @returns {Number} degrees 210 | */ 211 | const calcObliquityCorrection = (t: number) => { 212 | const meanObliquity = calcMeanObliquityOfEcliptic(t); 213 | const omega = 125.04 - 1934.136 * t; 214 | var e = meanObliquity + 0.00256 * Math.cos(degToRad(omega)); 215 | return e; // in degrees 216 | }; 217 | 218 | /** 219 | * Returns the Sun's right ascension in degrees 220 | * @param {Number} t 221 | * @returns {Number} degrees 222 | */ 223 | const calcSunRightAscension = (t: number) => { 224 | const obliquity = calcObliquityCorrection(t); 225 | const longitude = calcSunApparentLongitude(t); 226 | const tananum = Math.cos(degToRad(obliquity)) * Math.sin(degToRad(longitude)); 227 | const tanadenom = Math.cos(degToRad(longitude)); 228 | const ascension = radToDeg(Math.atan2(tananum, tanadenom)); 229 | 230 | return roundAngle(ascension); 231 | }; 232 | 233 | /** 234 | * Returns the Sun's declination in degrees 235 | * @param {Number} t Julian date century 236 | * @returns {Number} degrees 237 | */ 238 | const calcSunDeclination = (t: number) => { 239 | const obliquity = calcObliquityCorrection(t); 240 | const apparentLongitude = calcSunApparentLongitude(t); 241 | 242 | const sint = Math.sin(degToRad(obliquity)) * Math.sin(degToRad(apparentLongitude)); 243 | const theta = radToDeg(Math.asin(sint)); 244 | return theta; 245 | }; 246 | 247 | /** 248 | * Computes the equation of time. 249 | * @param {Number} t 250 | * @returns {Number} minutes 251 | */ 252 | const calcEquationOfTime = (t: number) => { 253 | var epsilon = calcObliquityCorrection(t); 254 | var meanLongitude = calcGeometricMeanLongitudeSun(t); 255 | const eccentricity = calcEccentricityEarthOrbit(t); 256 | const meanAnomaly = calcGeomMeanAnomalySun(t); 257 | 258 | var y = Math.tan(degToRad(epsilon) / 2.0); 259 | y *= y; 260 | 261 | var sin2l0 = Math.sin(2.0 * degToRad(meanLongitude)); 262 | var sinm = Math.sin(degToRad(meanAnomaly)); 263 | var cos2l0 = Math.cos(2.0 * degToRad(meanLongitude)); 264 | var sin4l0 = Math.sin(4.0 * degToRad(meanLongitude)); 265 | var sin2m = Math.sin(2.0 * degToRad(meanAnomaly)); 266 | 267 | var Etime = y * sin2l0 - 2.0 * eccentricity * sinm + 4.0 * eccentricity * y * sinm * cos2l0 - 0.5 * y * y * sin4l0 - 1.25 * eccentricity * eccentricity * sin2m; 268 | return radToDeg(Etime) * 4.0; // in minutes of time 269 | }; 270 | 271 | /** 272 | * Returns the hour angle [radians] at sunrise; negate teh value for sunset. 273 | * @param {Number} lat Observer latitude 274 | * @param {Number} solarDec Declination 275 | * @returns {Number} radians 276 | */ 277 | const calcHourAngleSunrise = (lat: number, solarDec: number) => { 278 | var latRad = degToRad(lat); 279 | var sdRad = degToRad(solarDec); 280 | var HAarg = (Math.cos(degToRad(90.833)) / (Math.cos(latRad) * Math.cos(sdRad)) - Math.tan(latRad) * Math.tan(sdRad)); 281 | var HA = Math.acos(HAarg); 282 | return HA; // in radians (for sunset, use -HA) 283 | }; 284 | 285 | /** 286 | * 287 | * @param {Object} inputVal 288 | * @returns {Boolean} 289 | */ 290 | const isNumber = (inputVal: any) => { 291 | var oneDecimal = false; 292 | var inputStr = "" + inputVal; 293 | for (var i = 0; i < inputStr.length; i++) { 294 | var oneChar = inputStr.charAt(i); 295 | if (i == 0 && (oneChar == "-" || oneChar == "+")) { 296 | continue; 297 | } 298 | if (oneChar == "." && !oneDecimal) { 299 | oneDecimal = true; 300 | continue; 301 | } 302 | if (oneChar < "0" || oneChar > "9") { 303 | return false; 304 | } 305 | } 306 | return true; 307 | } 308 | 309 | /** 310 | * Computes the Julian day for the given Jajascript date 311 | * @param {Date} date 312 | * @returns {Number} The julian day 313 | */ 314 | const computeJulianDay = (date: Date) => { 315 | let year = date.getUTCFullYear(); 316 | // Convert from zero-based month 317 | let month = date.getUTCMonth() + 1; 318 | const day = date.getUTCDate(); 319 | 320 | if (month <= 2) { 321 | year -= 1; 322 | month += 12; 323 | } 324 | 325 | const A = Math.floor(year / 100); 326 | const B = 2 - A + Math.floor(A / 4); 327 | const JD0h = Math.floor(365.25 * (year + 4716)) + Math.floor(30.6001 * (month + 1)) + day + B - 1524.5; 328 | 329 | return JD0h; 330 | }; 331 | 332 | /** 333 | * Computes the fractional minutes for the given date 334 | * @param {Date} date 335 | * @returns {Number} The fractional minutes 336 | */ 337 | const getFractionalMinutes = (date: Date) => { 338 | const hour = date.getUTCHours(); 339 | const minute = date.getUTCMinutes(); 340 | const second = date.getUTCSeconds(); 341 | 342 | const mins = hour * 60 + minute + second / 60.0; 343 | return mins; 344 | }; 345 | 346 | /** 347 | * Calculates the azimuth and elevation of the sun for the given 348 | * observer location and time. 349 | * @param {Number} t 350 | * @param {Number} timeLocal 351 | * @param {Number} latitude 352 | * @param {Number} longitude 353 | * @param {Number} zone 354 | * @returns {Number} 355 | */ 356 | const calcSunLatLon = (t: number) => { 357 | const latitude = calcSunDeclination(t); 358 | const rightAscension = calcSunRightAscension(t); 359 | const jday = calcJDFromJulianCent(t); 360 | // Number of days (positive or negative) since Greenwich noon, Terrestrial Time, on 1 January 2000 (J2000.0) 361 | const elapsedJulianDays = jday - 2451545; 362 | const greenwichMeanSiderealTime = roundAngle(280.46061837 + 360.98564736629 * elapsedJulianDays); 363 | let longitude = normalizedDegreesLongitude(greenwichMeanSiderealTime - rightAscension); // TODO: Why -90? 364 | 365 | return { 366 | latitude: latitude, 367 | longitude: longitude, 368 | }; 369 | }; 370 | 371 | /** 372 | * 373 | * @param {Boolean} rise 374 | * @param {Number} jday 375 | * @param {Number} latitude 376 | * @param {Number} longitude 377 | * @returns {Number} The time of sunrise or sunset in minutes 378 | */ 379 | const calcSunriseSetUTC = (rise: boolean, jday: number, latitude: number, longitude: number) => { 380 | const t = calcTimeJulianCent(jday); 381 | const eqTime = calcEquationOfTime(t); 382 | const solarDec = calcSunDeclination(t); 383 | let hourAngle = calcHourAngleSunrise(latitude, solarDec); 384 | if (!rise) 385 | hourAngle = -hourAngle; 386 | const delta = longitude + radToDeg(hourAngle); 387 | const timeUTC = 720 - (4.0 * delta) - eqTime; // in minutes 388 | 389 | return timeUTC; 390 | }; 391 | 392 | /** 393 | * Calculate the time of sunrise or sunset for the given observer location and date. 394 | * @param {Boolean} rise true for sunrise, false for sunset 395 | * @param {Number} jday 396 | * @param {Number} latitude 397 | * @param {Number} longitude 398 | * @param {Number} timezone 399 | * @returns {Number} The time of sunrise or sunset in minutes 400 | */ 401 | const calcSunriseSet = (rise: boolean, jday: number, latitude: number, longitude: number, timezone: number) => { 402 | var timeUTC = calcSunriseSetUTC(rise, jday, latitude, longitude); 403 | var newTimeUTC = calcSunriseSetUTC(rise, jday + timeUTC/1440.0, latitude, longitude); 404 | let timeLocal = 0.0; 405 | 406 | if (isNumber(newTimeUTC)) { 407 | timeLocal = newTimeUTC + (timezone * 60.0); 408 | 409 | if (timeLocal < 0.0 || timeLocal >= 1440.0) { 410 | var increment = ((timeLocal < 0) ? 1 : -1) 411 | while ((timeLocal < 0.0)||(timeLocal >= 1440.0)) { 412 | timeLocal += increment * 1440.0; 413 | jday -= increment; 414 | } 415 | } 416 | } else { // No sunrise/set found 417 | var doy = calcDoyFromJD(jday) 418 | if (((latitude > 66.4) && (doy > 79) && (doy < 267)) || 419 | ((latitude < -66.4) && ((doy < 83) || (doy > 263)))) { 420 | // previous sunrise/next sunset 421 | jday = calcJDofNextPrevRiseSet(!rise, rise, jday, latitude, longitude, timezone) 422 | } else { //previous sunset/next sunrise 423 | jday = calcJDofNextPrevRiseSet(rise, rise, jday, latitude, longitude, timezone) 424 | } 425 | } 426 | 427 | return timeLocal 428 | }; 429 | 430 | /** 431 | * Calculate the Julian date of the next or previous sunrise or sunset. 432 | * @param {Boolean} next 433 | * @param {Number} rise 434 | * @param {Number} jday 435 | * @param {Number} latitude 436 | * @param {Number} longitude 437 | * @param {Number} tz 438 | * @returns {Number} 439 | */ 440 | const calcJDofNextPrevRiseSet = (next: boolean, rise: boolean, jday: number, latitude: number, longitude: number, tz: number) => { 441 | const increment = next ? 1.0 : -1.0; 442 | let time = calcSunriseSetUTC(rise, jday, latitude, longitude); 443 | 444 | while(!isNumber(time)) { 445 | jday += increment; 446 | time = calcSunriseSetUTC(rise, jday, latitude, longitude); 447 | } 448 | var timeLocal = time + tz * 60.0 449 | while ((timeLocal < 0.0) || (timeLocal >= 1440.0)) { 450 | var incr = ((timeLocal < 0) ? 1 : -1) 451 | timeLocal += (incr * 1440.0) 452 | jday -= incr 453 | } 454 | 455 | return jday; 456 | }; 457 | 458 | /*********************/ 459 | 460 | const tz = -utcDate.getTimezoneOffset() / 60; 461 | const jday = computeJulianDay(utcDate); 462 | const fractionalMinutes = getFractionalMinutes(utcDate); 463 | const julianDate = jday + fractionalMinutes / 1440.0 - tz / 24.0; 464 | const t = calcTimeJulianCent(julianDate); 465 | const sunLatLon = calcSunLatLon(t); 466 | const sunriseTimeOffset = calcSunriseSet(true, jday, lat, lng, tz); 467 | const sunsetTimeOffset = calcSunriseSet(false, jday, lat, lng, tz); 468 | const midnight = new Date(utcDate.getUTCFullYear(), utcDate.getUTCMonth(), utcDate.getUTCDate()); 469 | const sunriseTime = new Date(midnight.getTime() + sunriseTimeOffset * 60000); 470 | const sunsetTime = new Date(midnight.getTime() + sunsetTimeOffset * 60000); 471 | 472 | return { 473 | lat: lat, 474 | lng: lng, 475 | sunrise: sunriseTime, 476 | sunset: sunsetTime, 477 | subsolarLatitude: sunLatLon.latitude, 478 | subsolarLongitude: sunLatLon.longitude, 479 | }; 480 | }; 481 | 482 | export default SolarCalculator; -------------------------------------------------------------------------------- /example/src/Utils/withPreventGoBack.tsx: -------------------------------------------------------------------------------- 1 | import {useEffect} from 'react'; 2 | import {BackHandler, NativeEventSubscription} from 'react-native'; 3 | import {useIsFocused} from '@react-navigation/native'; 4 | 5 | // Prevent the user from going back to the previous screen 6 | const withPreventGoBack = (WrappedComponent: any) => { 7 | const PreventGoBackComponent = (props: any) => { 8 | const isFocused = useIsFocused(); 9 | 10 | useEffect(() => { 11 | let backHandler: NativeEventSubscription; 12 | 13 | backHandler = BackHandler.addEventListener('hardwareBackPress', () => { 14 | if (!isFocused) { 15 | return false; 16 | } 17 | 18 | BackHandler.exitApp(); 19 | console.log('Prevented going back'); 20 | return true; 21 | }); 22 | 23 | return () => { 24 | backHandler ? backHandler.remove() : null; 25 | }; 26 | }, [isFocused]); 27 | 28 | return ; 29 | }; 30 | 31 | return PreventGoBackComponent; 32 | }; 33 | 34 | export default withPreventGoBack; 35 | -------------------------------------------------------------------------------- /example/src/assets/cube.pck: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/src/assets/cube.pck -------------------------------------------------------------------------------- /example/src/assets/earth.pck: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/example/src/assets/earth.pck -------------------------------------------------------------------------------- /example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "module": "esnext", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "noImplicitAny": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx", 18 | "baseUrl": ".", 19 | "paths": { 20 | "@/*": ["./src/*"], 21 | "react": ["react-native/node_modules/@types/react"] 22 | } 23 | }, 24 | "include": ["src"], 25 | "extends": "@react-native/typescript-config/tsconfig.json" 26 | } -------------------------------------------------------------------------------- /export_presets.cfg: -------------------------------------------------------------------------------- 1 | [preset.0] 2 | 3 | name="main" 4 | platform="iOS" 5 | runnable=true 6 | advanced_options=false 7 | dedicated_server=false 8 | custom_features="" 9 | export_filter="" 10 | include_filter="project.godot" 11 | exclude_filter="" 12 | export_path="" 13 | encryption_include_filters="" 14 | encryption_exclude_filters="" 15 | encrypt_pck=false 16 | encrypt_directory=false 17 | script_export_mode=2 18 | 19 | [preset.0.options] 20 | 21 | export/distribution_type=1 22 | binary_format/architecture="universal" 23 | binary_format/embed_pck=false 24 | custom_template/debug="" 25 | custom_template/release="" 26 | debug/export_console_wrapper=0 27 | display/high_res=true 28 | -------------------------------------------------------------------------------- /gen-pck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eux 4 | 5 | PROJECT_DIR=$@ 6 | CURRENT_DIR=$(pwd) 7 | 8 | cp -r $PROJECT_DIR $PROJECT_DIR-export 9 | cd $PROJECT_DIR-export 10 | 11 | /Applications/Godot.app/Contents/MacOS/Godot --headless --export-pack "main" main.pck 12 | 13 | PROJECT_NAME=$(basename $PROJECT_DIR) 14 | 15 | mv main.pck $CURRENT_DIR/$PROJECT_NAME.pck 16 | 17 | cd $CURRENT_DIR 18 | rm -rf $PROJECT_DIR-export -------------------------------------------------------------------------------- /package/.gitignore: -------------------------------------------------------------------------------- 1 | # Prebuilt static binaries from filament 2 | *.a 3 | *.so 4 | 5 | # OSX 6 | # 7 | .DS_Store 8 | 9 | # XDE 10 | .expo/ 11 | 12 | # VSCode 13 | .vscode/ 14 | jsconfig.json 15 | 16 | # Xcode 17 | # 18 | build/ 19 | *.pbxuser 20 | !default.pbxuser 21 | *.mode1v3 22 | !default.mode1v3 23 | *.mode2v3 24 | !default.mode2v3 25 | *.perspectivev3 26 | !default.perspectivev3 27 | xcuserdata 28 | *.xccheckout 29 | *.moved-aside 30 | DerivedData 31 | *.hmap 32 | *.ipa 33 | *.xcuserstate 34 | RNFFabric.xcworkspace 35 | .xcode.env.local 36 | 37 | # Android/IJ 38 | # 39 | .classpath 40 | .cxx 41 | .gradle 42 | .idea 43 | .project 44 | .settings 45 | local.properties 46 | android.iml 47 | 48 | # Cocoapods 49 | # 50 | example/ios/Pods 51 | 52 | # Ruby 53 | example/vendor/ 54 | 55 | # node.js 56 | # 57 | node_modules/ 58 | npm-debug.log 59 | yarn-debug.log 60 | yarn-error.log 61 | 62 | # BUCK 63 | buck-out/ 64 | \.buckd/ 65 | android/app/libs 66 | android/keystores/debug.keystore 67 | 68 | # Yarn 69 | .yarn/* 70 | !.yarn/patches 71 | !.yarn/plugins 72 | !.yarn/releases 73 | !.yarn/sdks 74 | !.yarn/versions 75 | 76 | # Expo 77 | .expo/ 78 | 79 | # Turborepo 80 | .turbo/ 81 | 82 | # generated by bob 83 | lib/ 84 | 85 | # Ignore bullet3 library code 86 | android/libs/bullet3 87 | ios/libs/bullet3 88 | 89 | # Yarn 90 | .yarn/* 91 | !.yarn/patches 92 | !.yarn/plugins 93 | !.yarn/releases 94 | !.yarn/sdks 95 | !.yarn/versions -------------------------------------------------------------------------------- /package/android/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | ios/.xcode.env.local 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | *.hprof 33 | .cxx/ 34 | *.keystore 35 | !debug.keystore 36 | 37 | # node.js 38 | # 39 | node_modules/ 40 | npm-debug.log 41 | yarn-error.log 42 | 43 | # fastlane 44 | # 45 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 46 | # screenshots whenever they are needed. 47 | # For more information about the recommended setup visit: 48 | # https://docs.fastlane.tools/best-practices/source-control/ 49 | 50 | **/fastlane/report.xml 51 | **/fastlane/Preview.html 52 | **/fastlane/screenshots 53 | **/fastlane/test_output 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # Ruby / CocoaPods 59 | /ios/Pods/ 60 | /vendor/bundle/ 61 | 62 | # Temporary files created by Metro to check the health of the file watcher 63 | .metro-health-check* 64 | 65 | # testing 66 | /coverage 67 | -------------------------------------------------------------------------------- /package/android/.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | arguments=--init-script /var/folders/xp/q9zpqk1j1yj5qc3bgwybkz1h0000gn/T/db3b08fc4a9ef609cb16b96b200fa13e563f396e9bb1ed0905fdab7bc3bc513b.gradle --init-script /var/folders/xp/q9zpqk1j1yj5qc3bgwybkz1h0000gn/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle 2 | auto.sync=false 3 | build.scans.enabled=false 4 | connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(8.9)) 5 | connection.project.dir= 6 | eclipse.preferences.version=1 7 | gradle.user.home= 8 | java.home=/Library/Java/JavaVirtualMachines/jdk-19.jdk/Contents/Home 9 | jvm.arguments= 10 | offline.mode=false 11 | override.workspace.settings=true 12 | show.console.view=true 13 | show.executions.view=true 14 | -------------------------------------------------------------------------------- /package/android/build.gradle: -------------------------------------------------------------------------------- 1 | import java.nio.file.Paths 2 | import org.apache.tools.ant.taskdefs.condition.Os 3 | 4 | buildscript { 5 | // The Android Gradle plugin is only required when opening the android folder stand-alone. 6 | // This avoids unnecessary downloads and potential conflicts when the library is included as a 7 | // module dependency in an application project. 8 | // ref: https://docs.gradle.org/current/userguide/tutorial_using_tasks.html#sec:build_script_external_dependencies 9 | if (project == rootProject) { 10 | repositories { 11 | google() 12 | } 13 | dependencies { 14 | // This should reflect the Gradle plugin version used by 15 | // the minimum React Native version supported. 16 | classpath 'com.android.tools.build:gradle:3.4.1' 17 | } 18 | } 19 | } 20 | 21 | def reactNativeArchitectures() { 22 | def value = project.getProperties().get("reactNativeArchitectures") 23 | return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] 24 | } 25 | 26 | static def findNodeModules(baseDir) { 27 | def basePath = baseDir.toPath().normalize() 28 | // Node's module resolution algorithm searches up to the root directory, 29 | // after which the base path will be null 30 | while (basePath) { 31 | def nodeModulesPath = Paths.get(basePath.toString(), "node_modules") 32 | def reactNativePath = Paths.get(nodeModulesPath.toString(), "react-native") 33 | if (nodeModulesPath.toFile().exists() && reactNativePath.toFile().exists()) { 34 | return nodeModulesPath.toString() 35 | } 36 | basePath = basePath.getParent() 37 | } 38 | throw new GradleException("react-native-engine: Failed to find node_modules/ path!") 39 | } 40 | 41 | def nodeModules = findNodeModules(projectDir) 42 | logger.warn("react-native-engine: node_modules/ found at: ${nodeModules}") 43 | 44 | def sourceBuild = false 45 | def defaultDir 46 | 47 | if (rootProject.ext.has('reactNativeAndroidRoot')) { 48 | defaultDir = rootProject.ext.get('reactNativeAndroidRoot') 49 | } else if (findProject(':ReactAndroid') != null) { 50 | sourceBuild = true 51 | defaultDir = project(':ReactAndroid').projectDir 52 | } else { 53 | defaultDir = file("$nodeModules/react-native") 54 | } 55 | 56 | if (!defaultDir.exists()) { 57 | throw new GradleException( 58 | "${project.name}: React Native android directory (node_modules/react-native/android) does not exist! Resolved node_modules to: ${nodeModules}" 59 | ) 60 | } 61 | 62 | def buildType = "debug" 63 | if (gradle.startParameter.taskRequests.args[0].toString().contains("Release")) { 64 | buildType = "release" 65 | } else if (gradle.startParameter.taskRequests.args[0].toString().contains("Debug")) { 66 | buildType = "debug" 67 | } 68 | 69 | def reactProperties = new Properties() 70 | file("$nodeModules/react-native/ReactAndroid/gradle.properties").withInputStream { reactProperties.load(it) } 71 | def FULL_RN_VERSION = (System.getenv("REACT_NATIVE_OVERRIDE_VERSION") ?: reactProperties.getProperty("VERSION_NAME")) 72 | def REACT_NATIVE_VERSION = FULL_RN_VERSION.split("\\.")[1].toInteger() 73 | def ENABLE_PREFAB = REACT_NATIVE_VERSION > 68 74 | 75 | def JS_RUNTIME = { 76 | // Override JS runtime with environment variable 77 | if (System.getenv("JS_RUNTIME")) { 78 | return System.getenv("JS_RUNTIME") 79 | } 80 | 81 | // Check if Hermes is enabled in app setup 82 | def appProject = rootProject.allprojects.find { it.plugins.hasPlugin('com.android.application') } 83 | if (appProject?.hermesEnabled?.toBoolean() || appProject?.ext?.react?.enableHermes?.toBoolean()) { 84 | return "hermes" 85 | } 86 | 87 | // Use JavaScriptCore (JSC) by default 88 | return "jsc" 89 | }.call() 90 | 91 | def jsRuntimeDir = { 92 | if (JS_RUNTIME == "hermes") { 93 | return Paths.get("$nodeModules/react-native", "sdks", "hermes") 94 | } else { 95 | return Paths.get("$nodeModules/react-native", "ReactCommon", "jsi") 96 | } 97 | }.call() 98 | 99 | def reactNativeRootDir = file("$nodeModules/react-native") 100 | 101 | logger.warn("[react-native-engine] RN Version: ${REACT_NATIVE_VERSION} / ${FULL_RN_VERSION}") 102 | logger.warn("[react-native-engine] isSourceBuild: ${sourceBuild}") 103 | logger.warn("[react-native-engine] buildType: ${buildType}") 104 | logger.warn("[react-native-engine] buildDir: ${buildDir}") 105 | logger.warn("[react-native-engine] node_modules: ${nodeModules}") 106 | logger.warn("[react-native-engine] Enable Prefab: ${ENABLE_PREFAB}") 107 | logger.warn("[react-native-engine] JS Runtime: ${JS_RUNTIME}") 108 | 109 | apply plugin: "com.android.library" 110 | 111 | if (isNewArchitectureEnabled()) { 112 | apply plugin: "com.facebook.react" 113 | } 114 | 115 | def getExtOrDefault(name) { 116 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["Engine_" + name] 117 | } 118 | 119 | def getExtOrIntegerDefault(name) { 120 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["Engine_" + name]).toInteger() 121 | } 122 | 123 | def supportsNamespace() { 124 | def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.') 125 | def major = parsed[0].toInteger() 126 | def minor = parsed[1].toInteger() 127 | 128 | // Namespace support was added in 7.3.0 129 | return (major == 7 && minor >= 3) || major >= 8 130 | } 131 | 132 | def isNewArchitectureEnabled() { 133 | // To opt-in for the New Architecture, you can either: 134 | // - Set `newArchEnabled` to true inside the `gradle.properties` file 135 | // - Invoke gradle with `-newArchEnabled=true` 136 | // - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true` 137 | return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true" 138 | } 139 | 140 | def toPlatformFileString(String path) { 141 | if (Os.isFamily(Os.FAMILY_WINDOWS)) { 142 | path = path.replace(File.separatorChar, '/' as char) 143 | } 144 | return path 145 | } 146 | 147 | logger.warn("[react-native-engine] Thanks for using react-native-engine 💜") 148 | 149 | android { 150 | if (supportsNamespace()) { 151 | namespace "games.calico" 152 | 153 | sourceSets { 154 | main { 155 | manifest.srcFile "src/main/AndroidManifestNew.xml" 156 | } 157 | } 158 | } 159 | 160 | ndkVersion getExtOrDefault("ndkVersion") 161 | compileSdkVersion getExtOrIntegerDefault("compileSdkVersion") 162 | 163 | defaultConfig { 164 | minSdkVersion getExtOrIntegerDefault("minSdkVersion") 165 | targetSdkVersion getExtOrIntegerDefault("targetSdkVersion") 166 | versionCode 1 167 | versionName "1.0" 168 | buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() 169 | 170 | externalNativeBuild { 171 | cmake { 172 | cppFlags "-fexceptions", "-frtti", "-std=c++1y", "-DONANDROID" 173 | abiFilters (*reactNativeArchitectures()) 174 | arguments '-DANDROID_STL=c++_shared', 175 | "-DREACT_NATIVE_VERSION=${REACT_NATIVE_VERSION}", 176 | "-DNODE_MODULES_DIR=${nodeModules}", 177 | "-DREACT_NATIVE_DIR=${toPlatformFileString(reactNativeRootDir.path)}", 178 | "-DJS_RUNTIME=${JS_RUNTIME}", 179 | "-DJS_RUNTIME_DIR=${jsRuntimeDir}" 180 | 181 | } 182 | } 183 | } 184 | 185 | buildFeatures { 186 | prefab true 187 | prefabPublishing true 188 | buildConfig true 189 | } 190 | 191 | buildTypes { 192 | debug { 193 | // if you need to debug your native module in Android Studio, this 194 | // will prevent Gradle from stripping out the native symbols that 195 | // are needed 196 | packagingOptions { 197 | doNotStrip '../libs/android/*/libengine.so' 198 | jniLibs.useLegacyPackaging = true 199 | excludes = [ 200 | "META-INF", 201 | "META-INF/**", 202 | "**/libc++_shared.so", 203 | "**/libfbjni.so", 204 | "**/libjsi.so", 205 | "**/libfolly_json.so", 206 | "**/libfolly_runtime.so", 207 | "**/libglog.so", 208 | "**/libhermes.so", 209 | "**/libhermes-executor-debug.so", 210 | "**/libhermes_executor.so", 211 | "**/libreactnativejni.so", 212 | "**/libturbomodulejsijni.so", 213 | "**/libreact_nativemodule_core.so", 214 | "**/libjscexecutor.so", 215 | "**/libv8executor.so", 216 | ] 217 | } 218 | 219 | ndk { 220 | debugSymbolLevel 'full' 221 | } 222 | 223 | externalNativeBuild { 224 | cmake { 225 | if (JS_RUNTIME == "hermes") { 226 | arguments "-DHERMES_ENABLE_DEBUGGER=1" 227 | } else { 228 | arguments "-DHERMES_ENABLE_DEBUGGER=0" 229 | } 230 | } 231 | } 232 | } 233 | 234 | release { 235 | minifyEnabled false 236 | 237 | externalNativeBuild { 238 | cmake { 239 | arguments "-DHERMES_ENABLE_DEBUGGER=0" 240 | } 241 | } 242 | } 243 | } 244 | 245 | lintOptions { 246 | disable "GradleCompatible" 247 | } 248 | 249 | compileOptions { 250 | sourceCompatibility JavaVersion.VERSION_1_8 251 | targetCompatibility JavaVersion.VERSION_1_8 252 | } 253 | 254 | sourceSets.main { 255 | jniLibs { 256 | srcDirs += ['../libs/android'] 257 | } 258 | } 259 | 260 | externalNativeBuild { 261 | cmake { 262 | path("src/main/cpp/CMakeLists.txt") 263 | } 264 | } 265 | } 266 | 267 | repositories { 268 | mavenCentral() 269 | google() 270 | } 271 | 272 | dependencies { 273 | // From node_modules 274 | implementation "com.facebook.react:react-native:+" 275 | 276 | implementation "com.facebook.react:react-android" 277 | if (JS_RUNTIME == "hermes") { 278 | implementation "com.facebook.react:hermes-android" // version substituted by RNGP 279 | } 280 | } -------------------------------------------------------------------------------- /package/android/gradle.properties: -------------------------------------------------------------------------------- 1 | Engine_kotlinVersion=1.7.0 2 | Engine_minSdkVersion=21 3 | Engine_targetSdkVersion=31 4 | Engine_compileSdkVersion=31 5 | Engine_ndkversion=21.4.7075529 -------------------------------------------------------------------------------- /package/android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /package/android/src/main/AndroidManifestNew.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /package/android/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(rnengine) 2 | cmake_minimum_required(VERSION 3.8) 3 | 4 | set (CMAKE_VERBOSE_MAKEFILE ON) 5 | set (CMAKE_CXX_STANDARD 17) 6 | 7 | set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSK_GL -DSK_GANESH -DSK_BUILD_FOR_ANDROID -DFOLLY_NO_CONFIG=1 -DFOLLY_HAVE_CLOCK_GETTIME=1 -DFOLLY_HAVE_MEMRCHR=1 -DFOLLY_USE_LIBCPP=1 -DFOLLY_MOBILE=1 -DON_ANDROID -DONANDROID") 8 | string(APPEND CMAKE_CXX_FLAGS " -DHERMES_ENABLE_DEBUGGER=${HERMES_ENABLE_DEBUGGER}") 9 | 10 | message("-- REACT_NATIVE_DIR : " ${REACT_NATIVE_DIR}) 11 | 12 | include("${REACT_NATIVE_DIR}/ReactAndroid/cmake-utils/folly-flags.cmake") 13 | add_compile_options(${folly_FLAGS}) 14 | 15 | message("-- REACT NATIVE VERSION : " ${REACT_NATIVE_VERSION}) 16 | 17 | set (PACKAGE_NAME "rnengine") 18 | 19 | # Consume shared libraries and headers from prefabs 20 | find_package(fbjni REQUIRED CONFIG) 21 | find_package(ReactAndroid REQUIRED CONFIG) 22 | if(${JS_RUNTIME} STREQUAL "hermes") 23 | find_package(hermes-engine REQUIRED CONFIG) 24 | endif() 25 | 26 | add_library( # Sets the name of the library. 27 | rnengine 28 | 29 | # Sets the library as a shared library. 30 | SHARED 31 | 32 | # Provides a relative path to your source file(s). 33 | native-lib.cpp) 34 | 35 | # includes 36 | 37 | target_include_directories( 38 | ${PACKAGE_NAME} 39 | PRIVATE 40 | "${REACT_NATIVE_DIR}/ReactAndroid/src/main/jni/react/turbomodule" 41 | "${REACT_NATIVE_DIR}/ReactCommon" 42 | "${REACT_NATIVE_DIR}/ReactCommon/callinvoker" 43 | "${REACT_NATIVE_DIR}/ReactCommon/react/renderer/graphics/platform/cxx" 44 | "${REACT_NATIVE_DIR}/ReactCommon/runtimeexecutor" 45 | "${REACT_NATIVE_DIR}/ReactCommon/yoga" 46 | ) 47 | 48 | # build shared lib 49 | 50 | set_target_properties(${PACKAGE_NAME} PROPERTIES LINKER_LANGUAGE CXX) 51 | 52 | find_library( # Sets the name of the path variable. 53 | LOG_LIB 54 | 55 | # Specifies the name of the NDK library that 56 | # you want CMake to locate. 57 | log 58 | ) 59 | message("-- LOG : " ${LOG_LIB}) 60 | 61 | target_link_libraries( # Specifies the target library. 62 | ${PACKAGE_NAME} 63 | ${LOG_LIB} 64 | ReactAndroid::folly_runtime 65 | ReactAndroid::glog 66 | ReactAndroid::jsi 67 | ReactAndroid::reactnativejni 68 | fbjni::fbjni 69 | ) 70 | 71 | if(${JS_RUNTIME} STREQUAL "hermes") 72 | string(APPEND CMAKE_CXX_FLAGS " -DJS_RUNTIME_HERMES=1") 73 | # From prefab from module `com.facebook.react:hermes-android` 74 | set(HERMES_LIB hermes-engine::libhermes) 75 | target_link_libraries( 76 | ${PACKAGE_NAME} 77 | ${HERMES_LIB} 78 | ) 79 | if (${HERMES_ENABLE_DEBUGGER}) 80 | set(HERMES_EXECUTOR_LIB ReactAndroid::hermes_executor) 81 | target_link_libraries( 82 | ${PACKAGE_NAME} 83 | ${HERMES_EXECUTOR_LIB} 84 | ) 85 | endif() 86 | elseif(${JS_RUNTIME} STREQUAL "jsc") 87 | string(APPEND CMAKE_CXX_FLAGS " -DJS_RUNTIME_JSC=1") 88 | set(JSEXECUTOR_LIB ReactAndroid::jscexecutor) 89 | target_link_libraries(${PACKAGE_NAME} ${JSEXECUTOR_LIB}) 90 | else() 91 | message(FATAL_ERROR "Unknown JS runtime ${JS_RUNTIME}.") 92 | endif() -------------------------------------------------------------------------------- /package/android/src/main/cpp/native-lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | -------------------------------------------------------------------------------- /package/android/src/main/java/games/calico/EngineJsiModule.java: -------------------------------------------------------------------------------- 1 | package games.calico; 2 | 3 | import android.util.Log; 4 | 5 | import androidx.annotation.NonNull; 6 | 7 | import com.facebook.react.bridge.ReactApplicationContext; 8 | import com.facebook.react.turbomodule.core.CallInvokerHolderImpl; 9 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 10 | import com.facebook.react.bridge.ReactMethod; 11 | import com.facebook.react.module.annotations.ReactModule; 12 | import java.lang.ref.WeakReference; 13 | 14 | @ReactModule(name = "EngineJsiModule") 15 | public class EngineJsiModule extends ReactContextBaseJavaModule { 16 | public static final String NAME = "EngineJsiModule"; 17 | public static native void engine_init(long runtimePtr, CallInvokerHolderImpl callInvoker); 18 | 19 | private final WeakReference weakReactContext; 20 | 21 | public EngineJsiModule(ReactApplicationContext reactContext) { 22 | super(reactContext); 23 | this.weakReactContext = new WeakReference<>(reactContext); 24 | } 25 | 26 | @NonNull 27 | @Override 28 | public String getName() { 29 | return NAME; 30 | } 31 | 32 | @ReactMethod(isBlockingSynchronousMethod = true) 33 | public boolean install() { 34 | try { 35 | // Load our dynamic library 36 | System.loadLibrary("engine"); 37 | } catch (Exception ex) { 38 | System.err.println("Could not load Engine library"); 39 | return false; 40 | } 41 | 42 | Log.i(NAME, "Engine Loaded!"); 43 | 44 | try { 45 | ReactApplicationContext context = weakReactContext.get(); 46 | if (context == null) { 47 | Log.e(NAME, "React Application Context was null!"); 48 | return false; 49 | } 50 | var jsContext = context.getJavaScriptContextHolder(); 51 | var runtimePtr = jsContext.get(); 52 | var callInvoker = (CallInvokerHolderImpl)context.getCatalystInstance().getJSCallInvokerHolder(); 53 | 54 | Log.i(NAME, "Initializing Engine..."); 55 | 56 | if (jsContext.get() != 0) { 57 | EngineJsiModule.engine_init(runtimePtr, callInvoker); 58 | Log.i(NAME, "Engine initialized yeahhh"); 59 | 60 | return true; 61 | } else { 62 | Log.e(NAME,"Failed to initialize engine: no runtime"); 63 | return false; 64 | } 65 | } catch (Exception exception) { 66 | Log.e(NAME, "Failed to initialize engine", exception); 67 | return false; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /package/android/src/main/java/games/calico/EngineJsiPackage.java: -------------------------------------------------------------------------------- 1 | package games.calico; 2 | 3 | import androidx.annotation.NonNull; 4 | import java.util.Collections; 5 | import java.util.List; 6 | import com.facebook.react.ReactPackage; 7 | import com.facebook.react.bridge.NativeModule; 8 | import com.facebook.react.bridge.ReactApplicationContext; 9 | import com.facebook.react.uimanager.ViewManager; 10 | 11 | public class EngineJsiPackage implements ReactPackage { 12 | @NonNull 13 | @Override 14 | public List createNativeModules(@NonNull ReactApplicationContext reactContext) { 15 | return List.of(new EngineJsiModule(reactContext)); 16 | } 17 | 18 | @NonNull 19 | @Override 20 | public List createViewManagers(@NonNull ReactApplicationContext reactContext) { 21 | return Collections.emptyList(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /package/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./src"; -------------------------------------------------------------------------------- /package/ios/GodotModule.mm: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import 4 | #import 5 | #import 6 | #import 7 | 8 | #import 9 | #import 10 | 11 | using namespace facebook; 12 | 13 | @implementation GodotModule { 14 | GodotManager *godotManager; 15 | std::shared_ptr jsCallInvoker; 16 | } 17 | 18 | RCT_EXPORT_MODULE() 19 | @synthesize bridge = _bridge; 20 | 21 | #pragma Accessors 22 | 23 | - (GodotManager *)manager { 24 | return godotManager; 25 | } 26 | 27 | #pragma Setup and invalidation 28 | 29 | + (BOOL)requiresMainQueueSetup { 30 | return NO; 31 | } 32 | 33 | - (void)invalidate { 34 | if (godotManager != nil) { 35 | [godotManager invalidate]; 36 | } 37 | godotManager = nil; 38 | } 39 | 40 | RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install) 41 | { 42 | if (godotManager != nil) { 43 | // Already initialized, ignore call. 44 | return @true; 45 | } 46 | 47 | RCTCxxBridge *cxxBridge = (RCTCxxBridge *)self.bridge; 48 | if (!jsCallInvoker) { 49 | jsCallInvoker = cxxBridge.jsCallInvoker; 50 | } 51 | 52 | godotManager = [[GodotManager alloc] initWithBridge:_bridge jsInvoker:jsCallInvoker]; 53 | 54 | return @true; 55 | } 56 | 57 | #ifdef RCT_NEW_ARCH_ENABLED 58 | - (std::shared_ptr)getTurboModule: 59 | (const facebook::react::ObjCTurboModule::InitParams &)params { 60 | jsCallInvoker = params.jsInvoker; 61 | return std::make_shared(params); 62 | } 63 | #endif 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /package/libs/android/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/package/libs/android/.gitkeep -------------------------------------------------------------------------------- /package/libs/ios/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/package/libs/ios/.gitkeep -------------------------------------------------------------------------------- /package/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-godot", 3 | "version": "0.0.9", 4 | "description": "Bring Godot to React Native.", 5 | "main": "lib/commonjs/index", 6 | "module": "lib/module/index", 7 | "types": "lib/typescript/src/index.d.ts", 8 | "react-native": "src/index.ts", 9 | "source": "src/index.ts", 10 | "files": [ 11 | "android", 12 | "ios", 13 | "lib/commonjs", 14 | "lib/module", 15 | "lib/typescript", 16 | "libs/ios/.gitkeep", 17 | "libs/android/.gitkeep", 18 | "src", 19 | "index.ts", 20 | "react-native-godot-utils.rb", 21 | "react-native-godot.podspec", 22 | "tsconfig.json" 23 | ], 24 | "scripts": { 25 | "typescript": "tsc --noEmit", 26 | "prepack": "bob build" 27 | }, 28 | "keywords": [ 29 | "react-native", 30 | "ios", 31 | "android", 32 | "godot", 33 | "game", 34 | "engine", 35 | "3d", 36 | "rendering", 37 | "gltf", 38 | "model", 39 | "threejs", 40 | "physics", 41 | "opengl", 42 | "metal", 43 | "vulkan" 44 | ], 45 | "repository": { 46 | "type": "git", 47 | "url": "git+https://github.com/calico-games/react-native-godot.git" 48 | }, 49 | "author": "Calico Games (https://github.com/calico-games)", 50 | "license": "UNLICENSED", 51 | "homepage": "https://github.com/calico-games/react-native-godot", 52 | "publishConfig": { 53 | "registry": "https://registry.npmjs.org/", 54 | "access": "public" 55 | }, 56 | "devDependencies": { 57 | "@types/react": "^19.0.0", 58 | "react": "^19.0.0", 59 | "react-native": "^0.78.1", 60 | "react-native-builder-bob": "^0.39.0", 61 | "typescript": "5.0.4" 62 | }, 63 | "resolutions": { 64 | "@types/react": "^18.2.44", 65 | "@react-native-community/cli": "^14.0.0-alpha.4" 66 | }, 67 | "peerDependencies": { 68 | "react": "*", 69 | "react-native": "*" 70 | }, 71 | "eslintIgnore": [ 72 | "node_modules/", 73 | "lib/" 74 | ], 75 | "prettier": { 76 | "quoteProps": "consistent", 77 | "singleQuote": true, 78 | "tabWidth": 2, 79 | "trailingComma": "es5", 80 | "useTabs": false 81 | }, 82 | "codegenConfig": { 83 | "name": "RNGodot", 84 | "type": "all", 85 | "jsSrcsDir": "src/specs", 86 | "android": { 87 | "javaPackageName": "games.calico.godot" 88 | } 89 | }, 90 | "react-native-builder-bob": { 91 | "source": "src", 92 | "output": "lib", 93 | "targets": [ 94 | "commonjs", 95 | "module", 96 | [ 97 | "typescript", 98 | { 99 | "project": "tsconfig.json" 100 | } 101 | ] 102 | ] 103 | }, 104 | "directories": { 105 | "lib": "lib" 106 | }, 107 | "bugs": { 108 | "url": "https://github.com/calico/react-native-godot/issues" 109 | }, 110 | "dependencies": {} 111 | } 112 | -------------------------------------------------------------------------------- /package/react-native-godot-utils.rb: -------------------------------------------------------------------------------- 1 | require 'net/http' 2 | 3 | def download_prebuilt(react_native_path, version) 4 | url = prebuilt_url(version) 5 | download_stable(react_native_path, version) 6 | return {:http => url} 7 | end 8 | 9 | # HELPERS 10 | 11 | def prebuilt_url(version) 12 | return "https://storage.googleapis.com/react-native-godot/react-native-godot-ios-#{version}.zip" 13 | end 14 | 15 | 16 | def library_dir() 17 | return File.join(Pod::Config.instance.project_pods_root, "package/libs") 18 | end 19 | 20 | def download_stable(react_native_path, version) 21 | url = prebuilt_url(version) 22 | download_xcframework(react_native_path, url, version) 23 | end 24 | 25 | def download_xcframework(react_native_path, url, version) 26 | destination_dir = "#{react_native_path}/libs/ios" 27 | zip_file = "#{destination_dir}/react-native-godot-ios-#{version}.zip" 28 | xcframework_dir = "#{destination_dir}/ReactNativeGodot.xcframework" 29 | 30 | if File.exist?(zip_file) 31 | react_native_godot_log("Using cached prebuilt at #{zip_file}") 32 | 33 | if File.exist?(xcframework_dir) 34 | react_native_godot_log("Prebuilt already extracted at #{xcframework_dir}") 35 | return zip_file 36 | end 37 | else 38 | react_native_godot_log("Downloading prebuilt from URL: #{url}") 39 | 40 | # Download to a temporary file first so we don't cache incomplete downloads. 41 | tmp_file = "#{library_dir()}/react-native-godot-ios.download" 42 | 43 | `mkdir -p "#{library_dir()}" && 44 | curl "#{url}" -Lo "#{tmp_file}" && 45 | mv "#{tmp_file}" "#{zip_file}" && 46 | rm -rf "#{tmp_file}"` 47 | end 48 | 49 | `rm -rf "#{xcframework_dir}" && 50 | unzip "#{zip_file}" -d "#{destination_dir}"` 51 | 52 | return zip_file 53 | end 54 | 55 | def react_native_godot_log(message, level = :warning) 56 | if !Object.const_defined?("Pod::UI") 57 | return 58 | end 59 | custom_message = '[react-native-godot] ' + message 60 | case level 61 | when :info 62 | Pod::UI.puts custom_message.green 63 | when :error 64 | Pod::UI.puts custom_message.red 65 | else 66 | Pod::UI.puts custom_message.yellow 67 | end 68 | end -------------------------------------------------------------------------------- /package/react-native-godot.podspec: -------------------------------------------------------------------------------- 1 | require "json" 2 | require_relative "./react-native-godot-utils.rb" 3 | 4 | # package.json 5 | package = JSON.parse(File.read(File.join(__dir__, "package.json"))) 6 | version = package['version'].gsub(/dev-.*/, '') 7 | 8 | source = download_prebuilt(__dir__, version) 9 | 10 | Pod::Spec.new do |s| 11 | s.name = "react-native-godot" 12 | s.version = package["version"] 13 | s.summary = package["description"] 14 | s.description = "Bring Godot to React Native." 15 | s.homepage = "https://github.com/calico-games/react-native-godot" 16 | s.license = "Copyright © 2024 Calico Games. All rights reserved." 17 | s.authors = { "Calico Games" => "team@calico.games" } 18 | s.platforms = { :ios => min_ios_version_supported } 19 | s.source = source 20 | 21 | s.requires_arc = true 22 | s.pod_target_xcconfig = { 23 | "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", 24 | "CLANG_CXX_LIBRARY" => "libc++", 25 | 'DEFINES_MODULE' => 'YES' 26 | } 27 | if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then 28 | s.compiler_flags = "-DRCT_NEW_ARCH_ENABLED=1" 29 | end 30 | 31 | s.dependency 'React-Core' 32 | s.dependency 'React-CoreModules' 33 | 34 | s.frameworks = ['MetalKit', 'MetalFX'] 35 | 36 | s.ios.vendored_frameworks = [ 37 | 'libs/ios/ReactNativeGodot.xcframework', 38 | ] 39 | 40 | # All iOS files 41 | s.source_files = [ 42 | 'ios/GodotModule.mm', 43 | ] 44 | end -------------------------------------------------------------------------------- /package/src/GodotProvider.tsx: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | import React, {createContext, useContext, useEffect, useState} from 'react'; 3 | import NativeGodotModule from './specs/NativeGodotModule'; 4 | 5 | interface GodotContextType { 6 | 7 | AABB: typeof global.AABB | null; 8 | Basis: typeof global.Basis | null; 9 | Color: typeof global.Color | null; 10 | Plane: typeof global.Plane | null; 11 | Projection: typeof global.Projection | null; 12 | Quaternion: typeof global.Quaternion | null; 13 | Rect2: typeof global.Rect2 | null; 14 | Rect2i: typeof global.Rect2i | null; 15 | Transform2D: typeof global.Transform2D | null; 16 | Transform3D: typeof global.Transform3D | null; 17 | Vector2: typeof global.Vector2 | null; 18 | Vector2i: typeof global.Vector2i | null; 19 | Vector3: typeof global.Vector3 | null; 20 | Vector3i: typeof global.Vector3i | null; 21 | Vector4: typeof global.Vector4 | null; 22 | Vector4i: typeof global.Vector4i | null; 23 | isInitialized: boolean; 24 | } 25 | 26 | export const GodotContext = createContext(undefined); 27 | 28 | export const GodotProvider: React.FC<{children: React.ReactNode}> = ({children}) => { 29 | 30 | const [AABB, setAABB] = useState(null); 31 | const [Basis, setBasis] = useState(null); 32 | const [Color, setColor] = useState(null); 33 | const [Plane, setPlane] = useState(null); 34 | const [Projection, setProjection] = useState(null); 35 | const [Quaternion, setQuaternion] = useState(null); 36 | const [Rect2, setRect2] = useState(null); 37 | const [Rect2i, setRect2i] = useState(null); 38 | const [Transform2D, setTransform2D] = useState(null); 39 | const [Transform3D, setTransform3D] = useState(null); 40 | const [Vector2, setVector2] = useState(null); 41 | const [Vector2i, setVector2i] = useState(null); 42 | const [Vector3, setVector3] = useState(null); 43 | const [Vector3i, setVector3i] = useState(null); 44 | const [Vector4, setVector4] = useState(null); 45 | const [Vector4i, setVector4i] = useState(null); 46 | const [isInitialized, setIsInitialized] = useState(false); 47 | 48 | useEffect(() => { 49 | const initialize = () => { 50 | if (!NativeGodotModule) { 51 | console.error('[react-native-godot] NativeGodotModule is not available'); 52 | return; 53 | } 54 | NativeGodotModule.install(); 55 | 56 | if (typeof global.AABB === 'function') { 57 | setAABB(() => global.AABB); 58 | } 59 | if (typeof global.Basis === 'function') { 60 | setBasis(() => global.Basis); 61 | } 62 | if (typeof global.Color === 'function') { 63 | setColor(() => global.Color); 64 | } 65 | if (typeof global.Plane === 'function') { 66 | setPlane(() => global.Plane); 67 | } 68 | if (typeof global.Projection === 'function') { 69 | setProjection(() => global.Projection); 70 | } 71 | if (typeof global.Quaternion === 'function') { 72 | setQuaternion(() => global.Quaternion); 73 | } 74 | if (typeof global.Rect2 === 'function') { 75 | setRect2(() => global.Rect2); 76 | } 77 | if (typeof global.Rect2i === 'function') { 78 | setRect2i(() => global.Rect2i); 79 | } 80 | if (typeof global.Transform2D === 'function') { 81 | setTransform2D(() => global.Transform2D); 82 | } 83 | if (typeof global.Transform3D === 'function') { 84 | setTransform3D(() => global.Transform3D); 85 | } 86 | if (typeof global.Vector2 === 'function') { 87 | setVector2(() => global.Vector2); 88 | } 89 | if (typeof global.Vector2i === 'function') { 90 | setVector2i(() => global.Vector2i); 91 | } 92 | if (typeof global.Vector3 === 'function') { 93 | setVector3(() => global.Vector3); 94 | } 95 | if (typeof global.Vector3i === 'function') { 96 | setVector3i(() => global.Vector3i); 97 | } 98 | if (typeof global.Vector4 === 'function') { 99 | setVector4(() => global.Vector4); 100 | } 101 | if (typeof global.Vector4i === 'function') { 102 | setVector4i(() => global.Vector4i); 103 | } 104 | 105 | if (typeof global.AABB === 'function' && typeof global.Basis === 'function' && typeof global.Color === 'function' && typeof global.Plane === 'function' && typeof global.Projection === 'function' && typeof global.Quaternion === 'function' && typeof global.Rect2 === 'function' && typeof global.Rect2i === 'function' && typeof global.Transform2D === 'function' && typeof global.Transform3D === 'function' && typeof global.Vector2 === 'function' && typeof global.Vector2i === 'function' && typeof global.Vector3 === 'function' && typeof global.Vector3i === 'function' && typeof global.Vector4 === 'function' && typeof global.Vector4i === 'function') { 106 | console.info('[react-native-godot] Godot initialized'); 107 | setIsInitialized(true); 108 | } 109 | }; 110 | 111 | initialize(); 112 | }, []); 113 | 114 | return ( 115 | 116 | {children} 117 | 118 | ); 119 | }; 120 | 121 | export const useGodot = () => { 122 | const context = useContext(GodotContext); 123 | if (context === undefined) { 124 | throw new Error('useGodot must be used within a GodotProvider'); 125 | } 126 | return context; 127 | }; 128 | -------------------------------------------------------------------------------- /package/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './views'; 2 | export * from './GodotProvider'; 3 | export * from './types'; -------------------------------------------------------------------------------- /package/src/specs/GodotViewNativeComponent.ts: -------------------------------------------------------------------------------- 1 | import codegenNativeComponent from "react-native/Libraries/Utilities/codegenNativeComponent"; 2 | import type {ViewProps} from "react-native"; 3 | 4 | export interface NativeProps extends ViewProps {} 5 | 6 | export default codegenNativeComponent("GodotView"); -------------------------------------------------------------------------------- /package/src/specs/NativeGodotModule.ts: -------------------------------------------------------------------------------- 1 | import {TurboModule, TurboModuleRegistry} from 'react-native'; 2 | 3 | export interface Spec extends TurboModule { 4 | install: () => boolean; 5 | } 6 | 7 | export default TurboModuleRegistry.getEnforcing("GodotModule") as Spec | null; -------------------------------------------------------------------------------- /package/src/types/Node.tsx: -------------------------------------------------------------------------------- 1 | export declare namespace GD { 2 | export interface Node { 3 | getNode(name: string): Node | null; 4 | getParent(): Node | null; 5 | getChildren(): Node[]; 6 | getChildCount(): number; 7 | } 8 | } 9 | 10 | declare global { 11 | var GodotNode: GD.Node; 12 | } 13 | 14 | export {}; -------------------------------------------------------------------------------- /package/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Node'; -------------------------------------------------------------------------------- /package/src/variants/AABB.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | 3 | import {Plane} from './Plane'; 4 | import {Vector3} from './Vector3'; 5 | 6 | type AABBConstructor = { 7 | (): AABB; 8 | (from_: AABB): AABB; 9 | (position_: Vector3, size_: Vector3): AABB; 10 | 11 | }; 12 | 13 | declare global { 14 | var AABB: AABBConstructor; 15 | } 16 | 17 | export interface AABB { 18 | position: Vector3; 19 | size: Vector3; 20 | 21 | abs(): AABB; 22 | getCenter(): Vector3; 23 | getVolume(): number; 24 | hasVolume(): boolean; 25 | hasSurface(): boolean; 26 | hasPoint(point_: Vector3): boolean; 27 | isEqualApprox(aabb_: AABB): boolean; 28 | isFinite(): boolean; 29 | intersects(with_: AABB): boolean; 30 | encloses(with_: AABB): boolean; 31 | intersectsPlane(plane_: Plane): boolean; 32 | intersection(with_: AABB): AABB; 33 | merge(with_: AABB): AABB; 34 | expand(toPoint_: Vector3): AABB; 35 | grow(by_: number): AABB; 36 | getSupport(direction_: Vector3): Vector3; 37 | getLongestAxis(): Vector3; 38 | getLongestAxisIndex(): number; 39 | getLongestAxisSize(): number; 40 | getShortestAxis(): Vector3; 41 | getShortestAxisIndex(): number; 42 | getShortestAxisSize(): number; 43 | getEndpoint(idx_: number): Vector3; 44 | intersectsSegment(from_: Vector3, to_: Vector3): any; 45 | intersectsRay(from_: Vector3, dir_: Vector3): any; 46 | 47 | } 48 | 49 | export {}; // Ensure this file is treated as a module 50 | -------------------------------------------------------------------------------- /package/src/variants/Basis.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | 3 | import {Quaternion} from './Quaternion'; 4 | import {Vector3} from './Vector3'; 5 | 6 | type BasisConstructor = { 7 | (): Basis; 8 | (from_: Basis): Basis; 9 | (from_: Quaternion): Basis; 10 | (axis_: Vector3, angle_: number): Basis; 11 | (xAxis_: Vector3, yAxis_: Vector3, zAxis_: Vector3): Basis; 12 | 13 | }; 14 | 15 | declare global { 16 | var Basis: BasisConstructor; 17 | } 18 | 19 | export interface Basis { 20 | x: Vector3; 21 | y: Vector3; 22 | z: Vector3; 23 | 24 | inverse(): Basis; 25 | transposed(): Basis; 26 | orthonormalized(): Basis; 27 | determinant(): number; 28 | rotated(axis_: Vector3, angle_: number): Basis; 29 | scaled(scale_: Vector3): Basis; 30 | getScale(): Vector3; 31 | tdotx(with_: Vector3): number; 32 | tdoty(with_: Vector3): number; 33 | tdotz(with_: Vector3): number; 34 | slerp(to_: Basis, weight_: number): Basis; 35 | isEqualApprox(b_: Basis): boolean; 36 | isFinite(): boolean; 37 | getRotationQuaternion(): Quaternion; 38 | fromScale(scale_: Vector3): Basis; 39 | 40 | } 41 | 42 | export {}; // Ensure this file is treated as a module 43 | -------------------------------------------------------------------------------- /package/src/variants/Color.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | 3 | type ColorConstructor = { 4 | (): Color; 5 | (from_: Color): Color; 6 | (from_: Color, alpha_: number): Color; 7 | (r_: number, g_: number, b_: number): Color; 8 | (r_: number, g_: number, b_: number, a_: number): Color; 9 | (code_: string): Color; 10 | (code_: string, alpha_: number): Color; 11 | 12 | }; 13 | 14 | declare global { 15 | var Color: ColorConstructor; 16 | } 17 | 18 | export interface Color { 19 | r: number; 20 | g: number; 21 | b: number; 22 | a: number; 23 | 24 | toArgb32(): number; 25 | toAbgr32(): number; 26 | toRgba32(): number; 27 | toArgb64(): number; 28 | toAbgr64(): number; 29 | toRgba64(): number; 30 | toHtml(withAlpha_: boolean): string; 31 | clamp(min_: Color, max_: Color): Color; 32 | inverted(): Color; 33 | lerp(to_: Color, weight_: number): Color; 34 | lightened(amount_: number): Color; 35 | darkened(amount_: number): Color; 36 | blend(over_: Color): Color; 37 | getLuminance(): number; 38 | srgbToLinear(): Color; 39 | linearToSrgb(): Color; 40 | isEqualApprox(to_: Color): boolean; 41 | hex(hex_: number): Color; 42 | hex64(hex_: number): Color; 43 | html(rgba_: string): Color; 44 | fromString(str_: string, default_: Color): Color; 45 | fromHsv(h_: number, s_: number, v_: number, alpha_: number): Color; 46 | fromRgbe9995(rgbe_: number): Color; 47 | 48 | } 49 | 50 | export {}; // Ensure this file is treated as a module 51 | -------------------------------------------------------------------------------- /package/src/variants/Plane.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | 3 | import {Vector3} from './Vector3'; 4 | 5 | type PlaneConstructor = { 6 | (): Plane; 7 | (from_: Plane): Plane; 8 | (normal_: Vector3): Plane; 9 | (normal_: Vector3, d_: number): Plane; 10 | (normal_: Vector3, point_: Vector3): Plane; 11 | (point1_: Vector3, point2_: Vector3, point3_: Vector3): Plane; 12 | (a_: number, b_: number, c_: number, d_: number): Plane; 13 | 14 | }; 15 | 16 | declare global { 17 | var Plane: PlaneConstructor; 18 | } 19 | 20 | export interface Plane { 21 | normal: Vector3; 22 | d: number; 23 | 24 | normalized(): Plane; 25 | isEqualApprox(toPlane_: Plane): boolean; 26 | isFinite(): boolean; 27 | isPointOver(point_: Vector3): boolean; 28 | distanceTo(point_: Vector3): number; 29 | hasPoint(point_: Vector3, tolerance_: number): boolean; 30 | project(point_: Vector3): Vector3; 31 | intersect3(b_: Plane, c_: Plane): any; 32 | 33 | } 34 | 35 | export {}; // Ensure this file is treated as a module 36 | -------------------------------------------------------------------------------- /package/src/variants/Projection.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | 3 | import {AABB} from './AABB'; 4 | import {Plane} from './Plane'; 5 | import {Rect2} from './Rect2'; 6 | import {Transform3D} from './Transform3D'; 7 | import {Vector2} from './Vector2'; 8 | import {Vector4} from './Vector4'; 9 | 10 | type ProjectionConstructor = { 11 | (): Projection; 12 | (from_: Projection): Projection; 13 | (from_: Transform3D): Projection; 14 | (xAxis_: Vector4, yAxis_: Vector4, zAxis_: Vector4, wAxis_: Vector4): Projection; 15 | 16 | }; 17 | 18 | declare global { 19 | var Projection: ProjectionConstructor; 20 | } 21 | 22 | export interface Projection { 23 | x: Vector4; 24 | y: Vector4; 25 | z: Vector4; 26 | w: Vector4; 27 | 28 | createDepthCorrection(flipY_: boolean): Projection; 29 | createLightAtlasRect(rect_: Rect2): Projection; 30 | createPerspective(fovy_: number, aspect_: number, zNear_: number, zFar_: number, flipFov_: boolean): Projection; 31 | createPerspectiveHmd(fovy_: number, aspect_: number, zNear_: number, zFar_: number, flipFov_: boolean, eye_: number, intraocularDist_: number, convergenceDist_: number): Projection; 32 | createForHmd(eye_: number, aspect_: number, intraocularDist_: number, displayWidth_: number, displayToLens_: number, oversample_: number, zNear_: number, zFar_: number): Projection; 33 | createOrthogonal(left_: number, right_: number, bottom_: number, top_: number, zNear_: number, zFar_: number): Projection; 34 | createOrthogonalAspect(size_: number, aspect_: number, zNear_: number, zFar_: number, flipFov_: boolean): Projection; 35 | createFrustum(left_: number, right_: number, bottom_: number, top_: number, zNear_: number, zFar_: number): Projection; 36 | createFrustumAspect(size_: number, aspect_: number, offset_: Vector2, zNear_: number, zFar_: number, flipFov_: boolean): Projection; 37 | createFitAabb(aabb_: AABB): Projection; 38 | determinant(): number; 39 | perspectiveZnearAdjusted(newZnear_: number): Projection; 40 | flippedY(): Projection; 41 | jitterOffseted(offset_: Vector2): Projection; 42 | getFovy(fovx_: number, aspect_: number): number; 43 | getZFar(): number; 44 | getZNear(): number; 45 | getAspect(): number; 46 | getFov(): number; 47 | isOrthogonal(): boolean; 48 | getViewportHalfExtents(): Vector2; 49 | getFarPlaneHalfExtents(): Vector2; 50 | inverse(): Projection; 51 | getPixelsPerMeter(forPixelWidth_: number): number; 52 | getLodMultiplier(): number; 53 | 54 | } 55 | 56 | export {}; // Ensure this file is treated as a module 57 | -------------------------------------------------------------------------------- /package/src/variants/Quaternion.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | 3 | import {Basis} from './Basis'; 4 | import {Vector3} from './Vector3'; 5 | 6 | type QuaternionConstructor = { 7 | (): Quaternion; 8 | (from_: Quaternion): Quaternion; 9 | (from_: Basis): Quaternion; 10 | (axis_: Vector3, angle_: number): Quaternion; 11 | (arcFrom_: Vector3, arcTo_: Vector3): Quaternion; 12 | (x_: number, y_: number, z_: number, w_: number): Quaternion; 13 | 14 | }; 15 | 16 | declare global { 17 | var Quaternion: QuaternionConstructor; 18 | } 19 | 20 | export interface Quaternion { 21 | x: number; 22 | y: number; 23 | z: number; 24 | w: number; 25 | 26 | length(): number; 27 | lengthSquared(): number; 28 | normalized(): Quaternion; 29 | isNormalized(): boolean; 30 | isEqualApprox(to_: Quaternion): boolean; 31 | isFinite(): boolean; 32 | inverse(): Quaternion; 33 | log(): Quaternion; 34 | exp(): Quaternion; 35 | angleTo(to_: Quaternion): number; 36 | dot(with_: Quaternion): number; 37 | slerp(to_: Quaternion, weight_: number): Quaternion; 38 | slerpni(to_: Quaternion, weight_: number): Quaternion; 39 | sphericalCubicInterpolate(b_: Quaternion, preA_: Quaternion, postB_: Quaternion, weight_: number): Quaternion; 40 | sphericalCubicInterpolateInTime(b_: Quaternion, preA_: Quaternion, postB_: Quaternion, weight_: number, bT_: number, preAT_: number, postBT_: number): Quaternion; 41 | getAxis(): Vector3; 42 | getAngle(): number; 43 | 44 | } 45 | 46 | export {}; // Ensure this file is treated as a module 47 | -------------------------------------------------------------------------------- /package/src/variants/Rect2.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | 3 | import {Rect2i} from './Rect2i'; 4 | import {Vector2} from './Vector2'; 5 | 6 | type Rect2Constructor = { 7 | (): Rect2; 8 | (from_: Rect2): Rect2; 9 | (from_: Rect2i): Rect2; 10 | (position_: Vector2, size_: Vector2): Rect2; 11 | (x_: number, y_: number, width_: number, height_: number): Rect2; 12 | 13 | }; 14 | 15 | declare global { 16 | var Rect2: Rect2Constructor; 17 | } 18 | 19 | export interface Rect2 { 20 | position: Vector2; 21 | size: Vector2; 22 | 23 | getCenter(): Vector2; 24 | getArea(): number; 25 | hasArea(): boolean; 26 | hasPoint(point_: Vector2): boolean; 27 | isEqualApprox(rect_: Rect2): boolean; 28 | isFinite(): boolean; 29 | intersects(b_: Rect2, includeBorders_: boolean): boolean; 30 | encloses(b_: Rect2): boolean; 31 | intersection(b_: Rect2): Rect2; 32 | merge(b_: Rect2): Rect2; 33 | expand(to_: Vector2): Rect2; 34 | getSupport(direction_: Vector2): Vector2; 35 | grow(amount_: number): Rect2; 36 | growIndividual(left_: number, top_: number, right_: number, bottom_: number): Rect2; 37 | abs(): Rect2; 38 | 39 | } 40 | 41 | export {}; // Ensure this file is treated as a module 42 | -------------------------------------------------------------------------------- /package/src/variants/Rect2i.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | 3 | import {Rect2} from './Rect2'; 4 | import {Vector2i} from './Vector2i'; 5 | 6 | type Rect2iConstructor = { 7 | (): Rect2i; 8 | (from_: Rect2i): Rect2i; 9 | (from_: Rect2): Rect2i; 10 | (position_: Vector2i, size_: Vector2i): Rect2i; 11 | (x_: number, y_: number, width_: number, height_: number): Rect2i; 12 | 13 | }; 14 | 15 | declare global { 16 | var Rect2i: Rect2iConstructor; 17 | } 18 | 19 | export interface Rect2i { 20 | position: Vector2i; 21 | size: Vector2i; 22 | 23 | getCenter(): Vector2i; 24 | getArea(): number; 25 | hasArea(): boolean; 26 | hasPoint(point_: Vector2i): boolean; 27 | intersects(b_: Rect2i): boolean; 28 | encloses(b_: Rect2i): boolean; 29 | intersection(b_: Rect2i): Rect2i; 30 | merge(b_: Rect2i): Rect2i; 31 | expand(to_: Vector2i): Rect2i; 32 | grow(amount_: number): Rect2i; 33 | growIndividual(left_: number, top_: number, right_: number, bottom_: number): Rect2i; 34 | abs(): Rect2i; 35 | 36 | } 37 | 38 | export {}; // Ensure this file is treated as a module 39 | -------------------------------------------------------------------------------- /package/src/variants/Transform2D.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | 3 | import {Vector2} from './Vector2'; 4 | 5 | type Transform2DConstructor = { 6 | (): Transform2D; 7 | (from_: Transform2D): Transform2D; 8 | (rotation_: number, position_: Vector2): Transform2D; 9 | (rotation_: number, scale_: Vector2, skew_: number, position_: Vector2): Transform2D; 10 | (xAxis_: Vector2, yAxis_: Vector2, origin_: Vector2): Transform2D; 11 | 12 | }; 13 | 14 | declare global { 15 | var Transform2D: Transform2DConstructor; 16 | } 17 | 18 | export interface Transform2D { 19 | x: Vector2; 20 | y: Vector2; 21 | origin: Vector2; 22 | 23 | inverse(): Transform2D; 24 | affineInverse(): Transform2D; 25 | getRotation(): number; 26 | getOrigin(): Vector2; 27 | getScale(): Vector2; 28 | getSkew(): number; 29 | orthonormalized(): Transform2D; 30 | rotated(angle_: number): Transform2D; 31 | rotatedLocal(angle_: number): Transform2D; 32 | scaled(scale_: Vector2): Transform2D; 33 | scaledLocal(scale_: Vector2): Transform2D; 34 | translated(offset_: Vector2): Transform2D; 35 | translatedLocal(offset_: Vector2): Transform2D; 36 | basisXform(v_: Vector2): Vector2; 37 | basisXformInv(v_: Vector2): Vector2; 38 | interpolateWith(xform_: Transform2D, weight_: number): Transform2D; 39 | isEqualApprox(xform_: Transform2D): boolean; 40 | isFinite(): boolean; 41 | 42 | } 43 | 44 | export {}; // Ensure this file is treated as a module 45 | -------------------------------------------------------------------------------- /package/src/variants/Transform3D.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | 3 | import {Basis} from './Basis'; 4 | import {Projection} from './Projection'; 5 | import {Vector3} from './Vector3'; 6 | 7 | type Transform3DConstructor = { 8 | (): Transform3D; 9 | (from_: Transform3D): Transform3D; 10 | (basis_: Basis, origin_: Vector3): Transform3D; 11 | (xAxis_: Vector3, yAxis_: Vector3, zAxis_: Vector3, origin_: Vector3): Transform3D; 12 | (from_: Projection): Transform3D; 13 | 14 | }; 15 | 16 | declare global { 17 | var Transform3D: Transform3DConstructor; 18 | } 19 | 20 | export interface Transform3D { 21 | basis: Basis; 22 | origin: Vector3; 23 | 24 | inverse(): Transform3D; 25 | affineInverse(): Transform3D; 26 | orthonormalized(): Transform3D; 27 | rotated(axis_: Vector3, angle_: number): Transform3D; 28 | rotatedLocal(axis_: Vector3, angle_: number): Transform3D; 29 | scaled(scale_: Vector3): Transform3D; 30 | scaledLocal(scale_: Vector3): Transform3D; 31 | translated(offset_: Vector3): Transform3D; 32 | translatedLocal(offset_: Vector3): Transform3D; 33 | interpolateWith(xform_: Transform3D, weight_: number): Transform3D; 34 | isEqualApprox(xform_: Transform3D): boolean; 35 | isFinite(): boolean; 36 | 37 | } 38 | 39 | export {}; // Ensure this file is treated as a module 40 | -------------------------------------------------------------------------------- /package/src/variants/Vector2.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | 3 | import {Vector2i} from './Vector2i'; 4 | 5 | type Vector2Constructor = { 6 | (): Vector2; 7 | (from_: Vector2): Vector2; 8 | (from_: Vector2i): Vector2; 9 | (x_: number, y_: number): Vector2; 10 | 11 | }; 12 | 13 | declare global { 14 | var Vector2: Vector2Constructor; 15 | } 16 | 17 | export interface Vector2 { 18 | x: number; 19 | y: number; 20 | 21 | angle(): number; 22 | angleTo(to_: Vector2): number; 23 | angleToPoint(to_: Vector2): number; 24 | directionTo(to_: Vector2): Vector2; 25 | distanceTo(to_: Vector2): number; 26 | distanceSquaredTo(to_: Vector2): number; 27 | length(): number; 28 | lengthSquared(): number; 29 | limitLength(length_: number): Vector2; 30 | normalized(): Vector2; 31 | isNormalized(): boolean; 32 | isEqualApprox(to_: Vector2): boolean; 33 | isZeroApprox(): boolean; 34 | isFinite(): boolean; 35 | posmod(mod_: number): Vector2; 36 | posmodv(modv_: Vector2): Vector2; 37 | project(b_: Vector2): Vector2; 38 | lerp(to_: Vector2, weight_: number): Vector2; 39 | slerp(to_: Vector2, weight_: number): Vector2; 40 | cubicInterpolate(b_: Vector2, preA_: Vector2, postB_: Vector2, weight_: number): Vector2; 41 | cubicInterpolateInTime(b_: Vector2, preA_: Vector2, postB_: Vector2, weight_: number, bT_: number, preAT_: number, postBT_: number): Vector2; 42 | bezierInterpolate(control1_: Vector2, control2_: Vector2, end_: Vector2, t_: number): Vector2; 43 | maxAxisIndex(): number; 44 | minAxisIndex(): number; 45 | moveToward(to_: Vector2, delta_: number): Vector2; 46 | rotated(angle_: number): Vector2; 47 | orthogonal(): Vector2; 48 | floor(): Vector2; 49 | ceil(): Vector2; 50 | round(): Vector2; 51 | aspect(): number; 52 | dot(with_: Vector2): number; 53 | slide(n_: Vector2): Vector2; 54 | bounce(n_: Vector2): Vector2; 55 | reflect(line_: Vector2): Vector2; 56 | cross(with_: Vector2): number; 57 | abs(): Vector2; 58 | sign(): Vector2; 59 | clamp(min_: Vector2, max_: Vector2): Vector2; 60 | clampf(min_: number, max_: number): Vector2; 61 | snapped(step_: Vector2): Vector2; 62 | snappedf(step_: number): Vector2; 63 | min(with_: Vector2): Vector2; 64 | minf(with_: number): Vector2; 65 | max(with_: Vector2): Vector2; 66 | maxf(with_: number): Vector2; 67 | fromAngle(angle_: number): Vector2; 68 | 69 | } 70 | 71 | export {}; // Ensure this file is treated as a module 72 | -------------------------------------------------------------------------------- /package/src/variants/Vector2i.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | 3 | import {Vector2} from './Vector2'; 4 | 5 | type Vector2iConstructor = { 6 | (): Vector2i; 7 | (from_: Vector2i): Vector2i; 8 | (from_: Vector2): Vector2i; 9 | (x_: number, y_: number): Vector2i; 10 | 11 | }; 12 | 13 | declare global { 14 | var Vector2i: Vector2iConstructor; 15 | } 16 | 17 | export interface Vector2i { 18 | x: number; 19 | y: number; 20 | 21 | aspect(): number; 22 | maxAxisIndex(): number; 23 | minAxisIndex(): number; 24 | distanceTo(to_: Vector2i): number; 25 | distanceSquaredTo(to_: Vector2i): number; 26 | length(): number; 27 | lengthSquared(): number; 28 | sign(): Vector2i; 29 | abs(): Vector2i; 30 | clamp(min_: Vector2i, max_: Vector2i): Vector2i; 31 | clampi(min_: number, max_: number): Vector2i; 32 | snapped(step_: Vector2i): Vector2i; 33 | snappedi(step_: number): Vector2i; 34 | min(with_: Vector2i): Vector2i; 35 | mini(with_: number): Vector2i; 36 | max(with_: Vector2i): Vector2i; 37 | maxi(with_: number): Vector2i; 38 | 39 | } 40 | 41 | export {}; // Ensure this file is treated as a module 42 | -------------------------------------------------------------------------------- /package/src/variants/Vector3.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | 3 | import {Basis} from './Basis'; 4 | import {Vector2} from './Vector2'; 5 | import {Vector3i} from './Vector3i'; 6 | 7 | type Vector3Constructor = { 8 | (): Vector3; 9 | (from_: Vector3): Vector3; 10 | (from_: Vector3i): Vector3; 11 | (x_: number, y_: number, z_: number): Vector3; 12 | 13 | }; 14 | 15 | declare global { 16 | var Vector3: Vector3Constructor; 17 | } 18 | 19 | export interface Vector3 { 20 | x: number; 21 | y: number; 22 | z: number; 23 | 24 | minAxisIndex(): number; 25 | maxAxisIndex(): number; 26 | angleTo(to_: Vector3): number; 27 | signedAngleTo(to_: Vector3, axis_: Vector3): number; 28 | directionTo(to_: Vector3): Vector3; 29 | distanceTo(to_: Vector3): number; 30 | distanceSquaredTo(to_: Vector3): number; 31 | length(): number; 32 | lengthSquared(): number; 33 | limitLength(length_: number): Vector3; 34 | normalized(): Vector3; 35 | isNormalized(): boolean; 36 | isEqualApprox(to_: Vector3): boolean; 37 | isZeroApprox(): boolean; 38 | isFinite(): boolean; 39 | inverse(): Vector3; 40 | clamp(min_: Vector3, max_: Vector3): Vector3; 41 | clampf(min_: number, max_: number): Vector3; 42 | snapped(step_: Vector3): Vector3; 43 | snappedf(step_: number): Vector3; 44 | rotated(axis_: Vector3, angle_: number): Vector3; 45 | lerp(to_: Vector3, weight_: number): Vector3; 46 | slerp(to_: Vector3, weight_: number): Vector3; 47 | cubicInterpolate(b_: Vector3, preA_: Vector3, postB_: Vector3, weight_: number): Vector3; 48 | cubicInterpolateInTime(b_: Vector3, preA_: Vector3, postB_: Vector3, weight_: number, bT_: number, preAT_: number, postBT_: number): Vector3; 49 | bezierInterpolate(control1_: Vector3, control2_: Vector3, end_: Vector3, t_: number): Vector3; 50 | moveToward(to_: Vector3, delta_: number): Vector3; 51 | dot(with_: Vector3): number; 52 | cross(with_: Vector3): Vector3; 53 | outer(with_: Vector3): Basis; 54 | abs(): Vector3; 55 | floor(): Vector3; 56 | ceil(): Vector3; 57 | round(): Vector3; 58 | posmod(mod_: number): Vector3; 59 | posmodv(modv_: Vector3): Vector3; 60 | project(b_: Vector3): Vector3; 61 | slide(n_: Vector3): Vector3; 62 | bounce(n_: Vector3): Vector3; 63 | reflect(n_: Vector3): Vector3; 64 | sign(): Vector3; 65 | octahedronEncode(): Vector2; 66 | min(with_: Vector3): Vector3; 67 | minf(with_: number): Vector3; 68 | max(with_: Vector3): Vector3; 69 | maxf(with_: number): Vector3; 70 | octahedronDecode(uv_: Vector2): Vector3; 71 | 72 | } 73 | 74 | export {}; // Ensure this file is treated as a module 75 | -------------------------------------------------------------------------------- /package/src/variants/Vector3i.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | 3 | import {Vector3} from './Vector3'; 4 | 5 | type Vector3iConstructor = { 6 | (): Vector3i; 7 | (from_: Vector3i): Vector3i; 8 | (from_: Vector3): Vector3i; 9 | (x_: number, y_: number, z_: number): Vector3i; 10 | 11 | }; 12 | 13 | declare global { 14 | var Vector3i: Vector3iConstructor; 15 | } 16 | 17 | export interface Vector3i { 18 | x: number; 19 | y: number; 20 | z: number; 21 | 22 | minAxisIndex(): number; 23 | maxAxisIndex(): number; 24 | distanceTo(to_: Vector3i): number; 25 | distanceSquaredTo(to_: Vector3i): number; 26 | length(): number; 27 | lengthSquared(): number; 28 | sign(): Vector3i; 29 | abs(): Vector3i; 30 | clamp(min_: Vector3i, max_: Vector3i): Vector3i; 31 | clampi(min_: number, max_: number): Vector3i; 32 | snapped(step_: Vector3i): Vector3i; 33 | snappedi(step_: number): Vector3i; 34 | min(with_: Vector3i): Vector3i; 35 | mini(with_: number): Vector3i; 36 | max(with_: Vector3i): Vector3i; 37 | maxi(with_: number): Vector3i; 38 | 39 | } 40 | 41 | export {}; // Ensure this file is treated as a module 42 | -------------------------------------------------------------------------------- /package/src/variants/Vector4.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | 3 | import {Vector4i} from './Vector4i'; 4 | 5 | type Vector4Constructor = { 6 | (): Vector4; 7 | (from_: Vector4): Vector4; 8 | (from_: Vector4i): Vector4; 9 | (x_: number, y_: number, z_: number, w_: number): Vector4; 10 | 11 | }; 12 | 13 | declare global { 14 | var Vector4: Vector4Constructor; 15 | } 16 | 17 | export interface Vector4 { 18 | x: number; 19 | y: number; 20 | z: number; 21 | w: number; 22 | 23 | minAxisIndex(): number; 24 | maxAxisIndex(): number; 25 | length(): number; 26 | lengthSquared(): number; 27 | abs(): Vector4; 28 | sign(): Vector4; 29 | floor(): Vector4; 30 | ceil(): Vector4; 31 | round(): Vector4; 32 | lerp(to_: Vector4, weight_: number): Vector4; 33 | cubicInterpolate(b_: Vector4, preA_: Vector4, postB_: Vector4, weight_: number): Vector4; 34 | cubicInterpolateInTime(b_: Vector4, preA_: Vector4, postB_: Vector4, weight_: number, bT_: number, preAT_: number, postBT_: number): Vector4; 35 | posmod(mod_: number): Vector4; 36 | posmodv(modv_: Vector4): Vector4; 37 | snapped(step_: Vector4): Vector4; 38 | snappedf(step_: number): Vector4; 39 | clamp(min_: Vector4, max_: Vector4): Vector4; 40 | clampf(min_: number, max_: number): Vector4; 41 | normalized(): Vector4; 42 | isNormalized(): boolean; 43 | directionTo(to_: Vector4): Vector4; 44 | distanceTo(to_: Vector4): number; 45 | distanceSquaredTo(to_: Vector4): number; 46 | dot(with_: Vector4): number; 47 | inverse(): Vector4; 48 | isEqualApprox(to_: Vector4): boolean; 49 | isZeroApprox(): boolean; 50 | isFinite(): boolean; 51 | min(with_: Vector4): Vector4; 52 | minf(with_: number): Vector4; 53 | max(with_: Vector4): Vector4; 54 | maxf(with_: number): Vector4; 55 | 56 | } 57 | 58 | export {}; // Ensure this file is treated as a module 59 | -------------------------------------------------------------------------------- /package/src/variants/Vector4i.ts: -------------------------------------------------------------------------------- 1 | // THIS FILE IS GENERATED. DO NOT EDIT. 2 | 3 | import {Vector4} from './Vector4'; 4 | 5 | type Vector4iConstructor = { 6 | (): Vector4i; 7 | (from_: Vector4i): Vector4i; 8 | (from_: Vector4): Vector4i; 9 | (x_: number, y_: number, z_: number, w_: number): Vector4i; 10 | 11 | }; 12 | 13 | declare global { 14 | var Vector4i: Vector4iConstructor; 15 | } 16 | 17 | export interface Vector4i { 18 | x: number; 19 | y: number; 20 | z: number; 21 | w: number; 22 | 23 | minAxisIndex(): number; 24 | maxAxisIndex(): number; 25 | length(): number; 26 | lengthSquared(): number; 27 | sign(): Vector4i; 28 | abs(): Vector4i; 29 | clamp(min_: Vector4i, max_: Vector4i): Vector4i; 30 | clampi(min_: number, max_: number): Vector4i; 31 | snapped(step_: Vector4i): Vector4i; 32 | snappedi(step_: number): Vector4i; 33 | min(with_: Vector4i): Vector4i; 34 | mini(with_: number): Vector4i; 35 | max(with_: Vector4i): Vector4i; 36 | maxi(with_: number): Vector4i; 37 | distanceTo(to_: Vector4i): number; 38 | distanceSquaredTo(to_: Vector4i): number; 39 | 40 | } 41 | 42 | export {}; // Ensure this file is treated as a module 43 | -------------------------------------------------------------------------------- /package/src/views/Godot.tsx: -------------------------------------------------------------------------------- 1 | import React, {useEffect, forwardRef, useRef} from 'react'; 2 | import type {Ref, MutableRefObject, ForwardedRef, FunctionComponent} from 'react'; 3 | 4 | import {GodotView} from './GodotView'; 5 | import type {GodotViewProps} from './types'; 6 | 7 | export const useGodotRef = () => useRef(null); 8 | 9 | export interface GodotProps extends GodotViewProps { 10 | ref?: Ref | undefined; 11 | } 12 | 13 | export const Godot = forwardRef( 14 | ( 15 | { 16 | style, 17 | onLayout: _onLayout, 18 | source, 19 | scene, 20 | debug, 21 | onMessage, 22 | ...props 23 | }, 24 | forwardedRef 25 | ) => { 26 | const innerRef = useGodotRef(); 27 | const ref = useCombinedRefs(forwardedRef, innerRef); 28 | 29 | return ( 30 | 40 | ); 41 | } 42 | ) as FunctionComponent>; 43 | 44 | /** 45 | * Combines a list of refs into a single ref. This can be used to provide 46 | * both a forwarded ref and an internal ref keeping the same functionality 47 | * on both of the refs. 48 | * @param refs Array of refs to combine 49 | * @returns A single ref that can be used in a ref prop. 50 | */ 51 | const useCombinedRefs = ( 52 | ...refs: Array | ForwardedRef> 53 | ) => { 54 | const targetRef = React.useRef(null); 55 | 56 | useEffect(() => { 57 | refs.forEach((ref) => { 58 | if (ref) { 59 | if (typeof ref === 'function') { 60 | ref(targetRef.current); 61 | } else { 62 | ref.current = targetRef.current; 63 | } 64 | } 65 | }); 66 | }, [refs]); 67 | 68 | return targetRef; 69 | }; -------------------------------------------------------------------------------- /package/src/views/GodotView.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Image} from 'react-native'; 3 | import type {HostComponent} from 'react-native'; 4 | 5 | import GodotViewNativeComponent from '../specs/GodotViewNativeComponent'; 6 | 7 | import {GodotViewApi} from './api'; 8 | import type {GodotViewProps} from './types'; 9 | import {GodotViewNativeId} from './GodotViewNativeId'; 10 | 11 | const NativeGodotView: HostComponent = GodotViewNativeComponent; 12 | 13 | export class GodotView extends React.Component { 14 | constructor(props: GodotViewProps) { 15 | super(props); 16 | this._nativeID = GodotViewNativeId.current++; 17 | const {source, scene, onMessage} = props; 18 | 19 | if (source) { 20 | assertGodotViewApi(); 21 | GodotViewApi.setJsiProperty(this._nativeID, "source", Image.resolveAssetSource(source as any).uri); 22 | } 23 | 24 | if (scene) { 25 | assertGodotViewApi(); 26 | GodotViewApi.setJsiProperty(this._nativeID, "scene", scene); 27 | } 28 | 29 | if (onMessage) { 30 | assertGodotViewApi(); 31 | GodotViewApi.setJsiProperty(this._nativeID, "onMessage", onMessage); 32 | } 33 | } 34 | 35 | private _nativeID: number; 36 | 37 | public get nativeId() { 38 | return this._nativeID; 39 | } 40 | 41 | componentDidUpdate(prevProps: GodotViewProps) { 42 | const {source, scene, onMessage} = this.props; 43 | 44 | if (source !== prevProps.source) { 45 | assertGodotViewApi(); 46 | GodotViewApi.setJsiProperty(this._nativeID, "source", Image.resolveAssetSource(source as any).uri); 47 | } 48 | 49 | if (scene !== prevProps.scene) { 50 | assertGodotViewApi(); 51 | GodotViewApi.setJsiProperty(this._nativeID, "scene", scene); 52 | } 53 | 54 | if (prevProps.onMessage === undefined && onMessage !== undefined) { 55 | assertGodotViewApi(); 56 | GodotViewApi.setJsiProperty(this._nativeID, "onMessage", onMessage); 57 | } 58 | } 59 | 60 | /** 61 | * Pause the Godot view. 62 | */ 63 | public pause() { 64 | assertGodotViewApi(); 65 | GodotViewApi.pause(this._nativeID); 66 | } 67 | 68 | /** 69 | * Resume the Godot view. 70 | */ 71 | public resume() { 72 | assertGodotViewApi(); 73 | GodotViewApi.resume(this._nativeID); 74 | } 75 | 76 | /** 77 | * Resume the Godot view. 78 | */ 79 | public getRoot() { 80 | assertGodotViewApi(); 81 | return GodotViewApi.getRoot(this._nativeID); 82 | } 83 | 84 | /** 85 | * Start drawing the Godot view. 86 | */ 87 | public static startDrawing() { 88 | assertGodotViewApi(); 89 | GodotViewApi.startDrawing(); 90 | } 91 | 92 | /** 93 | * Stop drawing the Godot view 94 | */ 95 | public static stopDrawing() { 96 | assertGodotViewApi(); 97 | GodotViewApi.stopDrawing(); 98 | } 99 | 100 | /** 101 | * Emit a message to the Godot view. 102 | */ 103 | public emitMessage(message: any) { 104 | assertGodotViewApi(); 105 | GodotViewApi.emitMessage(this._nativeID, message); 106 | } 107 | 108 | /** 109 | * Check if the Godot view is ready. 110 | */ 111 | public get isReady(): boolean { 112 | assertGodotViewApi(); 113 | return GodotViewApi.isReady(this._nativeID); 114 | } 115 | 116 | render() { 117 | const {debug = false, ...viewProps} = this.props; 118 | return ( 119 | 124 | ); 125 | } 126 | } 127 | 128 | const assertGodotViewApi = () => { 129 | if ( 130 | GodotViewApi === null || 131 | GodotViewApi.setJsiProperty === null || 132 | GodotViewApi.pause === null || 133 | GodotViewApi.resume === null || 134 | GodotViewApi.getRoot === null || 135 | GodotViewApi.isReady === null 136 | ) { 137 | throw Error('Godot View API was not found.'); 138 | } 139 | }; -------------------------------------------------------------------------------- /package/src/views/GodotViewNativeId.ts: -------------------------------------------------------------------------------- 1 | export const GodotViewNativeId = {current: 1000}; -------------------------------------------------------------------------------- /package/src/views/api.ts: -------------------------------------------------------------------------------- 1 | import type {IGodotViewApi} from './types'; 2 | 3 | declare global { 4 | var GodotViewApi: IGodotViewApi; 5 | } 6 | 7 | export const {GodotViewApi} = global; -------------------------------------------------------------------------------- /package/src/views/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Godot'; 2 | export * from './GodotView'; 3 | export * from './types'; -------------------------------------------------------------------------------- /package/src/views/types.ts: -------------------------------------------------------------------------------- 1 | import type {ViewProps, ImageSourcePropType} from 'react-native'; 2 | import {GD} from '../types'; 3 | 4 | export interface IGodotViewApi { 5 | setJsiProperty: (nativeId: number, name: string, value: T) => void; 6 | pause: (nativeId: number) => void; 7 | resume: (nativeId: number) => void; 8 | getRoot: (nativeId: number) => GD.Node | null; 9 | isReady: (nativeId: number) => boolean; 10 | startDrawing: () => void; 11 | stopDrawing: () => void; 12 | emitMessage: (nativeId: number, message: any) => void; 13 | } 14 | 15 | export type GodotMessageEventHandler = (message: any) => void; 16 | 17 | type Source = ImageSourcePropType; 18 | 19 | export interface GodotViewProps extends ViewProps { 20 | source?: Source; 21 | scene?: string; 22 | debug?: boolean; 23 | onMessage?: GodotMessageEventHandler; 24 | } -------------------------------------------------------------------------------- /package/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "lib": [ 5 | "dom", 6 | "es2019" 7 | ], 8 | "allowJs": true, 9 | "skipLibCheck": true, 10 | "allowSyntheticDefaultImports": true, 11 | "resolveJsonModule": true, 12 | "esModuleInterop": true, 13 | "moduleResolution": "node", 14 | "jsx": "react-native", 15 | "strict": true, 16 | "forceConsistentCasingInFileNames": true, 17 | "noUnusedLocals": false /* Report errors on unused locals. */, 18 | "noUnusedParameters": true /* Report errors on unused parameters. */, 19 | "noImplicitReturns": true /* Report error when not all code paths in function return a value. */, 20 | "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */, 21 | "noUncheckedIndexedAccess": false, /* Include 'undefined' in index signature results */ 22 | "allowUnreachableCode": false, 23 | "allowUnusedLabels": false, 24 | "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 25 | "strictNullChecks": true, /* Enable strict null checks. */ 26 | "strictFunctionTypes": true, /* Enable strict checking of function types. */ 27 | "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 28 | "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 29 | "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 30 | "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 31 | }, 32 | "exclude": [ 33 | "node_modules", 34 | "babel.config.js", 35 | "metro.config.js", 36 | "lib", 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /screenshots/screenshot1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/screenshots/screenshot1.jpeg -------------------------------------------------------------------------------- /screenshots/screenshot2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/screenshots/screenshot2.jpeg -------------------------------------------------------------------------------- /screenshots/screenshot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/screenshots/screenshot3.png -------------------------------------------------------------------------------- /static/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/calico-games/react-native-godot/3892f30db6e43715609562c6e50960613ecf0df9/static/banner.png --------------------------------------------------------------------------------