@airisu-dev/react-native-live2d-skia 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/Live2dSkia.podspec +159 -0
- package/README.md +64 -2
- package/android/CMakeLists.txt +113 -0
- package/android/build.gradle +223 -0
- package/android/fix-prefab.gradle +51 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/cpp-adapter.cpp +9 -0
- package/android/src/main/java/com/live2dskia/Live2dSkiaPackage.kt +20 -0
- package/app.plugin.js +2 -0
- package/cli/build/index.js +157 -0
- package/cpp/cubism/CubismCompat.hpp +26 -0
- package/cpp/cubism/CubismHelpers.hpp +27 -0
- package/cpp/cubism/CubismRendererStub.cpp +14 -0
- package/cpp/cubism/CubismSetup.cpp +54 -0
- package/cpp/cubism/CubismSetup.hpp +9 -0
- package/cpp/cubism/HeldParameterUpdater.hpp +25 -0
- package/cpp/cubism/Live2DUserModel.cpp +125 -0
- package/cpp/cubism/Live2DUserModel.hpp +57 -0
- package/cpp/cubism/Live2DUserModelAnimation.cpp +107 -0
- package/cpp/drawing/JsiUnwrap.hpp +25 -0
- package/cpp/drawing/MeshCache.cpp +75 -0
- package/cpp/drawing/MeshCache.hpp +45 -0
- package/cpp/drawing/SkiaDrawer.cpp +138 -0
- package/cpp/drawing/SkiaDrawer.hpp +42 -0
- package/cpp/hybrid/HybridLive2DModel.cpp +174 -0
- package/cpp/hybrid/HybridLive2DModel.hpp +64 -0
- package/cpp/hybrid/HybridLive2dSkia.cpp +10 -0
- package/cpp/hybrid/HybridLive2dSkia.hpp +11 -0
- package/ios/Bridge.h +8 -0
- package/nitro.json +20 -0
- package/nitrogen/generated/.gitattributes +1 -0
- package/nitrogen/generated/android/Live2dSkia+autolinking.cmake +82 -0
- package/nitrogen/generated/android/Live2dSkia+autolinking.gradle +27 -0
- package/nitrogen/generated/android/Live2dSkiaOnLoad.cpp +49 -0
- package/nitrogen/generated/android/Live2dSkiaOnLoad.hpp +34 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/live2dskia/Live2dSkiaOnLoad.kt +35 -0
- package/nitrogen/generated/ios/Live2dSkia+autolinking.rb +62 -0
- package/nitrogen/generated/ios/Live2dSkia-Swift-Cxx-Bridge.cpp +17 -0
- package/nitrogen/generated/ios/Live2dSkia-Swift-Cxx-Bridge.hpp +27 -0
- package/nitrogen/generated/ios/Live2dSkia-Swift-Cxx-Umbrella.hpp +38 -0
- package/nitrogen/generated/ios/Live2dSkiaAutolinking.mm +35 -0
- package/nitrogen/generated/ios/Live2dSkiaAutolinking.swift +16 -0
- package/nitrogen/generated/shared/c++/DrawableData.hpp +116 -0
- package/nitrogen/generated/shared/c++/HybridLive2DModelSpec.cpp +39 -0
- package/nitrogen/generated/shared/c++/HybridLive2DModelSpec.hpp +86 -0
- package/nitrogen/generated/shared/c++/HybridLive2dSkiaSpec.cpp +21 -0
- package/nitrogen/generated/shared/c++/HybridLive2dSkiaSpec.hpp +66 -0
- package/nitrogen/generated/shared/c++/MotionPriority.hpp +80 -0
- package/package.json +146 -4
- package/plugin/build/index.d.ts +14 -0
- package/plugin/build/index.js +81 -0
- package/src/components/Live2D.tsx +131 -0
- package/src/components/index.ts +2 -0
- package/src/hooks/index.ts +8 -0
- package/src/hooks/useLive2DGesture.ts +140 -0
- package/src/hooks/useLive2DModel.ts +47 -0
- package/src/index.ts +5 -0
- package/src/loader/cubismJson.ts +23 -0
- package/src/loader/index.ts +9 -0
- package/src/loader/loadModel.ts +194 -0
- package/src/loader/modelContext.ts +80 -0
- package/src/loader/modelUrl.ts +112 -0
- package/src/native.ts +4 -0
- package/src/rendering/drawer.ts +256 -0
- package/src/rendering/skia.ts +114 -0
- package/src/rendering/ticker/addToTicker.ts +52 -0
- package/src/rendering/ticker/constants.ts +11 -0
- package/src/rendering/ticker/frames.ts +35 -0
- package/src/rendering/ticker/index.ts +5 -0
- package/src/rendering/ticker/loop.ts +115 -0
- package/src/rendering/ticker/state.ts +65 -0
- package/src/rendering/ticker/stats.ts +36 -0
- package/src/rendering/ticker/types.ts +57 -0
- package/src/specs/react-native-live2d-skia.nitro.ts +88 -0
- package/src/utils/clock.ts +10 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 airisu.dev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
# Cubism SDK for Native: proprietary, so each app downloads it from Live2D and
|
|
6
|
+
# sets its folder (app.plugin.js writes live2dSkia.cubismSdkPath to
|
|
7
|
+
# Podfile.properties.json, relative to ios/).
|
|
8
|
+
ios_dir = Pod::Config.instance.installation_root.to_s
|
|
9
|
+
podfile_properties_path = File.join(ios_dir, "Podfile.properties.json")
|
|
10
|
+
podfile_properties = File.exist?(podfile_properties_path) ? JSON.parse(File.read(podfile_properties_path)) : {}
|
|
11
|
+
configured_sdk_dir = ENV["LIVE2D_SKIA_CUBISM_SDK"] || podfile_properties["live2dSkia.cubismSdkPath"]
|
|
12
|
+
unless configured_sdk_dir
|
|
13
|
+
raise "[react-native-live2d-skia] Cubism SDK for Native isn't configured. Add the plugin to app.json: " \
|
|
14
|
+
"[\"@airisu-dev/react-native-live2d-skia\", { \"cubismSdkPath\": \"./vendor/CubismSdkForNative\" }], download the SDK with " \
|
|
15
|
+
"`@airisu-dev/react-native-live2d-skia fetch-sdk --accept-license` (through npx, bunx, yarn or pnpm), then prebuild."
|
|
16
|
+
end
|
|
17
|
+
cubism_sdk_dir = File.expand_path(configured_sdk_dir, ios_dir)
|
|
18
|
+
cubism_info = File.join(cubism_sdk_dir, "cubism-info.yml")
|
|
19
|
+
unless File.file?(cubism_info)
|
|
20
|
+
raise "[react-native-live2d-skia] Cubism SDK for Native not found at #{cubism_sdk_dir} (no cubism-info.yml). " \
|
|
21
|
+
"Download it with `@airisu-dev/react-native-live2d-skia fetch-sdk --accept-license` (through npx, bunx, yarn or pnpm)."
|
|
22
|
+
end
|
|
23
|
+
cubism_version = File.read(cubism_info)[/^version:\s*(\S+)/, 1] || "unknown"
|
|
24
|
+
|
|
25
|
+
# A Cubism SDK version as a number: major * 10000 + release * 100 + patch, so
|
|
26
|
+
# 5-r.4.1 is 50401 (a -beta suffix is ignored). Nil if it isn't one.
|
|
27
|
+
cubism_version_number = lambda do |version|
|
|
28
|
+
m = version.match(/^(\d+)-r\.(\d+)(?:\.(\d+))?/)
|
|
29
|
+
m && m[1].to_i * 10000 + m[2].to_i * 100 + m[3].to_i
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Listed versions (cubismSdk.versions in package.json) are supported. A newer
|
|
33
|
+
# release of a listed major only warns; anything else fails.
|
|
34
|
+
listed_versions = package["cubismSdk"]["versions"].keys
|
|
35
|
+
cubism_version_num = cubism_version_number.call(cubism_version)
|
|
36
|
+
unless listed_versions.include?(cubism_version)
|
|
37
|
+
newest_of_major = cubism_version_num && listed_versions.map { |v| cubism_version_number.call(v) }
|
|
38
|
+
.select { |n| n / 10000 == cubism_version_num / 10000 }.max
|
|
39
|
+
if newest_of_major.nil? || cubism_version_num < newest_of_major
|
|
40
|
+
raise "[react-native-live2d-skia] Cubism SDK for Native #{cubism_version} at #{cubism_sdk_dir} isn't supported: use #{listed_versions.join(', ')}."
|
|
41
|
+
end
|
|
42
|
+
Pod::UI.warn "[react-native-live2d-skia] Cubism SDK for Native #{cubism_version} found, tested with #{listed_versions.join(', ')}."
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# CocoaPods only compiles files inside the pod, and the SDK ships one Core static
|
|
46
|
+
# library per slice. So copy the Framework source in, and package the Core
|
|
47
|
+
# slices as an xcframework (CocoaPods then links the right one for device or
|
|
48
|
+
# simulator). Redone when the SDK's folder or version changes. Gitignored, not published.
|
|
49
|
+
cubism_stage_dir = File.join(__dir__, "cubism-sdk")
|
|
50
|
+
cubism_stamp = "#{cubism_sdk_dir}\n#{cubism_version}\n"
|
|
51
|
+
cubism_stamp_path = File.join(cubism_stage_dir, ".stamp")
|
|
52
|
+
unless File.exist?(cubism_stamp_path) && File.read(cubism_stamp_path) == cubism_stamp
|
|
53
|
+
require "fileutils"
|
|
54
|
+
require "tmpdir"
|
|
55
|
+
FileUtils.rm_rf(cubism_stage_dir)
|
|
56
|
+
FileUtils.mkdir_p(cubism_stage_dir)
|
|
57
|
+
FileUtils.cp_r(File.join(cubism_sdk_dir, "Framework", "src"), File.join(cubism_stage_dir, "Framework"))
|
|
58
|
+
core = File.join(cubism_sdk_dir, "Core")
|
|
59
|
+
FileUtils.mkdir_p(File.join(cubism_stage_dir, "Core"))
|
|
60
|
+
FileUtils.cp_r(File.join(core, "include"), File.join(cubism_stage_dir, "Core", "include"))
|
|
61
|
+
lib = File.join(core, "lib", "ios")
|
|
62
|
+
Dir.mktmpdir do |tmp|
|
|
63
|
+
simulator_lib = File.join(tmp, "libLive2DCubismCore.a")
|
|
64
|
+
run = lambda do |*cmd|
|
|
65
|
+
system(*cmd) or raise "[react-native-live2d-skia] Failed to package Cubism Core: #{cmd.join(' ')}"
|
|
66
|
+
end
|
|
67
|
+
run.call("lipo", "-create",
|
|
68
|
+
File.join(lib, "Release-iphonesimulator-arm64", "libLive2DCubismCore.a"),
|
|
69
|
+
File.join(lib, "Release-iphonesimulator-x86_64", "libLive2DCubismCore.a"),
|
|
70
|
+
"-output", simulator_lib)
|
|
71
|
+
run.call("xcodebuild", "-create-xcframework",
|
|
72
|
+
"-library", File.join(lib, "Release-iphoneos", "libLive2DCubismCore.a"),
|
|
73
|
+
"-headers", File.join(core, "include"),
|
|
74
|
+
"-library", simulator_lib, "-headers", File.join(core, "include"),
|
|
75
|
+
"-output", File.join(cubism_stage_dir, "Live2DCubismCore.xcframework"))
|
|
76
|
+
end
|
|
77
|
+
File.write(cubism_stamp_path, cubism_stamp)
|
|
78
|
+
Pod::UI.puts "[react-native-live2d-skia] Using Cubism SDK for Native #{cubism_version} from #{cubism_sdk_dir}"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Draw in C++ onto Skia canvases (cpp/drawing/SkiaDrawer.cpp). Skia is linked statically
|
|
82
|
+
# into the app by its pod (named react-native-skia in v3 and v2), so this only
|
|
83
|
+
# needs its headers and the defines it's built with. Which Skia: the one
|
|
84
|
+
# app.plugin.js found in the app's package.json (live2dSkia.skiaPackage), v3
|
|
85
|
+
# (Graphite) or v2 (Ganesh), resolved from the app since a monorepo can have
|
|
86
|
+
# both installed. Without it, models are drawn in JS.
|
|
87
|
+
rn_skia_package = podfile_properties["live2dSkia.skiaPackage"].to_s
|
|
88
|
+
rn_skia_dir = nil
|
|
89
|
+
unless rn_skia_package.empty?
|
|
90
|
+
app_dir = File.dirname(ios_dir)
|
|
91
|
+
resolved = IO.popen(["node", "-p",
|
|
92
|
+
"require('path').dirname(require.resolve(process.argv[1] + '/package.json', { paths: [process.argv[2]] }))",
|
|
93
|
+
rn_skia_package, app_dir], err: File::NULL, &:read).to_s.strip
|
|
94
|
+
rn_skia_dir = resolved if $?.success? && File.file?(File.join(resolved, "cpp", "api", "JsiSkCanvas.h"))
|
|
95
|
+
end
|
|
96
|
+
rn_skia_graphite = rn_skia_package == "react-native-skia"
|
|
97
|
+
|
|
98
|
+
Pod::Spec.new do |s|
|
|
99
|
+
s.name = "Live2dSkia"
|
|
100
|
+
s.version = package["version"]
|
|
101
|
+
s.summary = package["description"]
|
|
102
|
+
s.homepage = package["homepage"]
|
|
103
|
+
s.license = package["license"]
|
|
104
|
+
s.authors = package["author"]
|
|
105
|
+
|
|
106
|
+
s.platforms = { :ios => min_ios_version_supported }
|
|
107
|
+
s.source = { :git => "https://github.com/airisu-dev/react-native-live2d-skia.git", :tag => "#{s.version}" }
|
|
108
|
+
|
|
109
|
+
s.source_files = [
|
|
110
|
+
# Implementation (Swift)
|
|
111
|
+
"ios/**/*.{swift}",
|
|
112
|
+
# Autolinking/Registration (Objective-C++)
|
|
113
|
+
"ios/**/*.{m,mm}",
|
|
114
|
+
# Implementation (C++ objects)
|
|
115
|
+
"cpp/**/*.{hpp,cpp}",
|
|
116
|
+
# Cubism Native Framework (motions, physics, pose, ...)
|
|
117
|
+
"cubism-sdk/Framework/**/*.{hpp,cpp}",
|
|
118
|
+
]
|
|
119
|
+
# Its Rendering/<backend> folders are left out: we draw with Skia
|
|
120
|
+
# (see cpp/cubism/CubismRendererStub.cpp).
|
|
121
|
+
s.exclude_files = "cubism-sdk/Framework/Rendering/*/**/*"
|
|
122
|
+
|
|
123
|
+
s.vendored_frameworks = "cubism-sdk/Live2DCubismCore.xcframework"
|
|
124
|
+
# Set before add_nitrogen_files, which merges its own settings into this.
|
|
125
|
+
header_search_paths = [
|
|
126
|
+
"\"$(PODS_TARGET_SRCROOT)/cubism-sdk/Core/include\"",
|
|
127
|
+
"\"$(PODS_TARGET_SRCROOT)/cubism-sdk/Framework\"",
|
|
128
|
+
"\"$(PODS_TARGET_SRCROOT)/cpp/hybrid\"",
|
|
129
|
+
"\"$(PODS_TARGET_SRCROOT)/cpp/cubism\"",
|
|
130
|
+
"\"$(PODS_TARGET_SRCROOT)/cpp/drawing\"",
|
|
131
|
+
]
|
|
132
|
+
# The SDK's version, for cpp/cubism/CubismCompat.hpp.
|
|
133
|
+
preprocessor_definitions = ["$(inherited)", "LIVE2D_SKIA_CUBISM_SDK=#{cubism_version_num}"]
|
|
134
|
+
if rn_skia_dir
|
|
135
|
+
Pod::UI.puts "[Live2dSkia] Drawing with Skia in C++ (#{rn_skia_dir}, #{rn_skia_graphite ? 'Graphite' : 'Ganesh'})"
|
|
136
|
+
s.dependency "react-native-skia"
|
|
137
|
+
skia_headers = ["cpp", "cpp/skia", "cpp/api", "cpp/jsi", "cpp/rnskia", "cpp/rnskia/values", "cpp/utils"]
|
|
138
|
+
skia_headers << "cpp/dawn/include" if rn_skia_graphite
|
|
139
|
+
header_search_paths += skia_headers.map { |dir| "\"#{File.join(rn_skia_dir, dir)}\"" }
|
|
140
|
+
# Same as the Skia pod: struct layouts must match.
|
|
141
|
+
preprocessor_definitions += ["LIVE2D_SKIA=1",
|
|
142
|
+
"SK_IMAGE_READ_PIXELS_DISABLE_LEGACY_API=1",
|
|
143
|
+
"SK_DISABLE_LEGACY_SHAPER_FACTORY=1"]
|
|
144
|
+
preprocessor_definitions += rn_skia_graphite ? ["SK_GRAPHITE=1"] : ["SK_METAL=1", "SK_GANESH=1"]
|
|
145
|
+
else
|
|
146
|
+
Pod::UI.puts "[Live2dSkia] No Skia to draw with in C++, drawing in JS"
|
|
147
|
+
end
|
|
148
|
+
s.pod_target_xcconfig = {
|
|
149
|
+
"HEADER_SEARCH_PATHS" => header_search_paths.join(" "),
|
|
150
|
+
"GCC_PREPROCESSOR_DEFINITIONS" => preprocessor_definitions.join(" "),
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
load 'nitrogen/generated/ios/Live2dSkia+autolinking.rb'
|
|
154
|
+
add_nitrogen_files(s)
|
|
155
|
+
|
|
156
|
+
s.dependency 'React-jsi'
|
|
157
|
+
s.dependency 'React-callinvoker'
|
|
158
|
+
install_modules_dependencies(s)
|
|
159
|
+
end
|
package/README.md
CHANGED
|
@@ -1,3 +1,65 @@
|
|
|
1
|
-
#
|
|
1
|
+
# react-native-live2d-skia
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
react-native-live2d-skia is a react native package built with Nitro
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@airisu-dev/react-native-live2d-skia)
|
|
6
|
+
[](https://www.npmjs.com/package/@airisu-dev/react-native-live2d-skia)
|
|
7
|
+
[](https://github.com/airisu-dev/react-native-live2d-skia/blob/main/LICENSE)
|
|
8
|
+
|
|
9
|
+
## Requirements
|
|
10
|
+
|
|
11
|
+
- React Native v0.76.0 or higher
|
|
12
|
+
- Node 18.0.0 or higher
|
|
13
|
+
|
|
14
|
+
> [!IMPORTANT]
|
|
15
|
+
> To Support `Nitro Views` you need to install React Native version v0.78.0 or higher.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx expo install @airisu-dev/react-native-live2d-skia react-native-nitro-modules react-native-skia react-native-reanimated react-native-worklets react-native-gesture-handler expo-asset expo-file-system
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Expo apps only (development builds with prebuild); the React Native CLI isn't supported.
|
|
24
|
+
|
|
25
|
+
Skia: either version works; install one, not both.
|
|
26
|
+
|
|
27
|
+
| Skia | Package | Renderer |
|
|
28
|
+
| ---- | ------------------------------------ | ------------------------ |
|
|
29
|
+
| v3 | `react-native-skia` (3.3+) | Graphite (Vulkan, Metal) |
|
|
30
|
+
| v2 | `@shopify/react-native-skia` (2.10+) | Ganesh (OpenGL, Metal) |
|
|
31
|
+
|
|
32
|
+
For v2, install `@shopify/react-native-skia` instead of `react-native-skia` above, at 2.10 or later: `expo install` picks 2.6.2 for SDK 57, which hands Skia objects to C++ differently (JSI host objects, not native state), so pin a newer one, e.g. `npx expo install @shopify/react-native-skia@2.14.0`. The config plugin reads which one the app depends on, and models are drawn in C++ with it.
|
|
33
|
+
|
|
34
|
+
### Cubism SDK for Native
|
|
35
|
+
|
|
36
|
+
The package doesn't include Live2D's Cubism SDK: its Core is proprietary, and
|
|
37
|
+
each app downloads it from Live2D, accepting
|
|
38
|
+
[Live2D's license terms](https://www.live2d.com/eula/live2d-proprietary-software-license-agreement_en.html).
|
|
39
|
+
1. Download it (it's checked against a SHA-256):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npx @airisu-dev/react-native-live2d-skia fetch-sdk --accept-license # or bunx, yarn, pnpm
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
It extracts to `./vendor/CubismSdkForNative` (change it with `--out`). Add `/vendor/` to `.gitignore`, so it's never in a public repo. On EAS Build,
|
|
46
|
+
run the same command in an `eas-build-post-install` script.
|
|
47
|
+
|
|
48
|
+
2. Point the config plugin at it, in `app.json`:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
"plugins": [["@airisu-dev/react-native-live2d-skia", { "cubismSdkPath": "./vendor/CubismSdkForNative" }]]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
3. `npx expo prebuild`, then build. A missing or unsupported SDK stops the build with the path it looked at.
|
|
55
|
+
|
|
56
|
+
Publishing an app built on the SDK may also need Live2D's
|
|
57
|
+
[Cubism SDK Release License](https://www.live2d.com/en/sdk/license/) (businesses above 10M JPY a year).
|
|
58
|
+
|
|
59
|
+
## Credits
|
|
60
|
+
|
|
61
|
+
Bootstrapped with [create-nitro-module](https://github.com/patrickkabwe/create-nitro-module).
|
|
62
|
+
|
|
63
|
+
## Contributing
|
|
64
|
+
|
|
65
|
+
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
project(Live2dSkia)
|
|
2
|
+
cmake_minimum_required(VERSION 3.9.0)
|
|
3
|
+
|
|
4
|
+
set (PACKAGE_NAME Live2dSkia)
|
|
5
|
+
set (CMAKE_VERBOSE_MAKEFILE ON)
|
|
6
|
+
set (CMAKE_CXX_STANDARD 20)
|
|
7
|
+
|
|
8
|
+
# Enable Raw Props parsing in react-native (for Nitro Views)
|
|
9
|
+
add_compile_options(-DRN_SERIALIZABLE_STATE=1)
|
|
10
|
+
|
|
11
|
+
# Cubism SDK for Native: proprietary, downloaded by each app. build.gradle
|
|
12
|
+
# passes its folder (and checks its version), see app.plugin.js.
|
|
13
|
+
if (NOT CUBISM_SDK_DIR OR NOT CUBISM_SDK_VERSION_NUMBER)
|
|
14
|
+
message(FATAL_ERROR "[react-native-live2d-skia] CUBISM_SDK_DIR isn't set: build through Gradle, "
|
|
15
|
+
"with live2dSkia.cubismSdkPath set by the react-native-live2d-skia config plugin.")
|
|
16
|
+
endif()
|
|
17
|
+
# The SDK's version, for cpp/cubism/CubismCompat.hpp.
|
|
18
|
+
add_compile_definitions(LIVE2D_SKIA_CUBISM_SDK=${CUBISM_SDK_VERSION_NUMBER})
|
|
19
|
+
|
|
20
|
+
# Cubism Core (closed source): the prebuilt static library.
|
|
21
|
+
set (CUBISM_CORE_DIR "${CUBISM_SDK_DIR}/Core")
|
|
22
|
+
set (CUBISM_CORE_LIB "${CUBISM_CORE_DIR}/lib/android/${ANDROID_ABI}/libLive2DCubismCore.a")
|
|
23
|
+
if (NOT EXISTS "${CUBISM_CORE_LIB}")
|
|
24
|
+
message(FATAL_ERROR "[react-native-live2d-skia] Cubism Core not found for ${ANDROID_ABI} at ${CUBISM_CORE_LIB}.")
|
|
25
|
+
endif()
|
|
26
|
+
add_library(Live2DCubismCore STATIC IMPORTED)
|
|
27
|
+
set_target_properties(Live2DCubismCore PROPERTIES IMPORTED_LOCATION "${CUBISM_CORE_LIB}")
|
|
28
|
+
|
|
29
|
+
# Cubism Native Framework (motions, physics, pose, ...): the source in the same
|
|
30
|
+
# SDK, so it always matches the Core.
|
|
31
|
+
# Its Rendering/<backend> folders are left out: we draw with Skia
|
|
32
|
+
# (see ../cpp/cubism/CubismRendererStub.cpp).
|
|
33
|
+
set (CUBISM_FRAMEWORK_DIR "${CUBISM_SDK_DIR}/Framework/src")
|
|
34
|
+
if (NOT EXISTS "${CUBISM_FRAMEWORK_DIR}/CubismFramework.cpp")
|
|
35
|
+
message(FATAL_ERROR "[react-native-live2d-skia] Cubism Native Framework not found at ${CUBISM_FRAMEWORK_DIR}.")
|
|
36
|
+
endif()
|
|
37
|
+
file(GLOB_RECURSE CUBISM_FRAMEWORK_SOURCES "${CUBISM_FRAMEWORK_DIR}/*.cpp")
|
|
38
|
+
list(FILTER CUBISM_FRAMEWORK_SOURCES EXCLUDE REGEX "/Rendering/[^/]+/")
|
|
39
|
+
add_library(CubismFramework STATIC ${CUBISM_FRAMEWORK_SOURCES})
|
|
40
|
+
target_include_directories(CubismFramework PUBLIC "${CUBISM_FRAMEWORK_DIR}" "${CUBISM_CORE_DIR}/include")
|
|
41
|
+
# Third-party code: don't flood the build log with its warnings.
|
|
42
|
+
target_compile_options(CubismFramework PRIVATE -w)
|
|
43
|
+
|
|
44
|
+
add_library(${PACKAGE_NAME} SHARED
|
|
45
|
+
src/main/cpp/cpp-adapter.cpp
|
|
46
|
+
../cpp/hybrid/HybridLive2dSkia.cpp
|
|
47
|
+
../cpp/hybrid/HybridLive2DModel.cpp
|
|
48
|
+
../cpp/cubism/CubismSetup.cpp
|
|
49
|
+
../cpp/cubism/CubismRendererStub.cpp
|
|
50
|
+
../cpp/cubism/Live2DUserModel.cpp
|
|
51
|
+
../cpp/cubism/Live2DUserModelAnimation.cpp
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/Live2dSkia+autolinking.cmake)
|
|
55
|
+
|
|
56
|
+
include_directories(
|
|
57
|
+
"src/main/cpp"
|
|
58
|
+
"../cpp/hybrid"
|
|
59
|
+
"../cpp/cubism"
|
|
60
|
+
"../cpp/drawing"
|
|
61
|
+
"${CUBISM_CORE_DIR}/include"
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# Draw in C++ onto Skia canvases (cpp/drawing/SkiaDrawer.cpp). librnskia.so doesn't
|
|
65
|
+
# export Skia, so link the same prebuilt libskia.a it's built from and use its
|
|
66
|
+
# headers and defines; objects cross over through virtual calls. build.gradle
|
|
67
|
+
# passes the folders of the Skia the app uses, v3 (Graphite) or v2 (Ganesh).
|
|
68
|
+
# Without them, models are drawn in JS (src/drawer.ts).
|
|
69
|
+
set (RN_SKIA_LIBS_ABI "${RN_SKIA_LIBS}/${ANDROID_ABI}")
|
|
70
|
+
if (RN_SKIA_DIR AND EXISTS "${RN_SKIA_LIBS_ABI}/libskia.a" AND EXISTS "${RN_SKIA_DIR}/cpp/api/JsiSkCanvas.h")
|
|
71
|
+
message(STATUS "react-native-live2d-skia: drawing with Skia in C++ (${RN_SKIA_DIR}, Graphite: ${RN_SKIA_GRAPHITE})")
|
|
72
|
+
add_library(skia STATIC IMPORTED)
|
|
73
|
+
set_target_properties(skia PROPERTIES IMPORTED_LOCATION "${RN_SKIA_LIBS_ABI}/libskia.a")
|
|
74
|
+
target_sources(${PACKAGE_NAME} PRIVATE ../cpp/drawing/SkiaDrawer.cpp ../cpp/drawing/MeshCache.cpp)
|
|
75
|
+
target_include_directories(${PACKAGE_NAME} PRIVATE
|
|
76
|
+
"${RN_SKIA_DIR}/cpp/skia"
|
|
77
|
+
"${RN_SKIA_DIR}/cpp/api"
|
|
78
|
+
"${RN_SKIA_DIR}/cpp/jsi"
|
|
79
|
+
"${RN_SKIA_DIR}/cpp/rnskia"
|
|
80
|
+
"${RN_SKIA_DIR}/cpp/rnskia/values"
|
|
81
|
+
"${RN_SKIA_DIR}/cpp/utils"
|
|
82
|
+
"${RN_SKIA_DIR}/cpp"
|
|
83
|
+
"${RN_SKIA_DIR}/android/cpp/rnskia-android"
|
|
84
|
+
"${RN_SKIA_DIR}/android/cpp/jni/include"
|
|
85
|
+
"${REACT_NATIVE_DIR}/ReactCommon"
|
|
86
|
+
"${REACT_NATIVE_DIR}/ReactCommon/callinvoker")
|
|
87
|
+
# Same as the Skia package's build: struct layouts must match.
|
|
88
|
+
target_compile_definitions(${PACKAGE_NAME} PRIVATE
|
|
89
|
+
LIVE2D_SKIA=1 SK_BUILD_FOR_ANDROID
|
|
90
|
+
SK_DISABLE_LEGACY_SHAPER_FACTORY SK_IMAGE_READ_PIXELS_DISABLE_LEGACY_API
|
|
91
|
+
FOLLY_NO_CONFIG=1 FOLLY_HAVE_CLOCK_GETTIME=1 FOLLY_HAVE_MEMRCHR=1
|
|
92
|
+
FOLLY_USE_LIBCPP=1 FOLLY_MOBILE=1 ON_ANDROID ONANDROID)
|
|
93
|
+
if (RN_SKIA_GRAPHITE)
|
|
94
|
+
target_include_directories(${PACKAGE_NAME} PRIVATE "${RN_SKIA_DIR}/cpp/dawn/include")
|
|
95
|
+
target_compile_definitions(${PACKAGE_NAME} PRIVATE SK_GRAPHITE)
|
|
96
|
+
else()
|
|
97
|
+
target_compile_definitions(${PACKAGE_NAME} PRIVATE SK_GL SK_GANESH)
|
|
98
|
+
endif()
|
|
99
|
+
set (LIVE2D_SKIA_LIBS skia)
|
|
100
|
+
else()
|
|
101
|
+
message(STATUS "react-native-live2d-skia: no Skia to draw with in C++, drawing in JS")
|
|
102
|
+
endif()
|
|
103
|
+
|
|
104
|
+
find_library(LOG_LIB log)
|
|
105
|
+
|
|
106
|
+
target_link_libraries(
|
|
107
|
+
${PACKAGE_NAME}
|
|
108
|
+
${LOG_LIB}
|
|
109
|
+
CubismFramework
|
|
110
|
+
Live2DCubismCore
|
|
111
|
+
${LIVE2D_SKIA_LIBS}
|
|
112
|
+
android # <-- Android core
|
|
113
|
+
)
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
buildscript {
|
|
2
|
+
repositories {
|
|
3
|
+
google()
|
|
4
|
+
mavenCentral()
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
dependencies {
|
|
8
|
+
classpath "com.android.tools.build:gradle:8.8.0"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
def reactNativeArchitectures() {
|
|
13
|
+
def value = rootProject.getProperties().get("reactNativeArchitectures")
|
|
14
|
+
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
def isNewArchitectureEnabled() {
|
|
18
|
+
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
apply plugin: "com.android.library"
|
|
22
|
+
apply plugin: 'org.jetbrains.kotlin.android'
|
|
23
|
+
apply from: '../nitrogen/generated/android/Live2dSkia+autolinking.gradle'
|
|
24
|
+
apply from: "./fix-prefab.gradle"
|
|
25
|
+
|
|
26
|
+
if (isNewArchitectureEnabled()) {
|
|
27
|
+
apply plugin: "com.facebook.react"
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Cubism SDK for Native: proprietary, so each app downloads it from Live2D and
|
|
31
|
+
// sets its folder (app.plugin.js writes live2dSkia.cubismSdkPath, relative to android/).
|
|
32
|
+
def findCubismSdk() {
|
|
33
|
+
def configured = System.getenv("LIVE2D_SKIA_CUBISM_SDK") ?: rootProject.findProperty("live2dSkia.cubismSdkPath")
|
|
34
|
+
if (!configured) {
|
|
35
|
+
throw new GradleException("[react-native-live2d-skia] Cubism SDK for Native isn't configured. Add the plugin to app.json: " +
|
|
36
|
+
"[\"@airisu-dev/react-native-live2d-skia\", { \"cubismSdkPath\": \"./vendor/CubismSdkForNative\" }], download the SDK with `@airisu-dev/react-native-live2d-skia fetch-sdk --accept-license` (through npx, bunx, yarn or pnpm), then prebuild.")
|
|
37
|
+
}
|
|
38
|
+
def dir = rootProject.file(configured)
|
|
39
|
+
def info = new File(dir, "cubism-info.yml")
|
|
40
|
+
if (!info.exists()) {
|
|
41
|
+
throw new GradleException("[react-native-live2d-skia] Cubism SDK for Native not found at ${dir} (no cubism-info.yml). " +
|
|
42
|
+
"Download it with `@airisu-dev/react-native-live2d-skia fetch-sdk --accept-license` (through npx, bunx, yarn or pnpm).")
|
|
43
|
+
}
|
|
44
|
+
def matcher = info.text =~ /(?m)^version:\s*(\S+)/
|
|
45
|
+
def version = matcher.find() ? matcher.group(1) : "unknown"
|
|
46
|
+
checkCubismSdkVersion(version, dir)
|
|
47
|
+
return [dir: dir.absolutePath.replace("\\", "/"), version: version]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// A Cubism SDK version as a number: major * 10000 + release * 100 + patch, so
|
|
51
|
+
// 5-r.4.1 is 50401 (a -beta suffix is ignored). Null if it isn't one.
|
|
52
|
+
def cubismSdkVersionNumber(String version) {
|
|
53
|
+
def m = version =~ /^(\d+)-r\.(\d+)(?:\.(\d+))?/
|
|
54
|
+
return m.find() ? m.group(1).toInteger() * 10000 + m.group(2).toInteger() * 100 + (m.group(3) ?: "0").toInteger() : null
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Listed versions (cubismSdk.versions in package.json) are supported. A newer
|
|
58
|
+
// release of a listed major only warns; anything else fails.
|
|
59
|
+
def checkCubismSdkVersion(String version, File dir) {
|
|
60
|
+
def listed = new groovy.json.JsonSlurper().parse(file("../package.json")).cubismSdk.versions.keySet()
|
|
61
|
+
if (listed.contains(version)) return
|
|
62
|
+
def number = cubismSdkVersionNumber(version)
|
|
63
|
+
def newestOfMajor = number == null ? null : listed.collect { cubismSdkVersionNumber(it) }
|
|
64
|
+
.findAll { it.intdiv(10000) == number.intdiv(10000) }.max()
|
|
65
|
+
if (newestOfMajor == null || number < newestOfMajor) {
|
|
66
|
+
throw new GradleException("[react-native-live2d-skia] Cubism SDK for Native ${version} at ${dir} isn't supported: use ${listed.join(', ')}.")
|
|
67
|
+
}
|
|
68
|
+
logger.warn("[react-native-live2d-skia] Cubism SDK for Native ${version} found, tested with ${listed.join(', ')}.")
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// The folder of a node package, as `from` resolves it. Null if it isn't installed.
|
|
72
|
+
def resolveNodePackage(String name, File from) {
|
|
73
|
+
def process = ["node", "-p",
|
|
74
|
+
"require('path').dirname(require.resolve(process.argv[1] + '/package.json', { paths: [process.argv[2]] }))",
|
|
75
|
+
name, from.absolutePath].execute()
|
|
76
|
+
def out = process.text.trim()
|
|
77
|
+
return process.waitFor() == 0 && out ? new File(out) : null
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Drawing in C++ onto Skia canvases (cpp/drawing/SkiaDrawer.cpp) needs the headers,
|
|
81
|
+
// defines and prebuilt libskia.a of the Skia the app uses: react-native-skia
|
|
82
|
+
// (v3, Graphite) or @shopify/react-native-skia (v2, Ganesh), as app.plugin.js
|
|
83
|
+
// found in the app's package.json (live2dSkia.skiaPackage). Resolved from the
|
|
84
|
+
// app, since a monorepo can have both installed. No arguments: drawn in JS.
|
|
85
|
+
def skiaCmakeArguments() {
|
|
86
|
+
def name = rootProject.findProperty("live2dSkia.skiaPackage")
|
|
87
|
+
if (!name) return []
|
|
88
|
+
def appDir = rootProject.projectDir.parentFile
|
|
89
|
+
def skiaDir = resolveNodePackage(name, appDir)
|
|
90
|
+
def graphite = name == "react-native-skia"
|
|
91
|
+
def libsDir = skiaDir ? resolveNodePackage(graphite ? "react-native-skia-graphite-android" : "react-native-skia-android", skiaDir) : null
|
|
92
|
+
def reactNativeDir = resolveNodePackage("react-native", appDir)
|
|
93
|
+
if (!skiaDir || !libsDir || !reactNativeDir) {
|
|
94
|
+
logger.warn("[react-native-live2d-skia] ${name} or its Android binaries not found from ${appDir}: drawing in JS.")
|
|
95
|
+
return []
|
|
96
|
+
}
|
|
97
|
+
return ["-DRN_SKIA_DIR=${skiaDir.absolutePath.replace("\\", "/")}",
|
|
98
|
+
"-DRN_SKIA_LIBS=${new File(libsDir, "libs").absolutePath.replace("\\", "/")}",
|
|
99
|
+
"-DRN_SKIA_GRAPHITE=${graphite ? "ON" : "OFF"}",
|
|
100
|
+
"-DREACT_NATIVE_DIR=${reactNativeDir.absolutePath.replace("\\", "/")}"]
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
def getExtOrDefault(name) {
|
|
104
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["Live2dSkia_" + name]
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
def getExtOrIntegerDefault(name) {
|
|
108
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["Live2dSkia_" + name]).toInteger()
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
android {
|
|
112
|
+
namespace "com.live2dskia"
|
|
113
|
+
|
|
114
|
+
ndkVersion getExtOrDefault("ndkVersion")
|
|
115
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
116
|
+
|
|
117
|
+
defaultConfig {
|
|
118
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
119
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
120
|
+
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
121
|
+
|
|
122
|
+
externalNativeBuild {
|
|
123
|
+
cmake {
|
|
124
|
+
cppFlags "-frtti -fexceptions -Wall -Wextra -fstack-protector-all"
|
|
125
|
+
def cubismSdk = findCubismSdk()
|
|
126
|
+
arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON",
|
|
127
|
+
"-DCUBISM_SDK_DIR=${cubismSdk.dir}",
|
|
128
|
+
"-DCUBISM_SDK_VERSION_NUMBER=${cubismSdkVersionNumber(cubismSdk.version)}", *skiaCmakeArguments()
|
|
129
|
+
abiFilters (*reactNativeArchitectures())
|
|
130
|
+
|
|
131
|
+
buildTypes {
|
|
132
|
+
debug {
|
|
133
|
+
cppFlags "-O1 -g"
|
|
134
|
+
}
|
|
135
|
+
release {
|
|
136
|
+
cppFlags "-O2"
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
externalNativeBuild {
|
|
144
|
+
cmake {
|
|
145
|
+
path "CMakeLists.txt"
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
packagingOptions {
|
|
150
|
+
excludes = [
|
|
151
|
+
"META-INF",
|
|
152
|
+
"META-INF/**",
|
|
153
|
+
"**/libc++_shared.so",
|
|
154
|
+
"**/libfbjni.so",
|
|
155
|
+
"**/libjsi.so",
|
|
156
|
+
"**/libfolly_json.so",
|
|
157
|
+
"**/libfolly_runtime.so",
|
|
158
|
+
"**/libglog.so",
|
|
159
|
+
"**/libhermes.so",
|
|
160
|
+
"**/libhermes-executor-debug.so",
|
|
161
|
+
"**/libhermes_executor.so",
|
|
162
|
+
"**/libreactnative.so",
|
|
163
|
+
"**/libreactnativejni.so",
|
|
164
|
+
"**/libturbomodulejsijni.so",
|
|
165
|
+
"**/libreact_nativemodule_core.so",
|
|
166
|
+
"**/libjscexecutor.so"
|
|
167
|
+
]
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
buildFeatures {
|
|
171
|
+
buildConfig true
|
|
172
|
+
prefab true
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
buildTypes {
|
|
176
|
+
release {
|
|
177
|
+
minifyEnabled false
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
lintOptions {
|
|
182
|
+
disable "GradleCompatible"
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
compileOptions {
|
|
186
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
187
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
sourceSets {
|
|
191
|
+
main {
|
|
192
|
+
if (isNewArchitectureEnabled()) {
|
|
193
|
+
java.srcDirs += [
|
|
194
|
+
// React Codegen files
|
|
195
|
+
"${project.buildDir}/generated/source/codegen/java"
|
|
196
|
+
]
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
repositories {
|
|
203
|
+
mavenCentral()
|
|
204
|
+
google()
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
dependencies {
|
|
209
|
+
// For < 0.71, this will be from the local maven repo
|
|
210
|
+
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
|
211
|
+
//noinspection GradleDynamicVersion
|
|
212
|
+
implementation "com.facebook.react:react-native:+"
|
|
213
|
+
|
|
214
|
+
implementation project(":react-native-nitro-modules")
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (isNewArchitectureEnabled()) {
|
|
218
|
+
react {
|
|
219
|
+
jsRootDir = file("../src/")
|
|
220
|
+
libraryName = "Live2dSkia"
|
|
221
|
+
codegenJavaPackageName = "com.live2dskia"
|
|
222
|
+
}
|
|
223
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
tasks.configureEach { task ->
|
|
2
|
+
// Make sure that we generate our prefab publication file only after having built the native library
|
|
3
|
+
// so that not a header publication file, but a full configuration publication will be generated, which
|
|
4
|
+
// will include the .so file
|
|
5
|
+
|
|
6
|
+
def prefabConfigurePattern = ~/^prefab(.+)ConfigurePackage$/
|
|
7
|
+
def matcher = task.name =~ prefabConfigurePattern
|
|
8
|
+
if (matcher.matches()) {
|
|
9
|
+
def variantName = matcher[0][1]
|
|
10
|
+
task.outputs.upToDateWhen { false }
|
|
11
|
+
task.dependsOn("externalNativeBuild${variantName}")
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
afterEvaluate {
|
|
16
|
+
def abis = reactNativeArchitectures()
|
|
17
|
+
rootProject.allprojects.each { proj ->
|
|
18
|
+
if (proj === rootProject) return
|
|
19
|
+
|
|
20
|
+
def dependsOnThisLib = proj.configurations.findAll { it.canBeResolved }.any { config ->
|
|
21
|
+
config.dependencies.any { dep ->
|
|
22
|
+
dep.group == project.group && dep.name == project.name
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (!dependsOnThisLib && proj != project) return
|
|
26
|
+
|
|
27
|
+
if (!proj.plugins.hasPlugin('com.android.application') && !proj.plugins.hasPlugin('com.android.library')) {
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
def variants = proj.android.hasProperty('applicationVariants') ? proj.android.applicationVariants : proj.android.libraryVariants
|
|
32
|
+
// Touch the prefab_config.json files to ensure that in ExternalNativeJsonGenerator.kt we will re-trigger the prefab CLI to
|
|
33
|
+
// generate a libnameConfig.cmake file that will contain our native library (.so).
|
|
34
|
+
// See this condition: https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ExternalNativeJsonGenerator.kt;l=207-219?q=createPrefabBuildSystemGlue
|
|
35
|
+
variants.all { variant ->
|
|
36
|
+
def variantName = variant.name
|
|
37
|
+
abis.each { abi ->
|
|
38
|
+
def searchDir = new File(proj.projectDir, ".cxx/${variantName}")
|
|
39
|
+
if (!searchDir.exists()) return
|
|
40
|
+
def matches = []
|
|
41
|
+
searchDir.eachDir { randomDir ->
|
|
42
|
+
def prefabFile = new File(randomDir, "${abi}/prefab_config.json")
|
|
43
|
+
if (prefabFile.exists()) matches << prefabFile
|
|
44
|
+
}
|
|
45
|
+
matches.each { prefabConfig ->
|
|
46
|
+
prefabConfig.setLastModified(System.currentTimeMillis())
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|