From 239505125ebf9032e6587cba94b82d80e8743768 Mon Sep 17 00:00:00 2001 From: NIMFER Date: Thu, 28 Mar 2024 16:42:55 +0100 Subject: [PATCH] moved game logic to lib.rs, added back mobile, changed the app icon --- Cargo.lock | 236 +++++++++ Cargo.toml | 9 +- mobile/.cargo/config.toml | 5 + mobile/.gitignore | 3 + mobile/Cargo.toml | 34 ++ mobile/Makefile | 29 ++ mobile/build_rust_deps.sh | 55 +++ .../AppIcon.appiconset/Contents.json | 14 + .../AppIcon.appiconset/icon_1024x1024.png | Bin 0 -> 50560 bytes mobile/ios-src/Assets.xcassets/Contents.json | 6 + mobile/ios-src/Info.plist | 35 ++ mobile/ios-src/LaunchScreen.storyboard | 37 ++ mobile/ios-src/bindings.h | 1 + mobile/ios-src/main.m | 6 + mobile/manifest.yaml | 11 + mobile/mobile.xcodeproj/project.pbxproj | 465 ++++++++++++++++++ .../xcshareddata/xcschemes/mobile.xcscheme | 78 +++ mobile/src/lib.rs | 20 + src/lib.rs | 103 ++++ src/main.rs | 124 ++--- 20 files changed, 1188 insertions(+), 83 deletions(-) create mode 100644 mobile/.cargo/config.toml create mode 100644 mobile/.gitignore create mode 100644 mobile/Cargo.toml create mode 100644 mobile/Makefile create mode 100644 mobile/build_rust_deps.sh create mode 100644 mobile/ios-src/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 mobile/ios-src/Assets.xcassets/AppIcon.appiconset/icon_1024x1024.png create mode 100644 mobile/ios-src/Assets.xcassets/Contents.json create mode 100644 mobile/ios-src/Info.plist create mode 100644 mobile/ios-src/LaunchScreen.storyboard create mode 100644 mobile/ios-src/bindings.h create mode 100644 mobile/ios-src/main.m create mode 100644 mobile/manifest.yaml create mode 100644 mobile/mobile.xcodeproj/project.pbxproj create mode 100644 mobile/mobile.xcodeproj/xcshareddata/xcschemes/mobile.xcscheme create mode 100644 mobile/src/lib.rs create mode 100644 src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index d5c05cf..4be259a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1419,6 +1419,18 @@ dependencies = [ "thiserror", ] +[[package]] +name = "calloop-wayland-source" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02" +dependencies = [ + "calloop", + "rustix", + "wayland-backend", + "wayland-client", +] + [[package]] name = "cc" version = "1.0.90" @@ -2708,6 +2720,15 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +[[package]] +name = "memmap2" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" +dependencies = [ + "libc", +] + [[package]] name = "metal" version = "0.27.0" @@ -2745,6 +2766,15 @@ version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" +[[package]] +name = "mobile" +version = "0.1.0" +dependencies = [ + "bevy", + "cpal", + "ttt_ce", +] + [[package]] name = "naga" version = "0.19.2" @@ -3355,6 +3385,15 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" +[[package]] +name = "quick-xml" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +dependencies = [ + "memchr", +] + [[package]] name = "quote" version = "1.0.35" @@ -3608,12 +3647,31 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sctk-adwaita" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b2eaf3a5b264a521b988b2e73042e742df700c4f962cde845d1541adb46550" +dependencies = [ + "ab_glyph", + "log", + "memmap2", + "smithay-client-toolkit", + "tiny-skia", +] + [[package]] name = "semver" version = "1.0.22" @@ -3718,6 +3776,31 @@ dependencies = [ "serde", ] +[[package]] +name = "smithay-client-toolkit" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" +dependencies = [ + "bitflags 2.5.0", + "calloop", + "calloop-wayland-source", + "cursor-icon", + "libc", + "log", + "memmap2", + "rustix", + "thiserror", + "wayland-backend", + "wayland-client", + "wayland-csd-frame", + "wayland-cursor", + "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", +] + [[package]] name = "smol_str" version = "0.2.1" @@ -3754,6 +3837,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strict-num" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" + [[package]] name = "svg_fmt" version = "0.4.2" @@ -3929,6 +4018,31 @@ dependencies = [ "weezl", ] +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "tiny-skia-path", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -4272,6 +4386,114 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +[[package]] +name = "wayland-backend" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d50fa61ce90d76474c87f5fc002828d81b32677340112b4ef08079a9d459a40" +dependencies = [ + "cc", + "downcast-rs", + "rustix", + "scoped-tls", + "smallvec", + "wayland-sys", +] + +[[package]] +name = "wayland-client" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f" +dependencies = [ + "bitflags 2.5.0", + "rustix", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.5.0", + "cursor-icon", + "wayland-backend", +] + +[[package]] +name = "wayland-cursor" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71ce5fa868dd13d11a0d04c5e2e65726d0897be8de247c0c5a65886e283231ba" +dependencies = [ + "rustix", + "wayland-client", + "xcursor", +] + +[[package]] +name = "wayland-protocols" +version = "0.31.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" +dependencies = [ + "bitflags 2.5.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" +dependencies = [ + "bitflags 2.5.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" +dependencies = [ + "bitflags 2.5.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-scanner" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b3a62929287001986fb58c789dce9b67604a397c15c611ad9f747300b6c283" +dependencies = [ + "proc-macro2", + "quick-xml", + "quote", +] + +[[package]] +name = "wayland-sys" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15a0c8eaff5216d07f226cb7a549159267f3467b289d9a2e52fd3ef5aae2b7af" +dependencies = [ + "dlib", + "log", + "pkg-config", +] + [[package]] name = "web-sys" version = "0.3.69" @@ -4754,6 +4976,7 @@ version = "0.29.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d59ad965a635657faf09c8f062badd885748428933dad8e8bdd64064d92e5ca" dependencies = [ + "ahash", "android-activity", "atomic-waker", "bitflags 2.5.0", @@ -4767,6 +4990,7 @@ dependencies = [ "js-sys", "libc", "log", + "memmap2", "ndk", "ndk-sys", "objc2 0.4.1", @@ -4776,10 +5000,16 @@ dependencies = [ "raw-window-handle 0.6.0", "redox_syscall 0.3.5", "rustix", + "sctk-adwaita", + "smithay-client-toolkit", "smol_str", "unicode-segmentation", "wasm-bindgen", "wasm-bindgen-futures", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-protocols-plasma", "web-sys", "web-time", "windows-sys 0.48.0", @@ -4838,6 +5068,12 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e63e71c4b8bd9ffec2c963173a4dc4cbde9ee96961d4fcb4429db9929b606c34" +[[package]] +name = "xcursor" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a0ccd7b4a5345edfcd0c3535718a4e9ff7798ffc536bb5b5a0e26ff84732911" + [[package]] name = "xi-unicode" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index 8fe1ced..d6f4a87 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,9 @@ authors = ["Mikolaj Wojciech 'Nimfer' Gorski"] # ToDo: you are the author ;) edition = "2021" exclude = ["dist", "build", "assets", "credits"] +[workspace] +members = ["mobile"] + [profile.dev.package."*"] opt-level = 3 @@ -53,6 +56,7 @@ bevy = { version = "0.13", default-features = false, features = [ "png", "hdr", "x11", + "wayland", "bevy_gizmos", "tonemapping_luts", "default_font", @@ -63,12 +67,13 @@ bevy_kira_audio = { version = "0.19" } bevy_asset_loader = { version = "0.20" } rand = { version = "0.8.3" } webbrowser = { version = "0.8", features = ["hardened"] } +bevy_editor_pls = "0.8.1" +bevy_xpbd_3d = {git = "https://git.opencodebox.com/MikolajG/bevy_xpbd", branch = "reflect-serialize"} # keep the following in sync with Bevy's dependencies winit = { version = "0.29", default-features = false } image = { version = "0.24", default-features = false } -bevy_editor_pls = "0.8.1" -bevy_xpbd_3d = {git = "https://git.opencodebox.com/MikolajG/bevy_xpbd", branch = "reflect-serialize"} + [build-dependencies] embed-resource = "1" diff --git a/mobile/.cargo/config.toml b/mobile/.cargo/config.toml new file mode 100644 index 0000000..19a6340 --- /dev/null +++ b/mobile/.cargo/config.toml @@ -0,0 +1,5 @@ +# Flag to notify the compiler we're building for the iOS simulator from an Apple silicon mac +# This needs some workarounds for now +# See https://github.com/bevyengine/bevy/pull/10178 - remove if it's not needed anymore. +[target.aarch64-apple-ios-sim] +rustflags = ["--cfg=ios_simulator"] diff --git a/mobile/.gitignore b/mobile/.gitignore new file mode 100644 index 0000000..b446ed7 --- /dev/null +++ b/mobile/.gitignore @@ -0,0 +1,3 @@ +mobile.xcodeproj/xcuserdata/ +mobile.xcodeproj/project.xcworkspace/ +build/ diff --git a/mobile/Cargo.toml b/mobile/Cargo.toml new file mode 100644 index 0000000..cfdb8a7 --- /dev/null +++ b/mobile/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "mobile" +version = "0.1.0" +edition = "2021" +publish = false + +[lib] +name = "mobile" +crate-type = ["staticlib", "cdylib"] + +[dependencies] +ttt_ce = { path = ".." } # ToDo +bevy = { version = "0.13", default-features = false } + +# As long as Kira doesn't expose a feature for this, we need to enable it +# See https://github.com/tesselode/kira/pull/51 +[target."cfg(target_os = \"android\")".dependencies.cpal] +version = "0.15" +features = ["oboe-shared-stdcxx"] + +[package.metadata.android] +package = "me.nikl.bevygame" # ToDo +apk_name = "BevyGame" # ToDo same as GAME_OSX_APP_NAME in release workflow +assets = "../assets" +strip = "strip" +resources = "../build/android/res" +build_targets = ["aarch64-linux-android"] + +[package.metadata.android.sdk] +target_sdk_version = 33 + +[package.metadata.android.application] +icon = "@mipmap/icon" +label = "Bevy Game" # ToDo diff --git a/mobile/Makefile b/mobile/Makefile new file mode 100644 index 0000000..4fb6908 --- /dev/null +++ b/mobile/Makefile @@ -0,0 +1,29 @@ +.PHONY: xcodebuild run install boot-sim generate clean + +DEVICE = ${DEVICE_ID} +ifndef DEVICE_ID + DEVICE=$(shell xcrun simctl list devices 'iOS' | grep -v 'unavailable' | grep -v '^--' | grep -v '==' | head -n 1 | grep -E -o -i "([0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12})") +endif + +run: install + # Todo: change the bundle identifier (then remove this comment :P) + xcrun simctl launch --console $(DEVICE) me.nikl.bevygame + +boot-sim: + xcrun simctl boot $(DEVICE) || true + +install: xcodebuild-simulator boot-sim + xcrun simctl install $(DEVICE) build/Build/Products/Debug-iphonesimulator/mobile.app + +xcodebuild-simulator: + IOS_TARGETS=x86_64-apple-ios xcodebuild -scheme mobile -configuration Debug -derivedDataPath build -destination "id=$(DEVICE)" + +xcodebuild-iphone: + IOS_TARGETS=aarch64-apple-ios xcodebuild -scheme mobile -configuration Debug -derivedDataPath build -arch arm64 + +xcodebuild-iphone-release: + IOS_TARGETS=aarch64-apple-ios xcodebuild -scheme mobile -configuration Release -derivedDataPath build -arch arm64 + +clean: + rm -r build + cargo clean diff --git a/mobile/build_rust_deps.sh b/mobile/build_rust_deps.sh new file mode 100644 index 0000000..af8e0a7 --- /dev/null +++ b/mobile/build_rust_deps.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + +# based on https://github.com/mozilla/glean/blob/main/build-scripts/xc-universal-binary.sh + +set -eux + +PATH=$PATH:$HOME/.cargo/bin + +RELFLAG= +if [[ "$CONFIGURATION" != "Debug" ]]; then + RELFLAG="--profile dist" +fi + +set -euvx + +if [[ -n "${DEVELOPER_SDK_DIR:-}" ]]; then + # Assume we're in Xcode, which means we're probably cross-compiling. + # In this case, we need to add an extra library search path for build scripts and proc-macros, + # which run on the host instead of the target. + # (macOS Big Sur does not have linkable libraries in /usr/lib/.) + export LIBRARY_PATH="${DEVELOPER_SDK_DIR}/MacOSX.sdk/usr/lib:${LIBRARY_PATH:-}" +fi + +# add homebrew bin path, as it's the most commonly used package manager on macOS +# this is needed for cmake on apple arm processors as it's not available by default +export PATH="$PATH:/opt/homebrew/bin" + +IS_SIMULATOR=0 +if [ "${LLVM_TARGET_TRIPLE_SUFFIX-}" = "-simulator" ]; then + IS_SIMULATOR=1 +fi + +for arch in $ARCHS; do + case "$arch" in + x86_64) + if [ $IS_SIMULATOR -eq 0 ]; then + echo "Building for x86_64, but not a simulator build. What's going on?" >&2 + exit 2 + fi + + # Intel iOS simulator + export CFLAGS_x86_64_apple_ios="-target x86_64-apple-ios" + cargo rustc --crate-type staticlib --lib $RELFLAG --target x86_64-apple-ios + ;; + + arm64) + if [ $IS_SIMULATOR -eq 0 ]; then + # Hardware iOS targets + cargo rustc --crate-type staticlib --lib $RELFLAG --target aarch64-apple-ios + else + # M1 iOS simulator -- currently in Nightly only and requires to build `libstd` + cargo rustc --crate-type staticlib --lib $RELFLAG --target aarch64-apple-ios-sim + fi + esac +done diff --git a/mobile/ios-src/Assets.xcassets/AppIcon.appiconset/Contents.json b/mobile/ios-src/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..5a60908 --- /dev/null +++ b/mobile/ios-src/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images" : [ + { + "filename" : "icon_1024x1024.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/mobile/ios-src/Assets.xcassets/AppIcon.appiconset/icon_1024x1024.png b/mobile/ios-src/Assets.xcassets/AppIcon.appiconset/icon_1024x1024.png new file mode 100644 index 0000000000000000000000000000000000000000..a79c37deee6fd41a3a8eb4a42b1d5072f94057a1 GIT binary patch literal 50560 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 literal 0 HcmV?d00001 diff --git a/mobile/ios-src/Assets.xcassets/Contents.json b/mobile/ios-src/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/mobile/ios-src/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/mobile/ios-src/Info.plist b/mobile/ios-src/Info.plist new file mode 100644 index 0000000..f815a6b --- /dev/null +++ b/mobile/ios-src/Info.plist @@ -0,0 +1,35 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 0.1.1 + CFBundleIconName + AppIcon + CFBundleVersion + 0.1.1 + UILaunchStoryboardName + LaunchScreen + UIRequiresFullScreen + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationPortraitUpsideDown + + + diff --git a/mobile/ios-src/LaunchScreen.storyboard b/mobile/ios-src/LaunchScreen.storyboard new file mode 100644 index 0000000..324de1d --- /dev/null +++ b/mobile/ios-src/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mobile/ios-src/bindings.h b/mobile/ios-src/bindings.h new file mode 100644 index 0000000..a705f03 --- /dev/null +++ b/mobile/ios-src/bindings.h @@ -0,0 +1 @@ +void main_rs(void); diff --git a/mobile/ios-src/main.m b/mobile/ios-src/main.m new file mode 100644 index 0000000..7d152fb --- /dev/null +++ b/mobile/ios-src/main.m @@ -0,0 +1,6 @@ +#import "bindings.h" + +int main() { + main_rs(); + return 0; +} diff --git a/mobile/manifest.yaml b/mobile/manifest.yaml new file mode 100644 index 0000000..4be78a5 --- /dev/null +++ b/mobile/manifest.yaml @@ -0,0 +1,11 @@ +android: + gradle: true + # this assets configuration is currently only used without gradle! + #assets: + # - "../assets/*" + icon: "ios-src/Assets.xcassets/AppIcon.appiconset/icon_1024x1024.png" + manifest: + package: "me.nikl.bevygame" # Todo + version_code: 3 # Todo you should start at 1 + application: + label: "Bevy game" # Todo diff --git a/mobile/mobile.xcodeproj/project.pbxproj b/mobile/mobile.xcodeproj/project.pbxproj new file mode 100644 index 0000000..d98a2c0 --- /dev/null +++ b/mobile/mobile.xcodeproj/project.pbxproj @@ -0,0 +1,465 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 134866208A035F8615C99114 /* Metal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96A1E5B62F48B379829E8A0D /* Metal.framework */; }; + 2469A4292A6F9AC200ACF4EF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2469A4282A6F9AC200ACF4EF /* Assets.xcassets */; }; + 2469A42B2A6FAC7000ACF4EF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2469A42A2A6FAC7000ACF4EF /* LaunchScreen.storyboard */; }; + 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 */; }; + 57CD6306253C7A940098CD4A /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 57CD6305253C7A940098CD4A /* AudioToolbox.framework */; }; + 57CD630E253C80EC0098CD4A /* assets in Resources */ = {isa = PBXBuildFile; fileRef = 57CD630A253C7F5F0098CD4A /* assets */; }; +/* 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 = ""; }; + 2469A4282A6F9AC200ACF4EF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "ios-src/Assets.xcassets"; sourceTree = SOURCE_ROOT; }; + 2469A42A2A6FAC7000ACF4EF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = ios-src/LaunchScreen.storyboard; sourceTree = ""; }; + 55EAC02897847195D2F44C15 /* mobile.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = mobile.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 57CD6305253C7A940098CD4A /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; + 57CD630A253C7F5F0098CD4A /* assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = assets; path = ../../assets; sourceTree = ""; }; + 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 */, + 57CD6306253C7A940098CD4A /* AudioToolbox.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 321F7D6A765B38E746C35105 /* Products */ = { + isa = PBXGroup; + children = ( + 55EAC02897847195D2F44C15 /* mobile.app */, + ); + name = Products; + sourceTree = ""; + }; + 4F1D6F28B8A5D1927AB0ADED /* ios-src */ = { + isa = PBXGroup; + children = ( + 2469A4282A6F9AC200ACF4EF /* Assets.xcassets */, + 57CD630A253C7F5F0098CD4A /* assets */, + 160DB77300A3F1806F024D47 /* bindings.h */, + 8EE7F1E3B0303533925D7E33 /* Info.plist */, + AF7DE91055EBD05ED77E57F9 /* main.m */, + ); + path = "ios-src"; + sourceTree = ""; + }; + 8F2E3E6040EAD2EC9F3FA530 = { + isa = PBXGroup; + children = ( + 2469A42A2A6FAC7000ACF4EF /* LaunchScreen.storyboard */, + 4F1D6F28B8A5D1927AB0ADED /* ios-src */, + EB028409C2D0655412DA6E44 /* Frameworks */, + 321F7D6A765B38E746C35105 /* Products */, + ); + sourceTree = ""; + }; + EB028409C2D0655412DA6E44 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 57CD6305253C7A940098CD4A /* AudioToolbox.framework */, + 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 = 1; + productName = cargo_ios; + }; +/* End PBXLegacyTarget section */ + +/* Begin PBXNativeTarget section */ + 3BDB8152E4962373181B4FE5 /* mobile */ = { + isa = PBXNativeTarget; + buildConfigurationList = E714A1AEAAE517C348B5BD27 /* Build configuration list for PBXNativeTarget "mobile" */; + buildPhases = ( + 9F13800790AD9DBC2BC0F116 /* Sources */, + D5A822CB2D6847BA8800BE4C /* Frameworks */, + 57CD630D253C80E60098CD4A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 19D4B9C22ADC6705B5132B4C /* PBXTargetDependency */, + ); + name = mobile; + productName = mobile; + productReference = 55EAC02897847195D2F44C15 /* mobile.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 8DBF1E2B5C613DA41701F6D9 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1240; + }; + buildConfigurationList = 9D43D41707A5C30B227B83F9 /* Build configuration list for PBXProject "mobile" */; + compatibilityVersion = "Xcode 10.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 8F2E3E6040EAD2EC9F3FA530; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3BDB8152E4962373181B4FE5 /* mobile */, + D08AEBE0B1A9C9A7B8C7B33F /* cargo_ios */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 57CD630D253C80E60098CD4A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2469A42B2A6FAC7000ACF4EF /* LaunchScreen.storyboard in Resources */, + 2469A4292A6F9AC200ACF4EF /* Assets.xcassets in Resources */, + 57CD630E253C80EC0098CD4A /* assets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + 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; + CODE_SIGN_IDENTITY = ""; + 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 = ""; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "ios-src/", + ); + INFOPLIST_FILE = "ios-src/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + "LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=arm64]" = ( + "$(inherited)", + "../target/aarch64-apple-ios/dist", + ); + "LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=arm64]" = ( + "$(inherited)", + "../target/aarch64-apple-ios-sim/dist", + ); + "LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=x86_64]" = ( + "$(inherited)", + "../target/x86_64-apple-ios/dist", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-lmobile", + "-lc++abi", + ); + PRODUCT_BUNDLE_IDENTIFIER /* Todo */ = me.nikl.bevygame; + 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + 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; + CODE_SIGN_IDENTITY = ""; + 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 = ""; + DEVELOPMENT_TEAM = ""; + ENABLE_BITCODE = NO; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "ios-src/", + ); + INFOPLIST_FILE = "ios-src/Info.plist"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + "LIBRARY_SEARCH_PATHS[sdk=iphoneos*][arch=arm64]" = ( + "$(inherited)", + "../target/aarch64-apple-ios/debug", + ); + "LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=arm64]" = ( + "$(inherited)", + "../target/aarch64-apple-ios-sim/debug", + ); + "LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*][arch=x86_64]" = ( + "$(inherited)", + "../target/x86_64-apple-ios/debug", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-lmobile", + "-lc++abi", + ); + PRODUCT_BUNDLE_IDENTIFIER /* Todo */ = me.nikl.bevygame; + 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 "mobile" */ = { + 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 "mobile" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A2D5B73DD30D562B6F366526 /* Debug */, + 5B14EC4ADC81FBF1F8CF20E9 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Debug; + }; +/* End XCConfigurationList section */ + }; + rootObject = 8DBF1E2B5C613DA41701F6D9 /* Project object */; +} diff --git a/mobile/mobile.xcodeproj/xcshareddata/xcschemes/mobile.xcscheme b/mobile/mobile.xcodeproj/xcshareddata/xcschemes/mobile.xcscheme new file mode 100644 index 0000000..495aaf6 --- /dev/null +++ b/mobile/mobile.xcodeproj/xcshareddata/xcschemes/mobile.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mobile/src/lib.rs b/mobile/src/lib.rs new file mode 100644 index 0000000..d32a94b --- /dev/null +++ b/mobile/src/lib.rs @@ -0,0 +1,20 @@ +use bevy::prelude::*; +use bevy::window::WindowMode; +use ttt_ce::GamePlugin; + +#[bevy_main] +fn main() { + App::new() + .add_plugins(( + DefaultPlugins.set(WindowPlugin { + primary_window: Some(Window { + resizable: false, + mode: WindowMode::BorderlessFullscreen, + ..default() + }), + ..default() + }), + GamePlugin, + )) + .run() +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..d3df9e3 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,103 @@ +/* +Trouble in Terror Town: Community Edition +Copyright (C) 2024 Mikolaj Wojciech Gorski + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#![allow(clippy::type_complexity)] + +use bevy::prelude::*; +#[cfg(debug_assertions)] +use bevy::diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin}; +use bevy_xpbd_3d::prelude::*; +use bevy_editor_pls::prelude::*; +mod charcacter_controller; +use charcacter_controller::*; + +pub struct GamePlugin; + +impl Plugin for GamePlugin { + fn build(&self, app: &mut App) { + app.add_plugins(( + PhysicsPlugins::default(), + CharacterControllerPlugin, + )) + .add_systems(Startup, setup) + .add_systems(Update, spawn_map); + + #[cfg(debug_assertions)] + { + app.add_plugins((FrameTimeDiagnosticsPlugin, EditorPlugin::default(), LogDiagnosticsPlugin::default())); + } + + app.world.init_resource::(); + } +} + +#[derive(Resource, Default, Debug)] +struct IsMapSpawned(bool); + +/// set up a simple 3D scene +fn setup( + mut commands: Commands, + mut meshes: ResMut>, + mut materials: ResMut>, +) { + + //player + commands.spawn((CharacterControllerBundle::new(Collider::capsule(1.0, 0.5), CharacterController::default()), PbrBundle{ + mesh: meshes.add(Capsule3d::new(0.5, 1.0)), + material: materials.add(Color::rgb_u8(124, 144, 255)), + transform: Transform::from_xyz(0.0, 5.0, 0.0), + ..default() + })); + // light + commands.spawn(PointLightBundle { + point_light: PointLight { + shadows_enabled: true, + ..default() + }, + transform: Transform::from_xyz(4.0, 8.0, 4.0), + ..default() + }); + // camera + commands.spawn(Camera3dBundle { + transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y), + ..default() + }); +} + +fn spawn_map( + asset_server: Res, + mut is_map_spawned: ResMut, + mut commands: Commands, +){ + if is_map_spawned.0 {return;} + + let scene = asset_server.load("test_map.gltf#Scene0"); + + commands.spawn(( + SceneBundle { + scene: scene.clone(), + transform: Transform::from_xyz(0.0, 0.0, 0.0), + ..default() + }, + AsyncSceneCollider::new(Some(ComputedCollider::TriMesh)), + RigidBody::Static, + )); + + println!("map spawned!"); + + is_map_spawned.0 = true +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index e0facc7..c0ae3e7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,94 +15,56 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -use bevy::{diagnostic::FrameTimeDiagnosticsPlugin, prelude::*, window::Cursor, winit::WinitWindows}; -use bevy_xpbd_3d::prelude::*; -use bevy_editor_pls::prelude::*; -mod charcacter_controller; -use charcacter_controller::*; +// disable console on windows for release builds +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + +use bevy::asset::AssetMetaCheck; +use bevy::prelude::*; +use bevy::window::PrimaryWindow; +use bevy::winit::WinitWindows; +use bevy::DefaultPlugins; +use ttt_ce::GamePlugin; +use std::io::Cursor; +use winit::window::Icon; fn main() { - let mut app = App::new(); - - app - .add_plugins(( - DefaultPlugins.set(WindowPlugin { + App::new() + .insert_resource(Msaa::Off) + .insert_resource(AssetMetaCheck::Never) + .insert_resource(ClearColor(Color::rgb(0.4, 0.4, 0.4))) + .add_plugins(DefaultPlugins.set(WindowPlugin { primary_window: Some(Window { - cursor: Cursor::default(), - present_mode: bevy::window::PresentMode::AutoNoVsync, - mode: bevy::window::WindowMode::Windowed, - title: "Trouble in Terror Town: Community Edition".to_string(), - resizable: true, + title: "Bevy game".to_string(), // ToDo + // Bind to canvas included in `index.html` + canvas: Some("#bevy".to_owned()), + // Tells wasm not to override default event handling, like F5 and Ctrl+R + prevent_default_event_handling: false, ..default() }), ..default() - }), - PhysicsPlugins::default(), - EditorPlugin::default(), - FrameTimeDiagnosticsPlugin::default(), - CharacterControllerPlugin, - )) - .add_systems(Startup, setup) - .add_systems(Update, spawn_map); - - app.world.init_resource::(); - - app.run(); + })) + .add_plugins(GamePlugin) + .add_systems(Startup, set_window_icon) + .run(); } -#[derive(Resource, Default, Debug)] -struct IsMapSpawned(bool); - -/// set up a simple 3D scene -fn setup( - mut commands: Commands, - mut meshes: ResMut>, - mut materials: ResMut>, +// Sets the icon on windows and X11 +fn set_window_icon( + windows: NonSend, + primary_window: Query>, ) { - - //player - commands.spawn((CharacterControllerBundle::new(Collider::capsule(1.0, 0.5), CharacterController::default()), PbrBundle{ - mesh: meshes.add(Capsule3d::new(0.5, 1.0)), - material: materials.add(Color::rgb_u8(124, 144, 255)), - transform: Transform::from_xyz(0.0, 5.0, 0.0), - ..default() - })); - // light - commands.spawn(PointLightBundle { - point_light: PointLight { - shadows_enabled: true, - ..default() - }, - transform: Transform::from_xyz(4.0, 8.0, 4.0), - ..default() - }); - // camera - commands.spawn(Camera3dBundle { - transform: Transform::from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3::ZERO, Vec3::Y), - ..default() - }); -} - -fn spawn_map( - asset_server: Res, - mut is_map_spawned: ResMut, - mut commands: Commands, -){ - if is_map_spawned.0 {return;} - - let scene = asset_server.load("test_map.gltf#Scene0"); - - commands.spawn(( - SceneBundle { - scene: scene.clone(), - transform: Transform::from_xyz(0.0, 0.0, 0.0), - ..default() - }, - AsyncSceneCollider::new(Some(ComputedCollider::TriMesh)), - RigidBody::Static, + let primary_entity = primary_window.single(); + let Some(primary) = windows.get_window(primary_entity) else { + return; + }; + let icon_buf = Cursor::new(include_bytes!( + "../build/macos/AppIcon.iconset/icon_256x256.png" )); - - println!("map spawned!"); - - is_map_spawned.0 = true -} \ No newline at end of file + if let Ok(image) = image::load(icon_buf, image::ImageFormat::Png) { + let image = image.into_rgba8(); + let (width, height) = image.dimensions(); + let rgba = image.into_raw(); + let icon = Icon::from_rgba(rgba, width, height).unwrap(); + primary.set_window_icon(Some(icon)); + }; +}