diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab83dbfb3694ee..9032e30d092216 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,6 +34,18 @@ jobs: target key: ${{ runner.os }}-cargo-check-test-${{ matrix.toolchain }}-${{ hashFiles('**/Cargo.lock') }} + - name: Install cargo-lipo + run: cargo install cargo-lipo + if: ${{ runner.os == 'macOS' }} + + - name: Add iOS targets + run: rustup target add aarch64-apple-ios x86_64-apple-ios + if: ${{ runner.os == 'macOS' }} + + - name: Add iOS targets + run: cd examples/ios && make install + if: ${{ runner.os == 'macOS' }} + - name: Install alsa run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev if: ${{ runner.os == 'Linux' }} @@ -65,7 +77,7 @@ jobs: toolchain: nightly components: rustfmt, clippy override: true - + - name: Install alsa run: sudo apt-get install --no-install-recommends libasound2-dev diff --git a/Cargo.toml b/Cargo.toml index f22fe6a3e042c1..aa3e72c1c27fc2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,7 +55,7 @@ wayland = ["bevy_winit/wayland"] x11 = ["bevy_winit/x11"] [workspace] -members = ["crates/*", "crates/bevy_ecs/hecs"] +members = ["crates/*", "crates/bevy_ecs/hecs", "examples/ios"] exclude = ["benches"] [dependencies] diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index 01d21404810d64..f30a6f60bfd249 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -49,7 +49,9 @@ parking_lot = "0.11.0" bevy-glsl-to-spirv = "0.1.7" [target.'cfg(target_os = "ios")'.dependencies] -shaderc = "0.6.2" +#shaderc = "0.6.2" +#shaderc = { path = "../../../shaderc-rs/shaderc-rs/" } +shaderc = { git = "https://github.com/simlay/shaderc-rs", branch = "ios-support" } [features] png = ["image/png"] diff --git a/examples/README.md b/examples/README.md index 48ede21f9d8783..f356d4ab5beea7 100644 --- a/examples/README.md +++ b/examples/README.md @@ -136,3 +136,21 @@ to point to the correct `.js` file. Then serve `examples/wasm` dir to browser. i.e. $ basic-http-server examples/wasm + +## ios + +#### pre-req + + $ rustup target add aarch64-apple-ios x86_64-apple-ios + $ cargo install cargo-lipo + +#### build & run + + $ cd examples/ios + $ make run + +If you'd like to see xcode do stuff, you can run + $ open bevy_ios_example.xcodeproj/ + +which will open xcode. You then must push the zoom zoom play button and wait +for the magic. diff --git a/examples/ios/.gitignore b/examples/ios/.gitignore new file mode 100644 index 00000000000000..796b96d1c40232 --- /dev/null +++ b/examples/ios/.gitignore @@ -0,0 +1 @@ +/build diff --git a/examples/ios/Cargo.toml b/examples/ios/Cargo.toml new file mode 100644 index 00000000000000..1d2184c56382e4 --- /dev/null +++ b/examples/ios/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "bevy-ios-example" +version = "0.1.0" +authors = ["Sebastian Imlay "] +edition = "2018" + +[lib] +name = "bevy_ios_example" +crate-type = ["staticlib"] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +bevy = { path = "../../", features = [ "bevy_gilrs", "bevy_gltf", "bevy_wgpu", "bevy_winit", "render", "dynamic_plugins", "png", "hdr"], default-features = false} diff --git a/examples/ios/Makefile b/examples/ios/Makefile new file mode 100644 index 00000000000000..cd958f9af6a42e --- /dev/null +++ b/examples/ios/Makefile @@ -0,0 +1,18 @@ +.PHONY: xcodebuild run install boot-sim generate clean + +run: install + xcrun simctl launch --console $(DEVICE_ID) com.rust.bevy-ios-example + +boot-sim: + xcrun simctl boot $(DEVICE_ID) || true + +install: xcodebuild boot-sim + xcrun simctl install $(DEVICE_ID) build/Build/Products/Debug-iphonesimulator/bevy_ios_example.app + +DEVICE_ID=$(shell xcrun simctl list devices 'iOS' | grep -v '^--' | grep -v '==' | head -n 1 | cut -d ' ' -f 7 | sed 's/[()]//g') +xcodebuild: + xcodebuild -scheme bevy_ios_example -configuration Debug -derivedDataPath build -destination "id=$(DEVICE_ID)" + +clean: + rm -r build + cargo clean diff --git a/examples/ios/bevy_ios_example.xcodeproj/.gitignore b/examples/ios/bevy_ios_example.xcodeproj/.gitignore new file mode 100644 index 00000000000000..8b53cbff82b112 --- /dev/null +++ b/examples/ios/bevy_ios_example.xcodeproj/.gitignore @@ -0,0 +1,2 @@ +xcuserdata +project.xcworkspace diff --git a/examples/ios/bevy_ios_example.xcodeproj/project.pbxproj b/examples/ios/bevy_ios_example.xcodeproj/project.pbxproj new file mode 100644 index 00000000000000..5446f0eb50437f --- /dev/null +++ b/examples/ios/bevy_ios_example.xcodeproj/project.pbxproj @@ -0,0 +1,418 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 134866208A035F8615C99114 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96A1E5B62F48B379829E8A0D /* Metal.framework */; }; + 2604C99FAB5A8322EDCABB9F /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FE71FBCAA714DB4F42459106 /* UIKit.framework */; }; + 442540D056ADB9AE61A0A590 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9F1B41978FA53999AA836D0F /* Security.framework */; }; + 55892F1396056740E1AF9685 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = AF7DE91055EBD05ED77E57F9 /* main.m */; }; + 55B7188F81C3C4183F81D3AE /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = A39528EB2CCB182F5328223A /* libc++.tbd */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 26BF2C4863C966DABAB40DC8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8DBF1E2B5C613DA41701F6D9 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D08AEBE0B1A9C9A7B8C7B33F; + remoteInfo = cargo_ios; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 160DB77300A3F1806F024D47 /* bindings.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bindings.h; sourceTree = ""; }; + 55EAC02897847195D2F44C15 /* bevy_ios_example.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = bevy_ios_example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 8EE7F1E3B0303533925D7E33 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; + 96A1E5B62F48B379829E8A0D /* Metal.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Metal.framework; path = System/Library/Frameworks/Metal.framework; sourceTree = SDKROOT; }; + 9F1B41978FA53999AA836D0F /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + A39528EB2CCB182F5328223A /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; + AF7DE91055EBD05ED77E57F9 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + FE71FBCAA714DB4F42459106 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + D5A822CB2D6847BA8800BE4C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 442540D056ADB9AE61A0A590 /* Security.framework in Frameworks */, + 134866208A035F8615C99114 /* Metal.framework in Frameworks */, + 2604C99FAB5A8322EDCABB9F /* UIKit.framework in Frameworks */, + 55B7188F81C3C4183F81D3AE /* libc++.tbd in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 321F7D6A765B38E746C35105 /* Products */ = { + isa = PBXGroup; + children = ( + 55EAC02897847195D2F44C15 /* bevy_ios_example.app */, + ); + name = Products; + sourceTree = ""; + }; + 4F1D6F28B8A5D1927AB0ADED /* ios-src */ = { + isa = PBXGroup; + children = ( + 160DB77300A3F1806F024D47 /* bindings.h */, + 8EE7F1E3B0303533925D7E33 /* Info.plist */, + AF7DE91055EBD05ED77E57F9 /* main.m */, + ); + path = "ios-src"; + sourceTree = ""; + }; + 8F2E3E6040EAD2EC9F3FA530 = { + isa = PBXGroup; + children = ( + 4F1D6F28B8A5D1927AB0ADED /* ios-src */, + EB028409C2D0655412DA6E44 /* Frameworks */, + 321F7D6A765B38E746C35105 /* Products */, + ); + sourceTree = ""; + }; + EB028409C2D0655412DA6E44 /* Frameworks */ = { + isa = PBXGroup; + children = ( + A39528EB2CCB182F5328223A /* libc++.tbd */, + 96A1E5B62F48B379829E8A0D /* Metal.framework */, + 9F1B41978FA53999AA836D0F /* Security.framework */, + FE71FBCAA714DB4F42459106 /* UIKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXLegacyTarget section */ + D08AEBE0B1A9C9A7B8C7B33F /* cargo_ios */ = { + isa = PBXLegacyTarget; + buildArgumentsString = build_rust_deps.sh; + buildConfigurationList = AA00A0CFDB11F37F2BA3FC2E /* Build configuration list for PBXLegacyTarget "cargo_ios" */; + buildPhases = ( + FE045B3D04D57B713A565FF8 /* Sources */, + ); + buildToolPath = /bin/sh; + buildWorkingDirectory = .; + dependencies = ( + ); + name = cargo_ios; + passBuildSettingsInEnvironment = 0; + productName = cargo_ios; + }; +/* End PBXLegacyTarget section */ + +/* Begin PBXNativeTarget section */ + 3BDB8152E4962373181B4FE5 /* bevy_ios_example */ = { + isa = PBXNativeTarget; + buildConfigurationList = E714A1AEAAE517C348B5BD27 /* Build configuration list for PBXNativeTarget "bevy_ios_example" */; + buildPhases = ( + 9F13800790AD9DBC2BC0F116 /* Sources */, + D5A822CB2D6847BA8800BE4C /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 19D4B9C22ADC6705B5132B4C /* PBXTargetDependency */, + ); + name = bevy_ios_example; + productName = bevy_ios_example; + productReference = 55EAC02897847195D2F44C15 /* bevy_ios_example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8DBF1E2B5C613DA41701F6D9 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1020; + TargetAttributes = { + }; + }; + buildConfigurationList = 9D43D41707A5C30B227B83F9 /* Build configuration list for PBXProject "bevy_ios_example" */; + compatibilityVersion = "Xcode 10.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 8F2E3E6040EAD2EC9F3FA530; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3BDB8152E4962373181B4FE5 /* bevy_ios_example */, + D08AEBE0B1A9C9A7B8C7B33F /* cargo_ios */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 9F13800790AD9DBC2BC0F116 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 55892F1396056740E1AF9685 /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FE045B3D04D57B713A565FF8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 19D4B9C22ADC6705B5132B4C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D08AEBE0B1A9C9A7B8C7B33F /* cargo_ios */; + targetProxy = 26BF2C4863C966DABAB40DC8 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 4AD7BC6FDD56FF18FA6DA7D7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "DEBUG=1", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 5B14EC4ADC81FBF1F8CF20E9 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_CXX_LANGUAGE_STANDARD = "c++11"; + CLANG_CXX_LIBRARY = "libc++"; + CODE_SIGN_IDENTITY = "iPhone Developer"; + ENABLE_BITCODE = NO; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "ios-src/", + ); + INFOPLIST_FILE = "ios-src/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../target/universal/release, + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-lbevy_ios_example", + "-lc++abi", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.rust.bevy-ios-example"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 79E3C28F06346EA58420A93D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_VERSION = 5.0; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 8265913A25816D964A847F1B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.rust.cargo-ios"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A2D5B73DD30D562B6F366526 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_CXX_LANGUAGE_STANDARD = "c++11"; + CLANG_CXX_LIBRARY = "libc++"; + CODE_SIGN_IDENTITY = "iPhone Developer"; + ENABLE_BITCODE = NO; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "ios-src/", + ); + INFOPLIST_FILE = "ios-src/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + ../../target/universal/debug, + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-lbevy_ios_example", + "-lc++abi", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.rust.bevy-ios-example"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + FEA9B18D9236F9F6DC6DF799 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = "com.rust.cargo-ios"; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 9D43D41707A5C30B227B83F9 /* Build configuration list for PBXProject "bevy_ios_example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4AD7BC6FDD56FF18FA6DA7D7 /* Debug */, + 79E3C28F06346EA58420A93D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + AA00A0CFDB11F37F2BA3FC2E /* Build configuration list for PBXLegacyTarget "cargo_ios" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8265913A25816D964A847F1B /* Debug */, + FEA9B18D9236F9F6DC6DF799 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; + E714A1AEAAE517C348B5BD27 /* Build configuration list for PBXNativeTarget "bevy_ios_example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A2D5B73DD30D562B6F366526 /* Debug */, + 5B14EC4ADC81FBF1F8CF20E9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + }; + rootObject = 8DBF1E2B5C613DA41701F6D9 /* Project object */; +} diff --git a/examples/ios/build_rust_deps.sh b/examples/ios/build_rust_deps.sh new file mode 100755 index 00000000000000..bc33a01aacb791 --- /dev/null +++ b/examples/ios/build_rust_deps.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +set -e + +PATH=$PATH:$HOME/.cargo/bin +echo "$PATH" + +# If you want your build to run faster, add a "--target x86_64-apple-ios" for just using the ios simulator. +cargo lipo diff --git a/examples/ios/ios-src/Info.plist b/examples/ios/ios-src/Info.plist new file mode 100644 index 00000000000000..db9c856e7fc867 --- /dev/null +++ b/examples/ios/ios-src/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + UILaunchStoryboardName + LaunchScreen + + diff --git a/examples/ios/ios-src/bindings.h b/examples/ios/ios-src/bindings.h new file mode 100644 index 00000000000000..a705f03b13edcc --- /dev/null +++ b/examples/ios/ios-src/bindings.h @@ -0,0 +1 @@ +void main_rs(void); diff --git a/examples/ios/ios-src/main.m b/examples/ios/ios-src/main.m new file mode 100644 index 00000000000000..7d152fb790e6c3 --- /dev/null +++ b/examples/ios/ios-src/main.m @@ -0,0 +1,6 @@ +#import "bindings.h" + +int main() { + main_rs(); + return 0; +} diff --git a/examples/ios/src/lib.rs b/examples/ios/src/lib.rs new file mode 100644 index 00000000000000..f7ec690d2a6901 --- /dev/null +++ b/examples/ios/src/lib.rs @@ -0,0 +1,247 @@ +use bevy::{ + prelude::*, + render::pass::ClearColor, + sprite::collide_aabb::{collide, Collision}, +}; + +#[no_mangle] +extern "C" fn main_rs() { + App::build() + .add_default_plugins() + .add_resource(Scoreboard { score: 0 }) + .add_resource(ClearColor(Color::rgb(0.7, 0.7, 0.7))) + .add_startup_system(setup.system()) + .add_system(paddle_movement_system.system()) + .add_system(ball_collision_system.system()) + .add_system(ball_movement_system.system()) + .add_system(scoreboard_system.system()) + .run(); +} + +struct Paddle { + speed: f32, +} + +struct Ball { + velocity: Vec3, +} + +struct Scoreboard { + score: usize, +} + +enum Collider { + Solid, + Scorable, +} + +fn setup( + mut commands: Commands, + mut materials: ResMut>, + asset_server: Res, +) { + // Add the game's entities to our world + commands + // cameras + .spawn(Camera2dComponents::default()) + .spawn(UiCameraComponents::default()) + // paddle + .spawn(SpriteComponents { + material: materials.add(Color::rgb(0.2, 0.2, 0.8).into()), + transform: Transform::from_translation(Vec3::new(0.0, -215.0, 0.0)), + sprite: Sprite::new(Vec2::new(120.0, 30.0)), + ..Default::default() + }) + .with(Paddle { speed: 500.0 }) + .with(Collider::Solid) + // ball + .spawn(SpriteComponents { + material: materials.add(Color::rgb(0.8, 0.2, 0.2).into()), + transform: Transform::from_translation(Vec3::new(0.0, -50.0, 1.0)), + sprite: Sprite::new(Vec2::new(30.0, 30.0)), + ..Default::default() + }) + .with(Ball { + velocity: 400.0 * Vec3::new(0.5, -0.5, 0.0).normalize(), + }) + // scoreboard + .spawn(TextComponents { + text: Text { + font: asset_server.load("assets/fonts/FiraSans-Bold.ttf").unwrap(), + value: "Score:".to_string(), + style: TextStyle { + color: Color::rgb(0.2, 0.2, 0.8), + font_size: 40.0, + }, + }, + style: Style { + position_type: PositionType::Absolute, + position: Rect { + top: Val::Px(5.0), + left: Val::Px(5.0), + ..Default::default() + }, + ..Default::default() + }, + ..Default::default() + }); + + // Add walls + let wall_material = materials.add(Color::rgb(0.5, 0.5, 0.5).into()); + let wall_thickness = 10.0; + let bounds = Vec2::new(900.0, 600.0); + + commands + // left + .spawn(SpriteComponents { + material: wall_material, + transform: Transform::from_translation(Vec3::new(-bounds.x() / 2.0, 0.0, 0.0)), + sprite: Sprite::new(Vec2::new(wall_thickness, bounds.y() + wall_thickness)), + ..Default::default() + }) + .with(Collider::Solid) + // right + .spawn(SpriteComponents { + material: wall_material, + transform: Transform::from_translation(Vec3::new(bounds.x() / 2.0, 0.0, 0.0)), + sprite: Sprite::new(Vec2::new(wall_thickness, bounds.y() + wall_thickness)), + ..Default::default() + }) + .with(Collider::Solid) + // bottom + .spawn(SpriteComponents { + material: wall_material, + transform: Transform::from_translation(Vec3::new(0.0, -bounds.y() / 2.0, 0.0)), + sprite: Sprite::new(Vec2::new(bounds.x() + wall_thickness, wall_thickness)), + ..Default::default() + }) + .with(Collider::Solid) + // top + .spawn(SpriteComponents { + material: wall_material, + transform: Transform::from_translation(Vec3::new(0.0, bounds.y() / 2.0, 0.0)), + sprite: Sprite::new(Vec2::new(bounds.x() + wall_thickness, wall_thickness)), + ..Default::default() + }) + .with(Collider::Solid); + + // Add bricks + let brick_rows = 4; + let brick_columns = 5; + let brick_spacing = 20.0; + let brick_size = Vec2::new(150.0, 30.0); + let bricks_width = brick_columns as f32 * (brick_size.x() + brick_spacing) - brick_spacing; + // center the bricks and move them up a bit + let bricks_offset = Vec3::new(-(bricks_width - brick_size.x()) / 2.0, 100.0, 0.0); + + for row in 0..brick_rows { + let y_position = row as f32 * (brick_size.y() + brick_spacing); + for column in 0..brick_columns { + let brick_position = Vec3::new( + column as f32 * (brick_size.x() + brick_spacing), + y_position, + 0.0, + ) + bricks_offset; + commands + // brick + .spawn(SpriteComponents { + material: materials.add(Color::rgb(0.2, 0.2, 0.8).into()), + sprite: Sprite::new(brick_size), + transform: Transform::from_translation(brick_position), + ..Default::default() + }) + .with(Collider::Scorable); + } + } +} + +fn paddle_movement_system( + time: Res