mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-21 13:09:54 +02:00
Merge pull request #1204 from castdrian/ios-improvements
feat(ios): improve branding and fix haptic feedback
This commit is contained in:
@@ -94,8 +94,8 @@ jobs:
|
||||
if: github.repository == 'bryanthaboi/gen1recomp'
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: gen1recomp-ios-ipa
|
||||
path: dist/ios/gen1recomp.ipa
|
||||
name: gen1recomp++-ios-ipa
|
||||
path: dist/ios/gen1recomp++.ipa
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
- name: clean up signing keychain
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
|
||||
HEAD_REPOSITORY: ${{ github.event.workflow_run.head_repository.full_name }}
|
||||
run: |
|
||||
artifact_id="$(gh api "repos/$GITHUB_REPOSITORY/actions/runs/$RUN_ID/artifacts" --jq '.artifacts[] | select(.name == "gen1recomp-ios-ipa") | .id')"
|
||||
artifact_id="$(gh api "repos/$GITHUB_REPOSITORY/actions/runs/$RUN_ID/artifacts" --jq '.artifacts[] | select(.name == "gen1recomp++-ios-ipa") | .id')"
|
||||
[ -n "$artifact_id" ] || exit 0
|
||||
head_owner="${HEAD_REPOSITORY%%/*}"
|
||||
pr_number="$(gh api "repos/$GITHUB_REPOSITORY/pulls?state=open&head=$head_owner:$HEAD_BRANCH" --jq '.[0].number // empty')"
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
with:
|
||||
message: |
|
||||
[gen1recomp.ipa](${{ steps.artifact.outputs.artifact_url }})
|
||||
[gen1recomp++.ipa](${{ steps.artifact.outputs.artifact_url }})
|
||||
|
||||
**Commit**: [#${{ steps.build-info.outputs.hash }}](https://github.com/${{ github.event.workflow_run.head_repository.full_name }}/commit/${{ github.event.workflow_run.head_sha }})
|
||||
**Build Time**: `${{ steps.build-info.outputs.time }}`
|
||||
|
||||
@@ -444,9 +444,9 @@ jobs:
|
||||
[ -n "$apk" ] || { echo "::error::no Android APK found under dist/android/debug"; exit 1; }
|
||||
cp "$apk" "$outdir/gen1recomp-${v}-android.apk"
|
||||
|
||||
ipa="dist/ios/gen1recomp.ipa"
|
||||
ipa="dist/ios/gen1recomp++.ipa"
|
||||
[ -f "$ipa" ] || { echo "::error::$ipa not found (expected from scripts/build_ios.sh --device)"; exit 1; }
|
||||
cp "$ipa" "$outdir/gen1recomp-${v}-ios.ipa"
|
||||
cp "$ipa" "$outdir/gen1recomp++-${v}-ios.ipa"
|
||||
|
||||
swzip="dist/switch/gen1recomp-${v}-switch.zip"
|
||||
[ -f "$swzip" ] || { echo "::error::$swzip not found (expected from scripts/build_switch.sh --fused → pack_sd_zip.sh)"; exit 1; }
|
||||
@@ -580,7 +580,7 @@ jobs:
|
||||
"dist/release/gen1recomp-${v}-linux.zip"
|
||||
"dist/release/gen1recomp-${v}-linux-arm64.AppImage"
|
||||
"dist/release/gen1recomp-${v}-android.apk"
|
||||
"dist/release/gen1recomp-${v}-ios.ipa"
|
||||
"dist/release/gen1recomp++-${v}-ios.ipa"
|
||||
"dist/release/gen1recomp-${v}-switch.zip"
|
||||
"dist/release/gen1recomp-${v}-xbox-uwp.zip"
|
||||
"dist/release/gen1recomp-${v}-rg34xxsp-stockos64-mod.zip"
|
||||
@@ -602,14 +602,15 @@ jobs:
|
||||
run: |
|
||||
set -euo pipefail
|
||||
v="${{ needs.version.outputs.version }}"
|
||||
ipa="dist/release/gen1recomp-${v}-ios.ipa"
|
||||
ipa="dist/release/gen1recomp++-${v}-ios.ipa"
|
||||
app_repo="mobile/ios/app-repo.json"
|
||||
[ -f "$ipa" ] || { echo "::error::$ipa not found"; exit 1; }
|
||||
[ -f "$app_repo" ] || { echo "::error::$app_repo not found"; exit 1; }
|
||||
|
||||
date="$(date -u +"%Y-%m-%d")"
|
||||
size="$(wc -c < "$ipa" | tr -d '[:space:]')"
|
||||
download_url="https://github.com/${GITHUB_REPOSITORY}/releases/download/v${v}/gen1recomp-${v}-ios.ipa"
|
||||
download_url="https://github.com/${GITHUB_REPOSITORY}/releases/download/v${v}/gen1recomp++-${v}-ios.ipa"
|
||||
bundle_id="com.theboisclub.gen1recompplusplus"
|
||||
localized_description="Gen1Recomp - A native Lua / LÖVE2D recreation of Gen 1 Poke"
|
||||
release_notes="$(GH_TOKEN="${{ github.token }}" gh release view "v${v}" --json body --jq '.body // ""' 2>/dev/null || true)"
|
||||
if [ -n "$release_notes" ]; then
|
||||
@@ -623,15 +624,15 @@ jobs:
|
||||
--argjson size "$size" \
|
||||
'{version: $version, date: $date, size: $size, downloadURL: $download_url, localizedDescription: $localized_description}')"
|
||||
|
||||
if jq -e --arg version "$v" \
|
||||
'any(.apps[] | select(.bundleIdentifier == "com.theboisclub.gen1recomp").versions[]?; .version == $version)' \
|
||||
if jq -e --arg bundle_id "$bundle_id" --arg version "$v" \
|
||||
'any(.apps[] | select(.bundleIdentifier == $bundle_id).versions[]?; .version == $version)' \
|
||||
"$app_repo" >/dev/null; then
|
||||
jq --arg version "$v" --argjson entry "$entry" \
|
||||
'(.apps[] | select(.bundleIdentifier == "com.theboisclub.gen1recomp").versions) |= map(if .version == $version then $entry else . end)' \
|
||||
jq --arg bundle_id "$bundle_id" --arg version "$v" --argjson entry "$entry" \
|
||||
'(.apps[] | select(.bundleIdentifier == $bundle_id).versions) |= map(if .version == $version then $entry else . end)' \
|
||||
"$app_repo" > "$app_repo.tmp"
|
||||
else
|
||||
jq --argjson entry "$entry" \
|
||||
'(.apps[] | select(.bundleIdentifier == "com.theboisclub.gen1recomp").versions) |= [$entry] + .' \
|
||||
jq --arg bundle_id "$bundle_id" --argjson entry "$entry" \
|
||||
'(.apps[] | select(.bundleIdentifier == $bundle_id).versions) |= [$entry] + .' \
|
||||
"$app_repo" > "$app_repo.tmp"
|
||||
fi
|
||||
mv "$app_repo.tmp" "$app_repo"
|
||||
|
||||
@@ -242,7 +242,7 @@ in [docs/linux-arm64-build.md](docs/linux-arm64-build.md).
|
||||
|
||||
## iOS
|
||||
|
||||
Every release ships `gen1recomp-*-ios.ipa`. Sideload it with AltStore
|
||||
Every release ships `gen1recomp++-*-ios.ipa`. Sideload it with AltStore
|
||||
(Windows or Mac) — see [docs/ios-sideload.md](docs/ios-sideload.md). To
|
||||
build and install from source on a Mac instead, see
|
||||
[docs/ios-install.md](docs/ios-install.md).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Sideload the iOS build with AltStore
|
||||
|
||||
Every GitHub Release ships an IPA (`gen1recomp-*-ios.ipa`). Install it on
|
||||
Every GitHub Release ships an IPA (`gen1recomp++-*-ios.ipa`). Install it on
|
||||
your iPhone or iPad with [AltStore Classic](https://altstore.io/) — AltStore
|
||||
re-signs the app with **your** free Apple ID so you do not need a Mac or
|
||||
Xcode.
|
||||
@@ -23,7 +23,7 @@ Stuck? Start here:
|
||||
|
||||
## 2. Install the game
|
||||
|
||||
1. Download `gen1recomp-*-ios.ipa` from
|
||||
1. Download `gen1recomp++-*-ios.ipa` from
|
||||
[Releases](https://github.com/bryanthaboi/gen1recomp/releases).
|
||||
2. Open **AltStore** on the phone (AltServer must be running on the same
|
||||
Wi‑Fi, or keep the phone plugged into the computer).
|
||||
|
||||
@@ -7,7 +7,7 @@ an iOS app with LÖVE 12.0.
|
||||
|
||||
The app uses the public iOS Documents directory as its LÖVE save directory.
|
||||
There is no `pokemon-love2d` subdirectory and the app does not create a
|
||||
README file there. When browsing `On My iPhone > gen1recomp` in Files, the
|
||||
README file there. When browsing `On My iPhone > gen1recomp++` in Files, the
|
||||
directory contains the app's runtime data directly, including:
|
||||
|
||||
- installed mods and downloaded ROMs
|
||||
@@ -46,7 +46,7 @@ scripts/build_ios.sh --device --release --install
|
||||
Device builds require a paired, unlocked device and a valid Apple signing
|
||||
identity. Set `DEVELOPMENT_TEAM` or `CODE_SIGN_IDENTITY` when automatic
|
||||
signing cannot select the intended account. Add `--ipa` to create
|
||||
`dist/ios/gen1recomp.ipa`.
|
||||
`dist/ios/gen1recomp++.ipa`.
|
||||
|
||||
The script verifies the final app before packaging it:
|
||||
|
||||
@@ -76,10 +76,10 @@ option.
|
||||
Simulator and device app bundles are copied to:
|
||||
|
||||
```text
|
||||
dist/ios/Debug-iphonesimulator/gen1recomp.app
|
||||
dist/ios/Release-iphonesimulator/gen1recomp.app
|
||||
dist/ios/Debug-iphoneos/gen1recomp.app
|
||||
dist/ios/Release-iphoneos/gen1recomp.app
|
||||
dist/ios/Debug-iphonesimulator/gen1recomp++.app
|
||||
dist/ios/Release-iphonesimulator/gen1recomp++.app
|
||||
dist/ios/Debug-iphoneos/gen1recomp++.app
|
||||
dist/ios/Release-iphoneos/gen1recomp++.app
|
||||
```
|
||||
|
||||
The intermediate Xcode products are under `mobile/ios/build/`. Both locations
|
||||
@@ -94,9 +94,9 @@ saves; those are created at runtime in Documents.
|
||||
|
||||
| Field | Default |
|
||||
| --- | --- |
|
||||
| Display name | `gen1recomp` |
|
||||
| Product name | `gen1recomp` |
|
||||
| Bundle identifier | `com.theboisclub.gen1recomp` |
|
||||
| Display name | `gen1recomp++` |
|
||||
| Product name | `gen1recomp++` |
|
||||
| Bundle identifier | `com.theboisclub.gen1recompplusplus` |
|
||||
| Save directory | Public `Documents` root |
|
||||
| Orientation | Portrait |
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "gen1recomp App Repo",
|
||||
"identifier": "com.theboisclub.gen1recomp.repo",
|
||||
"name": "gen1recomp++ App Repo",
|
||||
"identifier": "com.theboisclub.gen1recompplusplus.repo",
|
||||
"iconURL": "https://raw.githubusercontent.com/bryanthaboi/gen1recomp/main/assets/logo/gen1recomp_cover.png",
|
||||
"apps": [
|
||||
{
|
||||
"name": "gen1recomp",
|
||||
"bundleIdentifier": "com.theboisclub.gen1recomp",
|
||||
"name": "gen1recomp++",
|
||||
"bundleIdentifier": "com.theboisclub.gen1recompplusplus",
|
||||
"developerName": "bryanthaboi",
|
||||
"iconURL": "https://raw.githubusercontent.com/bryanthaboi/gen1recomp/main/assets/logo/gen1recomp_cover.png",
|
||||
"localizedDescription": "Gen1Recomp - A native Lua / LÖVE2D recreation of Gen 1 Poke",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>gen1recomp</string>
|
||||
<string>gen1recomp++</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
@@ -32,7 +32,7 @@
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>gen1recomp</string>
|
||||
<string>gen1recomp++</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
|
||||
@@ -29,6 +29,9 @@ WRAP_SYSTEM = LOVE_SRC / "src" / "modules" / "system" / "wrap_System.cpp"
|
||||
PBXPROJ = LOVE_SRC / "platform" / "xcode" / "love.xcodeproj" / "project.pbxproj"
|
||||
APPLE_MM = LOVE_SRC / "src" / "common" / "apple.mm"
|
||||
FILESYSTEM_CPP = LOVE_SRC / "src" / "modules" / "filesystem" / "physfs" / "Filesystem.cpp"
|
||||
IOS_MM = LOVE_SRC / "src" / "common" / "ios.mm"
|
||||
IOS_H = LOVE_SRC / "src" / "common" / "ios.h"
|
||||
SYSTEM_CPP = LOVE_SRC / "src" / "modules" / "system" / "System.cpp"
|
||||
ENTITLEMENTS_SRC = IOS_DIR / "overlays" / "love-ios.entitlements"
|
||||
|
||||
NATIVE_FILES = ("GRPickerBridge.swift", "GRHealthBridge.swift", "GRBootstrap.m")
|
||||
@@ -120,7 +123,7 @@ int w_pickFileKinds(lua_State *L)
|
||||
typedef const char *(*GRUTF8)(id, SEL);
|
||||
const char *bytes = ((GRUTF8)objc_msgSend)(kinds,
|
||||
sel_registerName("UTF8String"));
|
||||
if (bytes == nullptr || bytes[0] == '\0')
|
||||
if (bytes == nullptr || bytes[0] == '\\0')
|
||||
{
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
@@ -358,6 +361,50 @@ def patch_public_documents():
|
||||
print("patch_love_src: iOS save directory routed to Documents root")
|
||||
|
||||
|
||||
def patch_ios_haptics():
|
||||
text = pristine(IOS_MM, ("UIImpactFeedbackGenerator",))
|
||||
original = """void vibrate()
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
|
||||
}
|
||||
}
|
||||
"""
|
||||
replacement = """void vibrate(double seconds)
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
UIImpactFeedbackStyle style = UIImpactFeedbackStyleLight;
|
||||
if (seconds >= 0.035)
|
||||
style = UIImpactFeedbackStyleHeavy;
|
||||
else if (seconds >= 0.02)
|
||||
style = UIImpactFeedbackStyleMedium;
|
||||
UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc]
|
||||
initWithStyle:style];
|
||||
[generator prepare];
|
||||
[generator impactOccurred];
|
||||
}
|
||||
}
|
||||
"""
|
||||
if original not in text:
|
||||
fail(f"iOS haptic anchor not found in {IOS_MM}")
|
||||
IOS_MM.write_text(text.replace(original, replacement, 1))
|
||||
|
||||
header = pristine(IOS_H, ("void vibrate(double seconds);",))
|
||||
header_original = "void vibrate();"
|
||||
if header_original not in header:
|
||||
fail(f"iOS haptic declaration not found in {IOS_H}")
|
||||
IOS_H.write_text(header.replace(header_original, "void vibrate(double seconds);", 1))
|
||||
|
||||
system = pristine(SYSTEM_CPP, ("love::ios::vibrate(seconds)",))
|
||||
system_original = "love::ios::vibrate();"
|
||||
if system_original not in system:
|
||||
fail(f"iOS haptic call site not found in {SYSTEM_CPP}")
|
||||
SYSTEM_CPP.write_text(system.replace(system_original, "love::ios::vibrate(seconds);", 1))
|
||||
print("patch_love_src: iOS haptics use Taptic Engine impact presets")
|
||||
|
||||
|
||||
def patch_pbxproj():
|
||||
text = pristine(PBXPROJ)
|
||||
|
||||
@@ -408,7 +455,9 @@ def patch_pbxproj():
|
||||
fail(f"build configuration {config_id} not found")
|
||||
settings = (
|
||||
"\t\t\t\tSWIFT_VERSION = 5.0;\n"
|
||||
"\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 14.0;\n"
|
||||
"\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 15.0;\n"
|
||||
"\t\t\t\tPRODUCT_NAME = \"gen1recomp++\";\n"
|
||||
"\t\t\t\tEXECUTABLE_NAME = \"gen1recomp++\";\n"
|
||||
'\t\t\t\tCODE_SIGN_ENTITLEMENTS = "ios/native/love-ios.entitlements";\n'
|
||||
)
|
||||
text = text[: m.end()] + settings + text[m.end():]
|
||||
@@ -422,6 +471,7 @@ def main():
|
||||
fail("love-src/ missing; run scripts/build_ios.sh --fetch first")
|
||||
copy_native_files()
|
||||
patch_public_documents()
|
||||
patch_ios_haptics()
|
||||
patch_wrap_system()
|
||||
patch_pbxproj()
|
||||
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@
|
||||
# dist/linux/gen1recomp-linux.zip (fused x86_64 AppImage)
|
||||
# dist/android/debug/*.apk (full gradle output stays under
|
||||
# mobile/android/app/build/outputs/apk/embedNoRecord/)
|
||||
# dist/ios/<Config>-<sdk>/gen1recomp.app (full xcodebuild output stays
|
||||
# dist/ios/<Config>-<sdk>/gen1recomp++.app (full xcodebuild output stays
|
||||
# under mobile/ios/build/Build/Products/)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
+43
-25
@@ -20,9 +20,9 @@
|
||||
# - macOS + Xcode (xcodebuild)
|
||||
# - mobile/ios/love-src/ (see --fetch / mobile/ios/README.md)
|
||||
#
|
||||
# Output: dist/ios/<Config>-<sdk>/gen1recomp.app (convenience copy)
|
||||
# dist/ios/gen1recomp.ipa (device builds only)
|
||||
# mobile/ios/build/Build/Products/<Config>-<sdk>/gen1recomp.app
|
||||
# Output: dist/ios/<Config>-<sdk>/gen1recomp++.app (convenience copy)
|
||||
# dist/ios/gen1recomp++.ipa (device builds only)
|
||||
# mobile/ios/build/Build/Products/<Config>-<sdk>/gen1recomp++.app
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
@@ -39,8 +39,9 @@ RESOURCES_DIR="$XCODE_DIR/ios/resources"
|
||||
LOVE_FILE="$RESOURCES_DIR/game.love"
|
||||
LIBS_DIR="$XCODE_DIR/ios/libraries"
|
||||
|
||||
APP_NAME="gen1recomp"
|
||||
DISPLAY_NAME="gen1recomp"
|
||||
APP_NAME="gen1recomp++"
|
||||
DISPLAY_NAME="gen1recomp++"
|
||||
PRODUCT_NAME="gen1recomp++"
|
||||
# Bundle ID resolution, most specific wins:
|
||||
# 1. GEN1_BUNDLE_ID env var
|
||||
# 2. mobile/ios/bundle_id.local (one line, gitignored — pins YOUR install
|
||||
@@ -50,7 +51,7 @@ DISPLAY_NAME="gen1recomp"
|
||||
# capabilities like HealthKit are involved), so a per-team default
|
||||
# lets anyone build without colliding with someone else's app
|
||||
# 4. simulator: the project default (no App ID registration involved)
|
||||
BUNDLE_ID="${GEN1_BUNDLE_ID:-com.theboisclub.gen1recomp}"
|
||||
BUNDLE_ID="${GEN1_BUNDLE_ID:-}"
|
||||
if [ -z "$BUNDLE_ID" ] && [ -f "$IOS_DIR/bundle_id.local" ]; then
|
||||
BUNDLE_ID="$(tr -d '[:space:]' < "$IOS_DIR/bundle_id.local")"
|
||||
fi
|
||||
@@ -138,11 +139,7 @@ if $DEVICE && [ -z "${DEVELOPMENT_TEAM:-}" ]; then
|
||||
fi
|
||||
fi
|
||||
if [ -z "$BUNDLE_ID" ]; then
|
||||
if $DEVICE; then
|
||||
BUNDLE_ID="com.gen1recomp.t$(printf '%s' "$DEVELOPMENT_TEAM" | tr '[:upper:]' '[:lower:]')"
|
||||
else
|
||||
BUNDLE_ID="com.theboisclub.pokemonred"
|
||||
fi
|
||||
BUNDLE_ID="com.theboisclub.gen1recompplusplus"
|
||||
fi
|
||||
|
||||
# --------------------------------------------------------------- host checks
|
||||
@@ -226,13 +223,26 @@ verify_documents_overlay() {
|
||||
}
|
||||
|
||||
apply_ios_icon() {
|
||||
local source="$ROOT/assets/logo/gen1recomp_cover.png"
|
||||
local source="$ROOT/assets/logo/logo.png"
|
||||
local target="$XCODE_DIR/Images.xcassets/iOS AppIcon.appiconset"
|
||||
[ -f "$source" ] || fail "missing iOS icon source: $source"
|
||||
[ -d "$target" ] || fail "missing iOS app icon set: $target"
|
||||
local icon="$BUILD_DIR/gen1recomp-ios-icon.png"
|
||||
mkdir -p "$BUILD_DIR"
|
||||
if command -v magick >/dev/null 2>&1; then
|
||||
magick -size 1024x1024 xc:black \
|
||||
\( "$source" -resize 900x900 \) -gravity center -composite \
|
||||
-alpha off "$icon" || fail "could not create iOS app icon: $source"
|
||||
else
|
||||
local scaled="$BUILD_DIR/gen1recomp-logo.png"
|
||||
sips -Z 900 "$source" --out "$scaled" >/dev/null \
|
||||
|| fail "could not resize iOS app icon source: $source"
|
||||
sips -p 1024 1024 --padColor 000000 "$scaled" --out "$icon" >/dev/null \
|
||||
|| fail "could not center iOS app icon source: $source"
|
||||
fi
|
||||
local entry name size
|
||||
while IFS=: read -r name size; do
|
||||
sips -z "$size" "$size" "$source" --out "$target/$name" >/dev/null
|
||||
sips -z "$size" "$size" "$icon" --out "$target/$name" >/dev/null
|
||||
done <<'EOF'
|
||||
icon-1024pt@1x.png:1024
|
||||
icon-29pt@1x.png:29
|
||||
@@ -647,6 +657,7 @@ run_xcodebuild() {
|
||||
CURRENT_PROJECT_VERSION="$project_version"
|
||||
INFOPLIST_KEY_UIFileSharingEnabled=YES
|
||||
INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace=YES
|
||||
IPHONEOS_DEPLOYMENT_TARGET=15.0
|
||||
ONLY_ACTIVE_ARCH=NO
|
||||
DISABLE_MANUAL_TARGET_ORDER_BUILD_WARNING=YES
|
||||
)
|
||||
@@ -666,6 +677,9 @@ run_xcodebuild() {
|
||||
if [ -n "${CODE_SIGN_IDENTITY:-}" ]; then
|
||||
args+=(CODE_SIGN_IDENTITY="$CODE_SIGN_IDENTITY")
|
||||
fi
|
||||
if [ "${GEN1_DISABLE_HEALTHKIT:-0}" = "1" ]; then
|
||||
args+=(CODE_SIGN_ENTITLEMENTS=)
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! xcodebuild -showsdks 2>/dev/null | grep -q "$sdk"; then
|
||||
@@ -708,18 +722,22 @@ run_xcodebuild() {
|
||||
fi
|
||||
|
||||
local products="$BUILD_DIR/Build/Products/${config}-${sdk}"
|
||||
local app="$products/$APP_NAME.app"
|
||||
if [ ! -d "$app" ]; then
|
||||
# PRODUCT_NAME override can still leave love.app on older projects
|
||||
if [ -d "$products/love.app" ]; then
|
||||
app="$products/$APP_NAME.app"
|
||||
mv "$products/love.app" "$app"
|
||||
warn "renamed love.app to $APP_NAME.app"
|
||||
else
|
||||
warn "xcodebuild finished but no .app under $products"
|
||||
find "$BUILD_DIR/Build/Products" -name '*.app' 2>/dev/null | head -20 || true
|
||||
return 0
|
||||
local app=""
|
||||
local candidate
|
||||
for candidate in "$products/$PRODUCT_NAME.app" "$products/$APP_NAME.app" "$products/love.app"; do
|
||||
if [ -d "$candidate" ]; then
|
||||
app="$candidate"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -z "$app" ]; then
|
||||
warn "xcodebuild finished but no .app under $products"
|
||||
find "$BUILD_DIR/Build/Products" -name '*.app' 2>/dev/null | head -20 || true
|
||||
return 0
|
||||
fi
|
||||
if [ "$app" != "$products/$APP_NAME.app" ]; then
|
||||
mv "$app" "$products/$APP_NAME.app"
|
||||
app="$products/$APP_NAME.app"
|
||||
fi
|
||||
|
||||
verify_documents_configuration "$app"
|
||||
@@ -760,7 +778,7 @@ run_xcodebuild() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Pack Payload/<app>.app into dist/ios/gen1recomp.ipa for release / sideload tools.
|
||||
# Pack Payload/<app>.app into dist/ios/gen1recomp++.ipa for release / sideload tools.
|
||||
package_ipa() {
|
||||
local app="$1"
|
||||
local ipa="$DIST/$APP_NAME.ipa"
|
||||
|
||||
@@ -335,11 +335,11 @@ function SaveData.defaultOptions()
|
||||
-- TouchControls.normalizeConfig folds it into both orientations on load.
|
||||
touchControls = { enabled = true },
|
||||
-- Haptic feedback level for on-screen pad presses (#806):
|
||||
-- off | light | medium | heavy, mapped to a love.system.vibrate
|
||||
-- duration in src/core/TouchControls.lua. LIGHT by default, like the
|
||||
-- overlay itself defaulting on, so an options.lua predating this key
|
||||
-- gets the tick without going looking for the row. Inert wherever the
|
||||
-- overlay never appears (desktop) or LOVE has no vibrator.
|
||||
-- off | light | normal | strong, mapped to a love.system.vibrate duration
|
||||
-- in src/core/TouchControls.lua. LIGHT by default, so an options.lua
|
||||
-- predating this key gets the tick without going looking for the row.
|
||||
-- Inert wherever the overlay never appears (desktop) or LOVE has no
|
||||
-- vibrator.
|
||||
haptics = "light",
|
||||
-- Shared UI/mod timestamp presentation. DEVICE follows the process time
|
||||
-- locale where the platform exposes one; otherwise DateTime falls back to
|
||||
|
||||
@@ -105,17 +105,21 @@ end
|
||||
-- would be dropped on every editor save.
|
||||
-- love.system.vibrate takes a duration and nothing else, so "intensity" is a
|
||||
-- duration preset: Android runs the platform vibrator for exactly that long,
|
||||
-- while iOS ignores the duration and fires the fixed system vibration, so
|
||||
-- there the three levels all read as simply on.
|
||||
TouchControls.HAPTICS = { "off", "light", "medium", "heavy" }
|
||||
-- while iOS maps each duration to a matching Taptic Engine impact.
|
||||
TouchControls.HAPTICS = { "off", "light", "normal", "strong" }
|
||||
TouchControls.HAPTIC_DEFAULT = "light"
|
||||
|
||||
local HAPTIC_SECONDS = { off = 0, light = 0.012, medium = 0.025, heavy = 0.045 }
|
||||
local HAPTIC_SECONDS = {
|
||||
off = 0, light = 0.012, normal = 0.025, strong = 0.045,
|
||||
}
|
||||
local HAPTIC_LABELS = {
|
||||
off = "OFF", light = "LIGHT", medium = "MEDIUM", heavy = "HEAVY",
|
||||
off = "OFF", light = "LIGHT", normal = "NORMAL", strong = "STRONG",
|
||||
}
|
||||
|
||||
function TouchControls.normalizeHaptics(level)
|
||||
if level == "physical" then return "light" end
|
||||
if level == "medium" then return "normal" end
|
||||
if level == "heavy" then return "strong" end
|
||||
if HAPTIC_SECONDS[level] then return level end
|
||||
return TouchControls.HAPTIC_DEFAULT
|
||||
end
|
||||
|
||||
@@ -501,7 +501,7 @@ local function buildRows(game)
|
||||
return true
|
||||
end },
|
||||
-- Haptic feedback for on-screen pad presses (#806): OFF / LIGHT /
|
||||
-- MEDIUM / HEAVY, where the intensity is a vibration duration --
|
||||
-- NORMAL / STRONG, where the intensity is a vibration duration --
|
||||
-- love.system.vibrate takes nothing else. Hidden with TOUCH PAD below,
|
||||
-- since the only thing that buzzes is a virtual button press.
|
||||
{ id = "haptics", label = Strings("VIBRATION"),
|
||||
@@ -515,7 +515,7 @@ local function buildRows(game)
|
||||
o.haptics = TC.cycleHaptics(o.haptics, dir)
|
||||
TC:applyOptions(o)
|
||||
-- sample the level being selected: stepping the row is the only way
|
||||
-- to compare LIGHT against HEAVY without leaving the menu
|
||||
-- to compare LIGHT against STRONG without leaving the menu
|
||||
TC.buzz(o.haptics)
|
||||
return true
|
||||
end },
|
||||
|
||||
Reference in New Issue
Block a user