From b6d48a1f7beb03bac33763c85d738f6325f59265 Mon Sep 17 00:00:00 2001 From: mjtalbot Date: Wed, 24 May 2023 11:15:51 +0000 Subject: [PATCH] Macos take2 draft because i need to get a todo list together. Adds macos as a target for our ios runtime! Also adds a macos target for our example (which is a different app completely, very minimalistic right now). CleanShot 2023-05-17 at 20 32 45@2x macos, macos rosetta, macos (designed for ipad), and ios all co existing in peace, from the same runtime project ![CleanShot 2023-05-17 at 18 32 04@2x](https://github.com/rive-app/rive/assets/1216025/eead319d-a16b-4098-a7db-d5f033b1ef8f) todo: - [x] update build scripts to build supporting macos (gotta do this) - [x] run formatter - [x] test out builds in forked version of ios? (gotta do this) - [ ] one more stab at catalyst? (i think we can try that later...) - [ ] do we need a more comprehensive example setup for macos (I think we can do this later & try to pull zach's examples in) - [ ] I think we should restructure the ios project, but i think we can do that after this as well (i just think the folder structure/project structure can do with some work, now that we add macos (and should make room for tvos as well) - [x] probably got tests to fix - [ ] there's probably a bunch of looking at errors in the debugger and figuring those out, but i would hope that we can deploy with some warnings here too. catalyst problem: we get this error: and the problem is basically that we can target a specific library for macos, but we need one for macos and one for macos catalyst. they share the same architecture, so i dont think we can lipo them into one file... we could change the compiled binaries before creating the frameworks I guess though? .. maybe something to try.. `/Users/maxwelltalbot/development/rive/rive/packages/runtime_ios/dependencies/debug/librive_skia_renderer_macos.a(cg_factory.o), building for Mac Catalyst, but linking in object file built for macOS, file '/Users/maxwelltalbot/development/rive/rive/packages/runtime_ios/dependencies/debug/librive_skia_renderer_macos.a' for architecture arm64` basically Diffs= a9f8a1c5d Macos take2 (#5258) --- .github/workflows/Package.swift.template | 2 +- .../workflows/RiveRuntime.podspec.template | 3 +- .github/workflows/release.yml | 16 +- .rive_head | 2 +- .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 58 ++++ .../Assets.xcassets/Contents.json | 6 + Example-iOS/Example (macOS)/ContentView.swift | 25 ++ .../Example__macOS_.entitlements | 10 + .../Example (macOS)/Example__macOS_App.swift | 18 ++ .../Preview Assets.xcassets/Contents.json | 6 + .../RiveExample.xcodeproj/project.pbxproj | 268 +++++++++++++++- ...xample.xcscheme => Example (iOS).xcscheme} | 12 +- .../xcschemes/Example (macOS).xcscheme | 78 +++++ RiveRuntime.xcodeproj/project.pbxproj | 52 +++- Source/Renderer/rive_renderer_view.mm | 7 + Source/RiveView.swift | 294 +++++++++++++----- Source/RiveViewModel.swift | 97 ++++-- Source/Utils/FPSCounterView.swift | 47 +++ scripts/build.rive.sh | 44 ++- scripts/build.sh | 2 + scripts/build.skia.macos.sh | 47 +++ scripts/build.skia.sh | 2 +- scripts/build_framework.sh | 41 ++- scripts/merge_frameworks.sh | 30 -- submodules/rive-cpp | 2 +- 26 files changed, 987 insertions(+), 193 deletions(-) create mode 100644 Example-iOS/Example (macOS)/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 Example-iOS/Example (macOS)/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 Example-iOS/Example (macOS)/Assets.xcassets/Contents.json create mode 100644 Example-iOS/Example (macOS)/ContentView.swift create mode 100644 Example-iOS/Example (macOS)/Example__macOS_.entitlements create mode 100644 Example-iOS/Example (macOS)/Example__macOS_App.swift create mode 100644 Example-iOS/Example (macOS)/Preview Content/Preview Assets.xcassets/Contents.json rename Example-iOS/RiveExample.xcodeproj/xcshareddata/xcschemes/{RiveExample.xcscheme => Example (iOS).xcscheme} (90%) create mode 100644 Example-iOS/RiveExample.xcodeproj/xcshareddata/xcschemes/Example (macOS).xcscheme create mode 100755 scripts/build.skia.macos.sh delete mode 100755 scripts/merge_frameworks.sh diff --git a/.github/workflows/Package.swift.template b/.github/workflows/Package.swift.template index 001ff4a2..73de1ca4 100644 --- a/.github/workflows/Package.swift.template +++ b/.github/workflows/Package.swift.template @@ -3,7 +3,7 @@ import PackageDescription let package = Package( name: "RiveRuntime", - platforms: [.iOS("14.0")], + platforms: [.iOS("14.0"), .macOS("13.1")], products: [ .library( name: "RiveRuntime", diff --git a/.github/workflows/RiveRuntime.podspec.template b/.github/workflows/RiveRuntime.podspec.template index c9ca0bcc..b0e110d6 100644 --- a/.github/workflows/RiveRuntime.podspec.template +++ b/.github/workflows/RiveRuntime.podspec.template @@ -27,11 +27,12 @@ Pod::Spec.new do |spec| LICENSE } spec.authors = { "Luigi Rosso" => "luigi@rive.app" } - spec.platform = :ios, '14.0' spec.ios.deployment_target = '14.0' + spec.osx.deployment_target = '13.1' spec.swift_version = '5.0' spec.source = { :http => "https://github.com/rive-app/rive-ios/releases/download/$RELEASE_VERSION/RiveRuntime.xcframework.zip", } spec.ios.vendored_frameworks = 'RiveRuntime.xcframework' + spec.osx.vendored_frameworks = 'RiveRuntime.xcframework' end \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dd55f80c..f44a6a70 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -112,19 +112,13 @@ jobs: RiveRuntime.xcodeproj/project.pbxproj Source/Info.plist Tests/Info.plist - - id: build_iphoneos - name: Build release iphoneos framework - run: sh ./scripts/build_framework.sh -t iphoneos -c Release - - id: build_iphonesimulator - name: Build release iphonesimulator framework - run: sh ./scripts/build_framework.sh -t iphonesimulator -c Release - - id: merge_frameworks - if: steps.build_iphoneos.conclusion == 'success' && steps.build_iphonesimulator.conclusion == 'success' - name: Merge created frameworks - run: sh ./scripts/merge_frameworks.sh -c Release + - id: build_frameworks + name: Build frameworks + run: sh ./scripts/build_framework.sh -c Release - id: zip name: Zip the framework - run: zip -r RiveRuntime.xcframework.zip RiveRuntime.xcframework + # --symlinks is critical here to retain the structure of a macos framework. + run: zip --symlinks -r RiveRuntime.xcframework.zip RiveRuntime.xcframework working-directory: ./archive - id: get_checksum name: Add the checksum of the zip file into our environment diff --git a/.rive_head b/.rive_head index 592c7e03..eaeb7d14 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -f2ecb824beea0dadfe7077accacb5cd246cac669 +a9f8a1c5d351a72b4537a6b8a27962d130f0a97c diff --git a/Example-iOS/Example (macOS)/Assets.xcassets/AccentColor.colorset/Contents.json b/Example-iOS/Example (macOS)/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 00000000..eb878970 --- /dev/null +++ b/Example-iOS/Example (macOS)/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Example-iOS/Example (macOS)/Assets.xcassets/AppIcon.appiconset/Contents.json b/Example-iOS/Example (macOS)/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..3f00db43 --- /dev/null +++ b/Example-iOS/Example (macOS)/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "scale" : "1x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "16x16" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "32x32" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "128x128" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "256x256" + }, + { + "idiom" : "mac", + "scale" : "1x", + "size" : "512x512" + }, + { + "idiom" : "mac", + "scale" : "2x", + "size" : "512x512" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Example-iOS/Example (macOS)/Assets.xcassets/Contents.json b/Example-iOS/Example (macOS)/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Example-iOS/Example (macOS)/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Example-iOS/Example (macOS)/ContentView.swift b/Example-iOS/Example (macOS)/ContentView.swift new file mode 100644 index 00000000..35bb86a3 --- /dev/null +++ b/Example-iOS/Example (macOS)/ContentView.swift @@ -0,0 +1,25 @@ +// +// ContentView.swift +// Example (macOS) +// +// Created by Maxwell Talbot on 17/05/2023. +// Copyright © 2023 Rive. All rights reserved. +// + +import SwiftUI +import RiveRuntime + +struct ContentView: View { + var body: some View { + VStack { + RiveViewModel(fileName: "magic_8-ball_v2").view() + } + .padding() + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } +} diff --git a/Example-iOS/Example (macOS)/Example__macOS_.entitlements b/Example-iOS/Example (macOS)/Example__macOS_.entitlements new file mode 100644 index 00000000..f2ef3ae0 --- /dev/null +++ b/Example-iOS/Example (macOS)/Example__macOS_.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.files.user-selected.read-only + + + diff --git a/Example-iOS/Example (macOS)/Example__macOS_App.swift b/Example-iOS/Example (macOS)/Example__macOS_App.swift new file mode 100644 index 00000000..43ca20e5 --- /dev/null +++ b/Example-iOS/Example (macOS)/Example__macOS_App.swift @@ -0,0 +1,18 @@ +// +// Example__macOS_App.swift +// Example (macOS) +// +// Created by Maxwell Talbot on 17/05/2023. +// Copyright © 2023 Rive. All rights reserved. +// + +import SwiftUI + +@main +struct Example__macOS_App: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/Example-iOS/Example (macOS)/Preview Content/Preview Assets.xcassets/Contents.json b/Example-iOS/Example (macOS)/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/Example-iOS/Example (macOS)/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Example-iOS/RiveExample.xcodeproj/project.pbxproj b/Example-iOS/RiveExample.xcodeproj/project.pbxproj index 61c578fe..3db4a671 100644 --- a/Example-iOS/RiveExample.xcodeproj/project.pbxproj +++ b/Example-iOS/RiveExample.xcodeproj/project.pbxproj @@ -43,6 +43,56 @@ 04D5B06C266A460C004ACA5B /* nothing.riv in Resources */ = {isa = PBXBuildFile; fileRef = 04D5B069266A460C004ACA5B /* nothing.riv */; }; 04DB5937266A348C0020A7E8 /* RiveRuntime.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04A8F6BD26452E10002C909A /* RiveRuntime.framework */; }; 04DB5938266A348C0020A7E8 /* RiveRuntime.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 04A8F6BD26452E10002C909A /* RiveRuntime.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 04E51C362A151A1E0075E473 /* Example__macOS_App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04E51C352A151A1E0075E473 /* Example__macOS_App.swift */; }; + 04E51C382A151A1E0075E473 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04E51C372A151A1E0075E473 /* ContentView.swift */; }; + 04E51C3A2A151A1F0075E473 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 04E51C392A151A1F0075E473 /* Assets.xcassets */; }; + 04E51C3D2A151A1F0075E473 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 04E51C3C2A151A1F0075E473 /* Preview Assets.xcassets */; }; + 04E51C422A151B3C0075E473 /* RiveRuntime.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 04A8F6BD26452E10002C909A /* RiveRuntime.framework */; }; + 04E51C432A151B3C0075E473 /* RiveRuntime.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 04A8F6BD26452E10002C909A /* RiveRuntime.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 04E51C452A151C230075E473 /* halloween.riv in Resources */ = {isa = PBXBuildFile; fileRef = C3C074F1284161E400E8EB33 /* halloween.riv */; }; + 04E51C462A151C230075E473 /* testanimation.riv in Resources */ = {isa = PBXBuildFile; fileRef = C3C074A7283FC75800E8EB33 /* testanimation.riv */; }; + 04E51C472A151C230075E473 /* teststatemachine.riv in Resources */ = {isa = PBXBuildFile; fileRef = C3C074AA283FC75900E8EB33 /* teststatemachine.riv */; }; + 04E51C482A151C230075E473 /* bullet_man_game.riv in Resources */ = {isa = PBXBuildFile; fileRef = C3E2B5872833ECB500A8651B /* bullet_man_game.riv */; }; + 04E51C492A151C230075E473 /* hero_editor.riv in Resources */ = {isa = PBXBuildFile; fileRef = C3745FCB282AE2320087F4AF /* hero_editor.riv */; }; + 04E51C4A2A151C230075E473 /* watch_v1.riv in Resources */ = {isa = PBXBuildFile; fileRef = C3E383472837E6B00029D65E /* watch_v1.riv */; }; + 04E51C4B2A151C230075E473 /* leg_day_events_example.riv in Resources */ = {isa = PBXBuildFile; fileRef = C3ECAC29281837B300A81123 /* leg_day_events_example.riv */; }; + 04E51C4C2A151C230075E473 /* play_button_event_example.riv in Resources */ = {isa = PBXBuildFile; fileRef = C3ECAC28281837B300A81123 /* play_button_event_example.riv */; }; + 04E51C4D2A151C230075E473 /* switch_event_example.riv in Resources */ = {isa = PBXBuildFile; fileRef = C3ECAC2A281837B300A81123 /* switch_event_example.riv */; }; + 04E51C4E2A151C230075E473 /* magic_8-ball_v2.riv in Resources */ = {isa = PBXBuildFile; fileRef = C3ECAC222817BE1100A81123 /* magic_8-ball_v2.riv */; }; + 04E51C4F2A151C230075E473 /* light_switch.riv in Resources */ = {isa = PBXBuildFile; fileRef = 27108F2C282C96E700A99D81 /* light_switch.riv */; }; + 04E51C502A151C230075E473 /* riveslider.riv in Resources */ = {isa = PBXBuildFile; fileRef = C3D187F628075B6C008B739A /* riveslider.riv */; }; + 04E51C512A151C230075E473 /* rbutton.riv in Resources */ = {isa = PBXBuildFile; fileRef = C324DB5E280740FB0060589F /* rbutton.riv */; }; + 04E51C522A151C230075E473 /* constrained.riv in Resources */ = {isa = PBXBuildFile; fileRef = 0450445E26B3F71E007B25CA /* constrained.riv */; }; + 04E51C532A151C230075E473 /* nothing.riv in Resources */ = {isa = PBXBuildFile; fileRef = 04D5B069266A460C004ACA5B /* nothing.riv */; }; + 04E51C542A151C230075E473 /* artboard_animations.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88D42644447500E7DBB2 /* artboard_animations.riv */; }; + 04E51C552A151C230075E473 /* basketball.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88CF2644447500E7DBB2 /* basketball.riv */; }; + 04E51C562A151C230075E473 /* clean_icon_set.riv in Resources */ = {isa = PBXBuildFile; fileRef = 048002882729AA4400F7132B /* clean_icon_set.riv */; }; + 04E51C572A151C230075E473 /* clipping.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88D92644447500E7DBB2 /* clipping.riv */; }; + 04E51C582A151C230075E473 /* explorer.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88D32644447500E7DBB2 /* explorer.riv */; }; + 04E51C592A151C230075E473 /* f22.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88D02644447500E7DBB2 /* f22.riv */; }; + 04E51C5A2A151C230075E473 /* flux_capacitor.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88D12644447500E7DBB2 /* flux_capacitor.riv */; }; + 04E51C5B2A151C230075E473 /* juice_v7.riv in Resources */ = {isa = PBXBuildFile; fileRef = C9CE8265263B90E000F98DDB /* juice_v7.riv */; }; + 04E51C5C2A151C230075E473 /* life_bar.riv in Resources */ = {isa = PBXBuildFile; fileRef = C9D3DE67264F49F4001BA265 /* life_bar.riv */; }; + 04E51C5D2A151C230075E473 /* prop_example.riv in Resources */ = {isa = PBXBuildFile; fileRef = E5A7874B27E1158E0056F24B /* prop_example.riv */; }; + 04E51C5E2A151C230075E473 /* two_bone_ik.riv in Resources */ = {isa = PBXBuildFile; fileRef = 04F1C80826A8442300CEE6BE /* two_bone_ik.riv */; }; + 04E51C5F2A151C230075E473 /* energy_bar_example.riv in Resources */ = {isa = PBXBuildFile; fileRef = E5A7874727E115170056F24B /* energy_bar_example.riv */; }; + 04E51C602A151C230075E473 /* liquid.riv in Resources */ = {isa = PBXBuildFile; fileRef = C9D3DE5A264F3B51001BA265 /* liquid.riv */; }; + 04E51C612A151C230075E473 /* loopy.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88D62644447500E7DBB2 /* loopy.riv */; }; + 04E51C622A151C230075E473 /* mascot.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88CD2644447400E7DBB2 /* mascot.riv */; }; + 04E51C632A151C230075E473 /* neostream.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88D22644447500E7DBB2 /* neostream.riv */; }; + 04E51C642A151C230075E473 /* off_road_car_blog.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88D72644447500E7DBB2 /* off_road_car_blog.riv */; }; + 04E51C652A151C230075E473 /* progress.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88CE2644447500E7DBB2 /* progress.riv */; }; + 04E51C662A151C230075E473 /* pull.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88CA2644447400E7DBB2 /* pull.riv */; }; + 04E51C672A151C230075E473 /* rope.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88CC2644447400E7DBB2 /* rope.riv */; }; + 04E51C682A151C230075E473 /* skills.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88D82644447500E7DBB2 /* skills.riv */; }; + 04E51C692A151C230075E473 /* switch.riv in Resources */ = {isa = PBXBuildFile; fileRef = C9E040A8264DFCFD009ABC7C /* switch.riv */; }; + 04E51C6A2A151C230075E473 /* trailblaze.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88D52644447500E7DBB2 /* trailblaze.riv */; }; + 04E51C6B2A151C230075E473 /* ui_swipe_left_to_delete.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88CB2644447400E7DBB2 /* ui_swipe_left_to_delete.riv */; }; + 04E51C6C2A151C230075E473 /* vader.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88DA2644447500E7DBB2 /* vader.riv */; }; + 04E51C6D2A151C230075E473 /* wacky.riv in Resources */ = {isa = PBXBuildFile; fileRef = 042C88C92644447400E7DBB2 /* wacky.riv */; }; + 04E51C6E2A151C230075E473 /* truck.riv in Resources */ = {isa = PBXBuildFile; fileRef = C3D187F8280770EA008B739A /* truck.riv */; }; + 04E51C6F2A151C230075E473 /* truck_v7.riv in Resources */ = {isa = PBXBuildFile; fileRef = C9BD3925263B5FC700696C37 /* truck_v7.riv */; }; + 04E51C702A151C230075E473 /* blendmodes.riv in Resources */ = {isa = PBXBuildFile; fileRef = 046AFA6E2673AF04004ED497 /* blendmodes.riv */; }; 04F1C80B26A8442300CEE6BE /* two_bone_ik.riv in Resources */ = {isa = PBXBuildFile; fileRef = 04F1C80826A8442300CEE6BE /* two_bone_ik.riv */; }; 27108F2F282C96E700A99D81 /* light_switch.riv in Resources */ = {isa = PBXBuildFile; fileRef = 27108F2C282C96E700A99D81 /* light_switch.riv */; }; C324DB5628071EB80060589F /* RiveSwitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = C324DB5528071EB80060589F /* RiveSwitch.swift */; }; @@ -101,6 +151,17 @@ /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 04E51C442A151B3C0075E473 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 04E51C432A151B3C0075E473 /* RiveRuntime.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; C9C7420224FC53CF00EF9516 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -150,6 +211,12 @@ 04A8F6AB26452A91002C909A /* RiveRuntime.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RiveRuntime.xcodeproj; path = ../RiveRuntime.xcodeproj; sourceTree = ""; }; 04C4C83D2646FE410047E614 /* StateMachine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateMachine.swift; sourceTree = ""; }; 04D5B069266A460C004ACA5B /* nothing.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = nothing.riv; sourceTree = ""; }; + 04E51C332A151A1E0075E473 /* Example (macOS).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example (macOS).app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 04E51C352A151A1E0075E473 /* Example__macOS_App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Example__macOS_App.swift; sourceTree = ""; }; + 04E51C372A151A1E0075E473 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 04E51C392A151A1F0075E473 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 04E51C3C2A151A1F0075E473 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 04E51C3E2A151A1F0075E473 /* Example__macOS_.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Example__macOS_.entitlements; sourceTree = ""; }; 04F1C80826A8442300CEE6BE /* two_bone_ik.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = two_bone_ik.riv; sourceTree = ""; }; 27108F2C282C96E700A99D81 /* light_switch.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = light_switch.riv; sourceTree = ""; }; C324DB5528071EB80060589F /* RiveSwitch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RiveSwitch.swift; sourceTree = ""; }; @@ -176,7 +243,7 @@ C3ECAC2A281837B300A81123 /* switch_event_example.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = switch_event_example.riv; sourceTree = ""; }; C3ECAC2E281840A300A81123 /* ClockViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClockViewModel.swift; sourceTree = ""; }; C9BD3925263B5FC700696C37 /* truck_v7.riv */ = {isa = PBXFileReference; lastKnownFileType = file; path = truck_v7.riv; sourceTree = ""; }; - C9C73E9424FC471E00EF9516 /* RiveExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RiveExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + C9C73E9424FC471E00EF9516 /* Example (iOS).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example (iOS).app"; sourceTree = BUILT_PRODUCTS_DIR; }; C9C73E9724FC471E00EF9516 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; C9C73E9924FC471E00EF9516 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; C9C73E9D24FC471E00EF9516 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -201,6 +268,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 04E51C302A151A1E0075E473 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 04E51C422A151B3C0075E473 /* RiveRuntime.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -235,6 +310,26 @@ path = lib; sourceTree = ""; }; + 04E51C342A151A1E0075E473 /* Example (macOS) */ = { + isa = PBXGroup; + children = ( + 04E51C352A151A1E0075E473 /* Example__macOS_App.swift */, + 04E51C372A151A1E0075E473 /* ContentView.swift */, + 04E51C392A151A1F0075E473 /* Assets.xcassets */, + 04E51C3E2A151A1F0075E473 /* Example__macOS_.entitlements */, + 04E51C3B2A151A1F0075E473 /* Preview Content */, + ); + path = "Example (macOS)"; + sourceTree = ""; + }; + 04E51C3B2A151A1F0075E473 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 04E51C3C2A151A1F0075E473 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; C3ECAC322818608B00A81123 /* Examples */ = { isa = PBXGroup; children = ( @@ -329,6 +424,7 @@ children = ( C9696B0E24FC6FD10041502A /* Assets */, C9C73E9624FC471E00EF9516 /* Source */, + 04E51C342A151A1E0075E473 /* Example (macOS) */, C9C73E9524FC471E00EF9516 /* Products */, C9C741FF24FC53CF00EF9516 /* Frameworks */, ); @@ -337,7 +433,8 @@ C9C73E9524FC471E00EF9516 /* Products */ = { isa = PBXGroup; children = ( - C9C73E9424FC471E00EF9516 /* RiveExample.app */, + C9C73E9424FC471E00EF9516 /* Example (iOS).app */, + 04E51C332A151A1E0075E473 /* Example (macOS).app */, ); name = Products; sourceTree = ""; @@ -377,9 +474,27 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - C9C73E9324FC471E00EF9516 /* RiveExample */ = { + 04E51C322A151A1E0075E473 /* Example (macOS) */ = { + isa = PBXNativeTarget; + buildConfigurationList = 04E51C3F2A151A1F0075E473 /* Build configuration list for PBXNativeTarget "Example (macOS)" */; + buildPhases = ( + 04E51C2F2A151A1E0075E473 /* Sources */, + 04E51C302A151A1E0075E473 /* Frameworks */, + 04E51C312A151A1E0075E473 /* Resources */, + 04E51C442A151B3C0075E473 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "Example (macOS)"; + productName = "Example (macOS)"; + productReference = 04E51C332A151A1E0075E473 /* Example (macOS).app */; + productType = "com.apple.product-type.application"; + }; + C9C73E9324FC471E00EF9516 /* Example (iOS) */ = { isa = PBXNativeTarget; - buildConfigurationList = C9C73EBE24FC471E00EF9516 /* Build configuration list for PBXNativeTarget "RiveExample" */; + buildConfigurationList = C9C73EBE24FC471E00EF9516 /* Build configuration list for PBXNativeTarget "Example (iOS)" */; buildPhases = ( 04A8F6C026452E27002C909A /* Frameworks */, C9C73E9024FC471E00EF9516 /* Sources */, @@ -390,9 +505,9 @@ ); dependencies = ( ); - name = RiveExample; + name = "Example (iOS)"; productName = RiveExample; - productReference = C9C73E9424FC471E00EF9516 /* RiveExample.app */; + productReference = C9C73E9424FC471E00EF9516 /* Example (iOS).app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -401,10 +516,13 @@ C9C73E8C24FC471E00EF9516 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1160; + LastSwiftUpdateCheck = 1420; LastUpgradeCheck = 1310; ORGANIZATIONNAME = Rive; TargetAttributes = { + 04E51C322A151A1E0075E473 = { + CreatedOnToolsVersion = 14.2; + }; C9C73E9324FC471E00EF9516 = { CreatedOnToolsVersion = 11.6; }; @@ -429,7 +547,8 @@ ); projectRoot = ""; targets = ( - C9C73E9324FC471E00EF9516 /* RiveExample */, + C9C73E9324FC471E00EF9516 /* Example (iOS) */, + 04E51C322A151A1E0075E473 /* Example (macOS) */, ); }; /* End PBXProject section */ @@ -452,6 +571,59 @@ /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ + 04E51C312A151A1E0075E473 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 04E51C452A151C230075E473 /* halloween.riv in Resources */, + 04E51C462A151C230075E473 /* testanimation.riv in Resources */, + 04E51C472A151C230075E473 /* teststatemachine.riv in Resources */, + 04E51C482A151C230075E473 /* bullet_man_game.riv in Resources */, + 04E51C492A151C230075E473 /* hero_editor.riv in Resources */, + 04E51C4A2A151C230075E473 /* watch_v1.riv in Resources */, + 04E51C4B2A151C230075E473 /* leg_day_events_example.riv in Resources */, + 04E51C4C2A151C230075E473 /* play_button_event_example.riv in Resources */, + 04E51C4D2A151C230075E473 /* switch_event_example.riv in Resources */, + 04E51C4E2A151C230075E473 /* magic_8-ball_v2.riv in Resources */, + 04E51C4F2A151C230075E473 /* light_switch.riv in Resources */, + 04E51C502A151C230075E473 /* riveslider.riv in Resources */, + 04E51C512A151C230075E473 /* rbutton.riv in Resources */, + 04E51C522A151C230075E473 /* constrained.riv in Resources */, + 04E51C532A151C230075E473 /* nothing.riv in Resources */, + 04E51C542A151C230075E473 /* artboard_animations.riv in Resources */, + 04E51C552A151C230075E473 /* basketball.riv in Resources */, + 04E51C562A151C230075E473 /* clean_icon_set.riv in Resources */, + 04E51C572A151C230075E473 /* clipping.riv in Resources */, + 04E51C582A151C230075E473 /* explorer.riv in Resources */, + 04E51C592A151C230075E473 /* f22.riv in Resources */, + 04E51C5A2A151C230075E473 /* flux_capacitor.riv in Resources */, + 04E51C5B2A151C230075E473 /* juice_v7.riv in Resources */, + 04E51C5C2A151C230075E473 /* life_bar.riv in Resources */, + 04E51C5D2A151C230075E473 /* prop_example.riv in Resources */, + 04E51C5E2A151C230075E473 /* two_bone_ik.riv in Resources */, + 04E51C5F2A151C230075E473 /* energy_bar_example.riv in Resources */, + 04E51C602A151C230075E473 /* liquid.riv in Resources */, + 04E51C612A151C230075E473 /* loopy.riv in Resources */, + 04E51C622A151C230075E473 /* mascot.riv in Resources */, + 04E51C632A151C230075E473 /* neostream.riv in Resources */, + 04E51C642A151C230075E473 /* off_road_car_blog.riv in Resources */, + 04E51C652A151C230075E473 /* progress.riv in Resources */, + 04E51C662A151C230075E473 /* pull.riv in Resources */, + 04E51C672A151C230075E473 /* rope.riv in Resources */, + 04E51C682A151C230075E473 /* skills.riv in Resources */, + 04E51C692A151C230075E473 /* switch.riv in Resources */, + 04E51C6A2A151C230075E473 /* trailblaze.riv in Resources */, + 04E51C6B2A151C230075E473 /* ui_swipe_left_to_delete.riv in Resources */, + 04E51C6C2A151C230075E473 /* vader.riv in Resources */, + 04E51C6D2A151C230075E473 /* wacky.riv in Resources */, + 04E51C6E2A151C230075E473 /* truck.riv in Resources */, + 04E51C6F2A151C230075E473 /* truck_v7.riv in Resources */, + 04E51C702A151C230075E473 /* blendmodes.riv in Resources */, + 04E51C3D2A151A1F0075E473 /* Preview Assets.xcassets in Resources */, + 04E51C3A2A151A1F0075E473 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; C9C73E9224FC471E00EF9516 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -509,6 +681,15 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 04E51C2F2A151A1E0075E473 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 04E51C382A151A1E0075E473 /* ContentView.swift in Sources */, + 04E51C362A151A1E0075E473 /* Example__macOS_App.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; C9C73E9024FC471E00EF9516 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -544,6 +725,66 @@ /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ + 04E51C402A151A1F0075E473 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_ENTITLEMENTS = "Example (macOS)/Example__macOS_.entitlements"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Example (macOS)/Preview Content\""; + DEVELOPMENT_TEAM = NJ3JMFUNS9; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 Rive. All rights reserved."; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.1; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "rive.app.Example--macOS-"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 04E51C412A151A1F0075E473 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CODE_SIGN_ENTITLEMENTS = "Example (macOS)/Example__macOS_.entitlements"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"Example (macOS)/Preview Content\""; + DEVELOPMENT_TEAM = NJ3JMFUNS9; + ENABLE_HARDENED_RUNTIME = YES; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 Rive. All rights reserved."; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 13.1; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "rive.app.Example--macOS-"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = macosx; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; C9C73EBC24FC471E00EF9516 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -705,6 +946,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 04E51C3F2A151A1F0075E473 /* Build configuration list for PBXNativeTarget "Example (macOS)" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 04E51C402A151A1F0075E473 /* Debug */, + 04E51C412A151A1F0075E473 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; C9C73E8F24FC471E00EF9516 /* Build configuration list for PBXProject "RiveExample" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -714,7 +964,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - C9C73EBE24FC471E00EF9516 /* Build configuration list for PBXNativeTarget "RiveExample" */ = { + C9C73EBE24FC471E00EF9516 /* Build configuration list for PBXNativeTarget "Example (iOS)" */ = { isa = XCConfigurationList; buildConfigurations = ( C9C73EBF24FC471E00EF9516 /* Debug */, diff --git a/Example-iOS/RiveExample.xcodeproj/xcshareddata/xcschemes/RiveExample.xcscheme b/Example-iOS/RiveExample.xcodeproj/xcshareddata/xcschemes/Example (iOS).xcscheme similarity index 90% rename from Example-iOS/RiveExample.xcodeproj/xcshareddata/xcschemes/RiveExample.xcscheme rename to Example-iOS/RiveExample.xcodeproj/xcshareddata/xcschemes/Example (iOS).xcscheme index e61eb83a..f98d8d15 100644 --- a/Example-iOS/RiveExample.xcodeproj/xcshareddata/xcschemes/RiveExample.xcscheme +++ b/Example-iOS/RiveExample.xcodeproj/xcshareddata/xcschemes/Example (iOS).xcscheme @@ -15,8 +15,8 @@ @@ -45,8 +45,8 @@ @@ -62,8 +62,8 @@ diff --git a/Example-iOS/RiveExample.xcodeproj/xcshareddata/xcschemes/Example (macOS).xcscheme b/Example-iOS/RiveExample.xcodeproj/xcshareddata/xcschemes/Example (macOS).xcscheme new file mode 100644 index 00000000..38f54c78 --- /dev/null +++ b/Example-iOS/RiveExample.xcodeproj/xcshareddata/xcschemes/Example (macOS).xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/RiveRuntime.xcodeproj/project.pbxproj b/RiveRuntime.xcodeproj/project.pbxproj index 5f20d9fb..00ed23b1 100644 --- a/RiveRuntime.xcodeproj/project.pbxproj +++ b/RiveRuntime.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 52; objects = { /* Begin PBXBuildFile section */ @@ -56,7 +56,7 @@ C38BB5F4287629C20039E385 /* defaultstatemachine.riv in Resources */ = {isa = PBXBuildFile; fileRef = C38BB5F3287629C20039E385 /* defaultstatemachine.riv */; }; C38BB5F628762B720039E385 /* RiveStateMachineTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C38BB5F528762B720039E385 /* RiveStateMachineTest.swift */; }; C3E2B580282F242400A8651B /* RiveStateMachineInstance+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3E2B57F282F242400A8651B /* RiveStateMachineInstance+Extensions.swift */; }; - C9161A81263CBCBC007749A1 /* RiveRuntime.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9C73ED124FC478800EF9516 /* RiveRuntime.framework */; }; + C9161A81263CBCBC007749A1 /* RiveRuntime.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9C73ED124FC478800EF9516 /* RiveRuntime.framework */; platformFilter = ios; }; C9601F2B250C25930032AA07 /* RiveRenderer.mm in Sources */ = {isa = PBXBuildFile; fileRef = C9601F2A250C25930032AA07 /* RiveRenderer.mm */; }; C9C73EE024FC478900EF9516 /* RiveRuntimeTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = C9C73EDF24FC478900EF9516 /* RiveRuntimeTests.mm */; }; C9C73EE224FC478900EF9516 /* RiveRuntime.h in Headers */ = {isa = PBXBuildFile; fileRef = C9C73ED424FC478800EF9516 /* RiveRuntime.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -464,6 +464,7 @@ /* Begin PBXTargetDependency section */ C9C73EDD24FC478900EF9516 /* PBXTargetDependency */ = { isa = PBXTargetDependency; + platformFilter = ios; target = C9C73ED024FC478800EF9516 /* RiveRuntime */; targetProxy = C9C73EDC24FC478900EF9516 /* PBXContainerItemProxy */; }; @@ -474,6 +475,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; @@ -503,6 +505,8 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; @@ -529,7 +533,7 @@ MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -539,6 +543,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; @@ -568,6 +573,8 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -587,7 +594,7 @@ MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = "iphonesimulator iphoneos"; + SUPPORTED_PLATFORMS = "macosx iphonesimulator iphoneos"; SWIFT_COMPILATION_MODE = wholemodule; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -603,9 +610,9 @@ CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = NJ3JMFUNS9; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -647,26 +654,36 @@ "-lrive_sim", "-lrive_skia_renderer_sim", ); + "OTHER_LDFLAGS[sdk=macosx*]" = ( + "-lskia_macos", + "-lrive_macos", + "-lrive_skia_renderer_macos", + ); PRODUCT_BUNDLE_IDENTIFIER = rive.app.ios.runtime.RiveRuntime; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,6"; }; name = Debug; }; C9C73EE724FC478900EF9516 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES; BITCODE_GENERATION_MODE = bitcode; BUILD_LIBRARY_FOR_DISTRIBUTION = YES; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_STYLE = Manual; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = NJ3JMFUNS9; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -710,12 +727,21 @@ "-lrive_sim", "-lrive_skia_renderer_sim", ); + "OTHER_LDFLAGS[sdk=macosx*]" = ( + "-lskia_macos", + "-lrive_macos", + "-lrive_skia_renderer_macos", + ); PRODUCT_BUNDLE_IDENTIFIER = rive.app.ios.runtime.RiveRuntime; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; + TARGETED_DEVICE_FAMILY = "1,2,6"; }; name = Release; }; @@ -734,6 +760,9 @@ ); PRODUCT_BUNDLE_IDENTIFIER = rive.app.ios.runtime.RiveRuntimeTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -755,6 +784,9 @@ ); PRODUCT_BUNDLE_IDENTIFIER = rive.app.ios.runtime.RiveRuntimeTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; diff --git a/Source/Renderer/rive_renderer_view.mm b/Source/Renderer/rive_renderer_view.mm index 93c6a94a..4b3b95e6 100644 --- a/Source/Renderer/rive_renderer_view.mm +++ b/Source/Renderer/rive_renderer_view.mm @@ -2,7 +2,12 @@ #import #import + +#if __has_include() #import +#else +#import +#endif #include "include/core/SkCanvas.h" #include "include/core/SkSurface.h" @@ -205,10 +210,12 @@ - (void)drawRect:(CGRect)rect return; } auto canvas = surface->getCanvas(); + rive::SkiaRenderer renderer(canvas); _renderer = &renderer; canvas->clear(SkColor((0x00000000))); _renderer->save(); + [self drawRive:rect size:size]; _renderer->restore(); diff --git a/Source/RiveView.swift b/Source/RiveView.swift index a2dff1dc..5b1cf6f8 100644 --- a/Source/RiveView.swift +++ b/Source/RiveView.swift @@ -12,13 +12,13 @@ import Foundation open class RiveView: RiveRendererView { // MARK: Configuration internal weak var riveModel: RiveModel? - internal var fit: RiveFit = .contain { didSet { setNeedsDisplay() } } - internal var alignment: RiveAlignment = .center { didSet { setNeedsDisplay() } } + internal var fit: RiveFit = .contain { didSet { needsDisplay() } } + internal var alignment: RiveAlignment = .center { didSet { needsDisplay() } } // MARK: Render Loop internal private(set) var isPlaying: Bool = false private var lastTime: CFTimeInterval = 0 - private var displayLinkProxy: CADisplayLinkProxy? + private var displayLinkProxy: DisplayLinkProxy? private var eventQueue = EventQueue() // MARK: Delegates @@ -46,12 +46,25 @@ open class RiveView: RiveRendererView { super.init(coder: aDecoder) } + private func needsDisplay() { + #if os(iOS) + setNeedsDisplay() + #else + needsDisplay=true + #endif + } + /// This resets the view with the new model. Useful when the `RiveView` was initialized without one. open func setModel(_ model: RiveModel, autoPlay: Bool = true) throws { stopTimer() isPlaying = false riveModel = model - isOpaque = false + #if os(iOS) + isOpaque = false + #else + layer?.isOpaque=false + #endif + if autoPlay { play() @@ -103,8 +116,9 @@ open class RiveView: RiveRendererView { // MARK: - Render Loop private func startTimer() { + if displayLinkProxy == nil { - displayLinkProxy = CADisplayLinkProxy( + displayLinkProxy = DisplayLinkProxy( handle: { [weak self] in self?.tick() }, @@ -112,9 +126,11 @@ open class RiveView: RiveRendererView { forMode: .common ) } - if displayLinkProxy?.displayLink?.isPaused == true { - displayLinkProxy?.displayLink?.isPaused = false - } + #if os(iOS) + if displayLinkProxy?.displayLink?.isPaused == true { + displayLinkProxy?.displayLink?.isPaused = false + } + #endif } private func stopTimer() { @@ -124,17 +140,22 @@ open class RiveView: RiveRendererView { fpsCounter?.stopped() } + private func timestamp() -> Double { + return Date().timeIntervalSince1970 + } + + /// Start a redraw: /// - determine the elapsed time /// - advance the artbaord, which will invalidate the display. /// - if the artboard has come to a stop, stop. @objc fileprivate func tick() { - guard let displayLink = displayLinkProxy?.displayLink else { + guard displayLinkProxy?.displayLink != nil else { stopTimer() return } - let timestamp = displayLink.timestamp + let timestamp = timestamp() // last time needs to be set on the first tick if lastTime == 0 { lastTime = timestamp @@ -142,6 +163,14 @@ open class RiveView: RiveRendererView { // Calculate the time elapsed between ticks let elapsedTime = timestamp - lastTime + + #if os(iOS) + fpsCounter?.didDrawFrame(timestamp: timestamp) + #else + fpsCounter?.elapsed(time: elapsedTime) + #endif + + lastTime = timestamp advance(delta: elapsedTime) if !isPlaying { @@ -182,7 +211,7 @@ open class RiveView: RiveRendererView { playerDelegate?.player(didAdvanceby: delta, riveModel: riveModel) // Trigger a redraw - setNeedsDisplay() + needsDisplay() } /// This is called in the middle of drawRect @@ -194,67 +223,141 @@ open class RiveView: RiveRendererView { align(with: newFrame, contentRect: artboard.bounds(), alignment: alignment, fit: fit) draw(with: artboard) - if let displayLink = displayLinkProxy?.displayLink { - fpsCounter?.didDrawFrame(timestamp:displayLink.timestamp) - } } // MARK: - UIResponder - - open override func touchesBegan(_ touches: Set, with event: UIEvent?) { - handleTouch(touches.first!, delegate: stateMachineDelegate?.touchBegan) { - $0.touchBegan(atLocation: $1) + #if os(iOS) + open override func touchesBegan(_ touches: Set, with event: UIEvent?) { + handleTouch(touches.first!, delegate: stateMachineDelegate?.touchBegan) { + $0.touchBegan(atLocation: $1) + } } - } - - open override func touchesMoved(_ touches: Set, with event: UIEvent?) { - handleTouch(touches.first!, delegate: stateMachineDelegate?.touchMoved) { - $0.touchMoved(atLocation: $1) + + open override func touchesMoved(_ touches: Set, with event: UIEvent?) { + handleTouch(touches.first!, delegate: stateMachineDelegate?.touchMoved) { + $0.touchMoved(atLocation: $1) + } } - } - - open override func touchesEnded(_ touches: Set, with event: UIEvent?) { - handleTouch(touches.first!, delegate: stateMachineDelegate?.touchEnded) { - $0.touchEnded(atLocation: $1) + + open override func touchesEnded(_ touches: Set, with event: UIEvent?) { + handleTouch(touches.first!, delegate: stateMachineDelegate?.touchEnded) { + $0.touchEnded(atLocation: $1) + } } - } - - open override func touchesCancelled(_ touches: Set, with event: UIEvent?) { - handleTouch(touches.first!, delegate: stateMachineDelegate?.touchCancelled) { - $0.touchCancelled(atLocation: $1) + + open override func touchesCancelled(_ touches: Set, with event: UIEvent?) { + handleTouch(touches.first!, delegate: stateMachineDelegate?.touchCancelled) { + $0.touchCancelled(atLocation: $1) + } } - } - - /// Sends incoming touch event to all playing `RiveStateMachineInstance`'s - /// - Parameters: - /// - touch: The `CGPoint` where the touch occurred in `RiveView` coordinate space - /// - delegateAction: The delegate callback that should be triggered by this touch event - /// - stateMachineAction: Param1: A playing `RiveStateMachineInstance`, Param2: `CGPoint` - /// location where touch occurred in `artboard` coordinate space - private func handleTouch( - _ touch: UITouch, - delegate delegateAction: ((RiveArtboard?, CGPoint)->Void)?, - stateMachineAction: (RiveStateMachineInstance, CGPoint)->Void - ) { - guard let artboard = riveModel?.artboard else { return } - guard let stateMachine = riveModel?.stateMachine else { return } - let location = touch.location(in: self) - let artboardLocation = artboardLocation( - fromTouchLocation: location, - inArtboard: artboard.bounds(), - fit: fit, - alignment: alignment - ) + /// Sends incoming touch event to all playing `RiveStateMachineInstance`'s + /// - Parameters: + /// - touch: The `CGPoint` where the touch occurred in `RiveView` coordinate space + /// - delegateAction: The delegate callback that should be triggered by this touch event + /// - stateMachineAction: Param1: A playing `RiveStateMachineInstance`, Param2: `CGPoint` + /// location where touch occurred in `artboard` coordinate space + private func handleTouch( + _ touch: UITouch, + delegate delegateAction: ((RiveArtboard?, CGPoint)->Void)?, + stateMachineAction: (RiveStateMachineInstance, CGPoint)->Void + ) { + guard let artboard = riveModel?.artboard else { return } + guard let stateMachine = riveModel?.stateMachine else { return } + let location = touch.location(in: self) + + let artboardLocation = artboardLocation( + fromTouchLocation: location, + inArtboard: artboard.bounds(), + fit: fit, + alignment: alignment + ) + + stateMachineAction(stateMachine, artboardLocation) + play() + + // We send back the touch location in UIView coordinates because + // users cannot query or manually control the coordinates of elements + // in the Artboard. So that information would be of no use. + delegateAction?(artboard, location) + } + #else + open override func mouseDown(with event: NSEvent) { + handleTouch(event, delegate: stateMachineDelegate?.touchBegan) { + $0.touchBegan(atLocation: $1) + } + } - stateMachineAction(stateMachine, artboardLocation) - play() + open override func mouseMoved(with event: NSEvent) { + handleTouch(event, delegate: stateMachineDelegate?.touchMoved) { + $0.touchMoved(atLocation: $1) + } + } - // We send back the touch location in UIView coordinates because - // users cannot query or manually control the coordinates of elements - // in the Artboard. So that information would be of no use. - delegateAction?(artboard, location) - } + open override func mouseDragged(with event: NSEvent) { + handleTouch(event, delegate: stateMachineDelegate?.touchMoved) { + $0.touchMoved(atLocation: $1) + } + } + + open override func mouseUp(with event: NSEvent) { + handleTouch(event, delegate: stateMachineDelegate?.touchEnded) { + $0.touchEnded(atLocation: $1) + } + } + + open override func mouseExited(with event: NSEvent) { + handleTouch(event, delegate: stateMachineDelegate?.touchCancelled) { + $0.touchCancelled(atLocation: $1) + } + } + + open override func updateTrackingAreas() { + addTrackingArea( + NSTrackingArea( + rect: self.bounds, + options: [.mouseEnteredAndExited, .mouseMoved, .activeInKeyWindow], + owner: self, + userInfo: nil + ) + ) + } + + /// Sends incoming touch event to all playing `RiveStateMachineInstance`'s + /// - Parameters: + /// - touch: The `CGPoint` where the touch occurred in `RiveView` coordinate space + /// - delegateAction: The delegate callback that should be triggered by this touch event + /// - stateMachineAction: Param1: A playing `RiveStateMachineInstance`, Param2: `CGPoint` + /// location where touch occurred in `artboard` coordinate space + private func handleTouch( + _ event: NSEvent, + delegate delegateAction: ((RiveArtboard?, CGPoint)->Void)?, + stateMachineAction: (RiveStateMachineInstance, CGPoint)->Void + ) { + guard let artboard = riveModel?.artboard else { return } + guard let stateMachine = riveModel?.stateMachine else { return } + let location = convert(event.locationInWindow, from: nil) + + // This is conforms the point to UIView coordinates which the + // RiveRendererView expects in its artboardLocation method + let locationFlippedY = CGPoint(x: location.x, y: frame.height - location.y) + + let artboardLocation = artboardLocation( + fromTouchLocation: locationFlippedY, + inArtboard: artboard.bounds(), + fit: fit, + alignment: alignment + ) + + stateMachineAction(stateMachine, artboardLocation) + play() + + // We send back the touch location in NSView coordinates because + // users cannot query or manually control the coordinates of elements + // in the Artboard. So that information would be of no use. + delegateAction?(artboard, location) + } + #endif // MARK: - Debug @@ -294,30 +397,59 @@ public protocol RivePlayerDelegate: AnyObject { func player(didAdvanceby seconds: Double, riveModel: RiveModel?) } -class CADisplayLinkProxy { - var displayLink: CADisplayLink? - var handle: (() -> Void)? - private var runloop: RunLoop - private var mode: RunLoop.Mode +#if os(iOS) + fileprivate class DisplayLinkProxy { + var displayLink: CADisplayLink? + var handle: (() -> Void)? + private var runloop: RunLoop + private var mode: RunLoop.Mode - init(handle: (() -> Void)?, to runloop: RunLoop, forMode mode: RunLoop.Mode) { - self.handle = handle - self.runloop = runloop - self.mode = mode - displayLink = CADisplayLink(target: self, selector: #selector(updateHandle)) - displayLink?.add(to: runloop, forMode: mode) - } + init(handle: (() -> Void)?, to runloop: RunLoop, forMode mode: RunLoop.Mode) { + self.handle = handle + self.runloop = runloop + self.mode = mode + displayLink = CADisplayLink(target: self, selector: #selector(updateHandle)) + displayLink?.add(to: runloop, forMode: mode) + } - @objc func updateHandle() { - handle?() + @objc func updateHandle() { + handle?() + } + + func invalidate() { + displayLink?.remove(from: runloop, forMode: mode) + displayLink?.invalidate() + displayLink = nil + } } +#else + fileprivate class DisplayLinkProxy { + var displayLink: CVDisplayLink? + + init?(handle: (() -> Void)!, to runloop: RunLoop, forMode mode: RunLoop.Mode) { + //ignore runloop/formode + let error = CVDisplayLinkCreateWithActiveCGDisplays(&displayLink) + if error != kCVReturnSuccess { return nil } + + CVDisplayLinkSetOutputHandler(displayLink!) { dl, ts, tsDisplay, _, _ in + DispatchQueue.main.async { + handle() + } + return kCVReturnSuccess + } + + CVDisplayLinkStart(displayLink!) + } - func invalidate() { - displayLink?.remove(from: runloop, forMode: mode) - displayLink?.invalidate() - displayLink = nil + func invalidate() { + + if let displayLink = displayLink { + CVDisplayLinkStop(displayLink) + self.displayLink = nil + } + } } -} +#endif /// Tracks a queue of events that haven't been fired yet. We do this so that we're not calling delegates and modifying state /// while a view is updating (e.g. being initialized, as we autoplay and fire play events during the view's init otherwise diff --git a/Source/RiveViewModel.swift b/Source/RiveViewModel.swift index 496ad344..5d9d67f6 100644 --- a/Source/RiveViewModel.swift +++ b/Source/RiveViewModel.swift @@ -408,38 +408,75 @@ open class RiveViewModel: NSObject, ObservableObject, RiveFileDelegate, RiveStat open func player(didAdvanceby seconds: Double, riveModel: RiveModel?) { } } -/// This makes a SwiftUI digestable view from an `RiveViewModel` and its `RiveView` -public struct RiveViewRepresentable: UIViewRepresentable { - let viewModel: RiveViewModel - - public init(viewModel: RiveViewModel) { - self.viewModel = viewModel - } - - /// Constructs the view - public func makeUIView(context: Context) -> RiveView { - return viewModel.createRiveView() - } - - public func updateUIView(_ view: RiveView, context: UIViewRepresentableContext) { - viewModel.update(view: view) - } - - public static func dismantleUIView(_ view: RiveView, coordinator: Coordinator) { - view.stop() - coordinator.viewModel.deregisterView() - } - - /// Constructs a coordinator for managing updating state - public func makeCoordinator() -> Coordinator { - return Coordinator(viewModel: viewModel) +#if os(iOS) + /// This makes a SwiftUI digestable view from an `RiveViewModel` and its `RiveView` + public struct RiveViewRepresentable: UIViewRepresentable { + let viewModel: RiveViewModel + + public init(viewModel: RiveViewModel) { + self.viewModel = viewModel + } + + /// Constructs the view + public func makeUIView(context: Context) -> RiveView { + return viewModel.createRiveView() + } + + public func updateUIView(_ view: RiveView, context: UIViewRepresentableContext) { + viewModel.update(view: view) + } + + public static func dismantleUIView(_ view: RiveView, coordinator: Coordinator) { + view.stop() + coordinator.viewModel.deregisterView() + } + + /// Constructs a coordinator for managing updating state + public func makeCoordinator() -> Coordinator { + return Coordinator(viewModel: viewModel) + } + + public class Coordinator: NSObject { + public var viewModel: RiveViewModel + + init(viewModel: RiveViewModel) { + self.viewModel = viewModel + } + } } - - public class Coordinator: NSObject { - public var viewModel: RiveViewModel +#else + public struct RiveViewRepresentable: NSViewRepresentable { + let viewModel: RiveViewModel - init(viewModel: RiveViewModel) { + public init(viewModel: RiveViewModel) { self.viewModel = viewModel } + + /// Constructs the view + public func makeNSView(context: Context) -> RiveView { + return viewModel.createRiveView() + } + + public func updateNSView(_ view: RiveView, context: NSViewRepresentableContext) { + viewModel.update(view: view) + } + + public static func dismantleNSView(_ view: RiveView, coordinator: Coordinator) { + view.stop() + coordinator.viewModel.deregisterView() + } + + /// Constructs a coordinator for managing updating state + public func makeCoordinator() -> Coordinator { + return Coordinator(viewModel: viewModel) + } + + public class Coordinator: NSObject { + public var viewModel: RiveViewModel + + init(viewModel: RiveViewModel) { + self.viewModel = viewModel + } + } } -} +#endif diff --git a/Source/Utils/FPSCounterView.swift b/Source/Utils/FPSCounterView.swift index 3f2880dc..b9b6a822 100644 --- a/Source/Utils/FPSCounterView.swift +++ b/Source/Utils/FPSCounterView.swift @@ -6,6 +6,7 @@ // Copyright © 2022 Rive. All rights reserved. // +#if canImport(UIKit) import UIKit class FPSCounterView: UILabel { @@ -51,3 +52,49 @@ class FPSCounterView: UILabel { text = "Stopped" } } +#else +import AppKit + +class FPSCounterView: NSTextField { + private let fpsFormatter = NumberFormatter() + private let updateInterval: Double = 0.5 + private var timeSinceUpdate: Double = 0 + + internal convenience init() { + self.init(frame: CGRect(x: 1, y: 1, width: 70, height: 15)) + isBezeled = false + isEditable = false + isSelectable = false + + backgroundColor = .darkGray + textColor = .white + alignment = .center + font = NSFont.systemFont(ofSize: 11, weight: .regular) + alphaValue = 0.75 + + //clipsToBounds = true + //layer?.cornerRadius = 5 + stringValue = "..." + + fpsFormatter.minimumFractionDigits = 2 + fpsFormatter.maximumFractionDigits = 2 + fpsFormatter.roundingMode = .down + } + + internal func elapsed(time elapsedTime: Double) { + if elapsedTime != 0 { + timeSinceUpdate += elapsedTime + + if timeSinceUpdate >= updateInterval { + timeSinceUpdate = 0 + stringValue = fpsFormatter.string(from: NSNumber(value: 1 / elapsedTime))! + "fps" + } + } + } + + internal func stopped() { + stringValue = "Stopped" + } +} + +#endif diff --git a/scripts/build.rive.sh b/scripts/build.rive.sh index 2f595784..98c73615 100755 --- a/scripts/build.rive.sh +++ b/scripts/build.rive.sh @@ -54,26 +54,42 @@ build_renderer_sim() { cp -r $RIVE_RUNTIME_DIR/include $DEV_SCRIPT_DIR/../dependencies/includes/rive } +build_renderer_macosx() { + # NOTE: we do not currently use debug, so lets not build debug + pushd $RIVE_RUNTIME_DIR/skia/renderer + ./build.sh -p macosx clean + ./build.sh -p macosx $1 + popd + cp -r $RIVE_RUNTIME_DIR/build/macosx/bin/$1/librive.a $DEV_SCRIPT_DIR/../dependencies/$1/librive_macos.a + cp -r $RIVE_RUNTIME_DIR/skia/renderer/build/macosx/bin/$1/librive_skia_renderer.a $DEV_SCRIPT_DIR/../dependencies/$1/librive_skia_renderer_macos.a + + cp -r $RIVE_RUNTIME_DIR/skia/renderer/include $DEV_SCRIPT_DIR/../dependencies/includes/renderer + cp -r $RIVE_RUNTIME_DIR/include $DEV_SCRIPT_DIR/../dependencies/includes/rive +} + + finalize_skia() { # COMBINE SKIA # make fat library, note that the ios64 library is already fat with arm64 and arm64e so we don't specify arch there. pwd pushd $RIVE_RUNTIME_DIR/skia/dependencies/skia - xcrun -sdk iphoneos lipo -create -arch armv7 out/arm/libskia.a out/arm64/libskia.a -output out/libskia_ios.a - xcrun -sdk iphoneos lipo -create -arch x86_64 out/x64/libskia.a -arch i386 out/x86/libskia.a out/iossim_arm64/libskia.a -output out/libskia_ios_sim.a + xcrun -sdk macosx lipo -create -arch x86_64 out/macosx/x64/libskia.a -arch arm64 out/macosx/arm64/libskia.a -output out/macosx/libskia_macos.a + xcrun -sdk iphoneos lipo -create -arch armv7 out/ios/arm/libskia.a out/ios/arm64/libskia.a -output out/ios/libskia_ios.a + xcrun -sdk iphoneos lipo -create -arch x86_64 out/ios/x64/libskia.a -arch i386 out/ios/x86/libskia.a out/ios/iossim_arm64/libskia.a -output out/ios/libskia_ios_sim.a popd # copy skia outputs from ld'in skia! - cp -r $RIVE_RUNTIME_DIR/skia/dependencies/skia/out/libskia_ios.a $DEV_SCRIPT_DIR/../dependencies - cp -r $RIVE_RUNTIME_DIR/skia/dependencies/skia/out/libskia_ios_sim.a $DEV_SCRIPT_DIR/../dependencies + cp -r $RIVE_RUNTIME_DIR/skia/dependencies/skia/out/ios/libskia_ios.a $DEV_SCRIPT_DIR/../dependencies + cp -r $RIVE_RUNTIME_DIR/skia/dependencies/skia/out/ios/libskia_ios_sim.a $DEV_SCRIPT_DIR/../dependencies + cp -r $RIVE_RUNTIME_DIR/skia/dependencies/skia/out/macosx/libskia_macos.a $DEV_SCRIPT_DIR/../dependencies # note we purposefully put the skia include folder into dependencies/includes/skia, skia includes headers from include/core/name.h cp -r $RIVE_RUNTIME_DIR/skia/dependencies/skia/include $DEV_SCRIPT_DIR/../dependencies/includes/skia } usage () { - echo "USAGE: $0 " + echo "USAGE: $0 " exit 1 } @@ -90,6 +106,24 @@ case $1 in build_renderer release build_renderer_sim debug build_renderer_sim release + build_renderer_macosx debug + build_renderer_macosx release + ;; + macosx) + if (( $# < 2 )) + then + usage + fi + case $2 in + release | debug) + make_dependency_directories + finalize_skia + build_renderer_macosx $2 + ;; + *) + usage + ;; + esac ;; ios) if (( $# < 2 )) diff --git a/scripts/build.sh b/scripts/build.sh index bbe2feb0..e7bc493d 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -9,5 +9,7 @@ $DEV_SCRIPT_DIR/build.skia.sh -a x64 $DEV_SCRIPT_DIR/build.skia.sh -a arm $DEV_SCRIPT_DIR/build.skia.sh -a arm64 $DEV_SCRIPT_DIR/build.skia.sh -a iossim_arm64 +$DEV_SCRIPT_DIR/build.skia.macos.sh -a arm64 +$DEV_SCRIPT_DIR/build.skia.macos.sh -a x64 $DEV_SCRIPT_DIR/build.rive.sh $@ \ No newline at end of file diff --git a/scripts/build.skia.macos.sh b/scripts/build.skia.macos.sh new file mode 100755 index 00000000..1c5f7675 --- /dev/null +++ b/scripts/build.skia.macos.sh @@ -0,0 +1,47 @@ +#!/bin/bash +set -ex + +ARCH_X64=x64 +ARCH_ARM64=arm64 + +usage() { + printf "Usage: %s -a arch\n" "$0" + printf "\t-a Specify an architecture (i.e. '%s', '%s')\n" $ARCH_X64 $ARCH_ARM64 + exit 1 # Exit script after printing help +} + +while getopts "a:cd" opt; do + case "$opt" in + a) ARCH_NAME="$OPTARG" ;; + \?) usage ;; # Print usage in case parameter is non-existent + esac +done + +if [ -z "$ARCH_NAME" ]; then + echo "No architecture specified" + usage +fi + +path=`readlink -f "${BASH_SOURCE:-$0}"` +DEV_SCRIPT_DIR=`dirname $path` + +export SKIA_REPO="https://github.com/rive-app/skia" +export SKIA_BRANCH="rive" +export COMPILE_TARGET="macos_$EXPECTED_NDK_VERSION_$ARCH_NAME" +export CACHE_NAME="rive_skia_macos" +export MAKE_SKIA_FILE="make_skia_macos.sh" +export SKIA_DIR_NAME="skia" +# we can have multiple at the same time... +export ARCHIVE_CONTENTS_NAME="archive_contents_macos_$ARCH_NAME" + +if [ -d "$DEV_SCRIPT_DIR/../submodules/rive-cpp" ]; +then + export RIVE_RUNTIME_DIR="$DEV_SCRIPT_DIR/../submodules/rive-cpp" +else + export RIVE_RUNTIME_DIR="$DEV_SCRIPT_DIR/../../runtime" +fi + +# Build skia +pushd "$RIVE_RUNTIME_DIR"/skia/dependencies +./make_skia_macos.sh $ARCH_NAME +popd \ No newline at end of file diff --git a/scripts/build.skia.sh b/scripts/build.skia.sh index f36d28eb..bf63c82d 100755 --- a/scripts/build.skia.sh +++ b/scripts/build.skia.sh @@ -35,7 +35,7 @@ export CACHE_NAME="rive_skia_ios" export MAKE_SKIA_FILE="make_skia_ios.sh" export SKIA_DIR_NAME="skia" # we can have multiple at the same time... -export ARCHIVE_CONTENTS_NAME="archive_contents_$ARCH_NAME" +export ARCHIVE_CONTENTS_NAME="archive_contents_ios_$ARCH_NAME" if [ -d "$DEV_SCRIPT_DIR/../submodules/rive-cpp" ]; then diff --git a/scripts/build_framework.sh b/scripts/build_framework.sh index 493f4af8..1042a8f7 100755 --- a/scripts/build_framework.sh +++ b/scripts/build_framework.sh @@ -8,25 +8,54 @@ function usage() { echo -e "${RED}👉 $1${CLEAR}\n"; fi echo "Usage: $0 [-t target] [-c configuration]" - echo " -t, --target Target (iphoneos / iphonesimulator)" echo " -c, --configuration Configuration (Debug / Release)" echo "" - echo "Example: $0 --target iphoneos --configuration Debug" + echo "Example: $0 --configuration Debug" exit 1 } # parse params while [[ "$#" > 0 ]]; do case $1 in - -t|--target) TARGET="$2"; shift;shift;; -c|--configuration) CONFIGURATION="$2";shift;shift;; *) usage "Unknown parameter passed: $1"; shift; shift;; esac; done # verify params -if [ -z "$TARGET" ]; then usage "Target is not set"; fi; if [ -z "$CONFIGURATION" ]; then usage "Configuration is not set."; fi; echo -e "Build Rive Framework" -echo -e "Configuration -> ${CONFIGURATION}, target -> ${TARGET}" +echo -e "Configuration -> ${CONFIGURATION}" -xcodebuild -project RiveRuntime.xcodeproj -scheme RiveRuntime -sdk ${TARGET} -derivedDataPath archive -configuration ${CONFIGURATION} | xcpretty \ No newline at end of file +xcodebuild archive \ + -configuration ${CONFIGURATION} \ + -project RiveRuntime.xcodeproj \ + -scheme RiveRuntime \ + -destination generic/platform=iOS \ + -archivePath ".build/archives/RiveRuntime_iOS" \ + SKIP_INSTALL=NO \ + BUILD_LIBRARY_FOR_DISTRIBUTION=YES + +xcodebuild archive \ + -configuration ${CONFIGURATION} \ + -project RiveRuntime.xcodeproj \ + -scheme RiveRuntime \ + -destination "generic/platform=iOS Simulator" \ + -archivePath ".build/archives/RiveRuntime_iOS_Simulator" \ + SKIP_INSTALL=NO \ + BUILD_LIBRARY_FOR_DISTRIBUTION=YES + +xcodebuild archive \ + -configuration ${CONFIGURATION} \ + -project RiveRuntime.xcodeproj \ + -scheme RiveRuntime \ + -destination generic/platform=macOS \ + -archivePath ".build/archives/RiveRuntime_macOS" \ + SKIP_INSTALL=NO \ + BUILD_LIBRARY_FOR_DISTRIBUTION=YES + +xcodebuild \ + -create-xcframework \ + -framework .build/archives/RiveRuntime_iOS.xcarchive/Products/Library/Frameworks/RiveRuntime.framework \ + -framework .build/archives/RiveRuntime_iOS_Simulator.xcarchive/Products/Library/Frameworks/RiveRuntime.framework \ + -framework .build/archives/RiveRuntime_macOS.xcarchive/Products/Library/Frameworks/RiveRuntime.framework \ + -output archive/RiveRuntime.xcframework \ No newline at end of file diff --git a/scripts/merge_frameworks.sh b/scripts/merge_frameworks.sh deleted file mode 100755 index 6c8ae85f..00000000 --- a/scripts/merge_frameworks.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -BASEDIR=$(pwd) - -CLEAR='\033[0m' -RED='\033[0;31m' - -function usage() { - if [ -n "$1" ]; then - echo -e "${RED}👉 $1${CLEAR}\n"; - fi - echo "Usage: $0 [-c configuration]" - echo " -c, --configuration Configuration (Debug / Release)" - echo "" - echo "Example: $0 --target iphoneos --configuration Debug" - exit 1 -} - -# parse params -while [[ "$#" > 0 ]]; do case $1 in - -c|--configuration) CONFIGURATION="$2";shift;shift;; - *) usage "Unknown parameter passed: $1"; shift; shift;; -esac; done - -echo -e "Merge Rive Frameworks" -xcodebuild \ - -create-xcframework \ - -framework "${BASEDIR}/archive/Build/Products/${CONFIGURATION}-iphoneos/RiveRuntime.framework" \ - -framework "${BASEDIR}/archive/Build/Products/${CONFIGURATION}-iphonesimulator/RiveRuntime.framework" \ - -output "${BASEDIR}/archive/RiveRuntime.xcframework" | xcpretty \ No newline at end of file diff --git a/submodules/rive-cpp b/submodules/rive-cpp index 2121cdcb..73fac9a8 160000 --- a/submodules/rive-cpp +++ b/submodules/rive-cpp @@ -1 +1 @@ -Subproject commit 2121cdcbc19c7c8853507dcc6482bb5f97440bbb +Subproject commit 73fac9a8376bd83d6b241b92fc84f7a9886d6b2f