@aguacerowx/react-native 0.0.39 → 0.0.41

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.
Files changed (26) hide show
  1. package/ios/GridRenderLayer.swift +73 -29
  2. package/lib/commonjs/ios/GridRenderLayer.swift +73 -29
  3. package/lib/commonjs/package.json +1 -1
  4. package/lib/commonjs/src/WeatherLayerManager.js +0 -15
  5. package/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
  6. package/lib/module/ios/GridRenderLayer.swift +73 -29
  7. package/lib/module/lib/commonjs/package.json +1 -1
  8. package/lib/module/lib/commonjs/src/WeatherLayerManager.js +0 -15
  9. package/lib/module/lib/commonjs/src/WeatherLayerManager.js.map +1 -1
  10. package/lib/module/package.json +1 -1
  11. package/lib/module/src/WeatherLayerManager.js +0 -15
  12. package/lib/module/src/WeatherLayerManager.js.map +1 -1
  13. package/lib/typescript/src/WeatherLayerManager.d.ts.map +1 -1
  14. package/package.json +1 -1
  15. package/src/WeatherLayerManager.js +0 -16
  16. package/lib/module/lib/commonjs/ios/GridRenderLayerBridge.swift +0 -45
  17. package/lib/module/lib/commonjs/ios/GridRenderLayerManager.mm +0 -172
  18. package/lib/module/lib/commonjs/ios/GridRenderLayerView.h +0 -31
  19. package/lib/module/lib/commonjs/ios/GridRenderLayerView.m +0 -201
  20. package/lib/module/lib/commonjs/ios/InspectorDataCache.swift +0 -64
  21. package/lib/module/lib/commonjs/ios/InspectorModule.m +0 -10
  22. package/lib/module/lib/commonjs/ios/InspectorModule.swift +0 -113
  23. package/lib/module/lib/commonjs/ios/Shaders.metal +0 -320
  24. package/lib/module/lib/commonjs/ios/WeatherFrameProcessorModule.m +0 -16
  25. package/lib/module/lib/commonjs/ios/WeatherFrameProcessorModule.swift +0 -153
  26. package/lib/module/lib/commonjs/scripts/compile-shaders.sh +0 -39
@@ -1,320 +0,0 @@
1
- #include <metal_stdlib>
2
- using namespace metal;
3
-
4
- // Struct to match the vertex buffer layout in Swift
5
- struct Vertex {
6
- float2 position [[attribute(0)]];
7
- float2 texCoord [[attribute(1)]];
8
- };
9
-
10
- // Struct for passing data from vertex to fragment shader
11
- struct RasterizerData {
12
- float4 position [[position]];
13
- float2 texCoord;
14
- };
15
-
16
- // Uniforms passed from the CPU to the fragment shader
17
- struct FragmentUniforms {
18
- float opacity;
19
- float2 dataRange;
20
- float scale;
21
- float offset;
22
- float missingQuantized;
23
- float2 textureSize;
24
- int smoothing;
25
- int scaleType;
26
- int isPtype;
27
- int isMRMS;
28
- };
29
-
30
- // --- Vertex Shader (Unchanged) ---
31
- vertex RasterizerData vertex_main(const Vertex in [[stage_in]],
32
- constant float4x4 &mvp [[buffer(1)]]) {
33
- RasterizerData out;
34
- out.position = mvp * float4(in.position, 0.0, 1.0);
35
- out.texCoord = in.texCoord;
36
- return out;
37
- }
38
-
39
-
40
- // --- HELPER FUNCTIONS FOR FRAGMENT SHADER ---
41
-
42
- // Dequantizes a signed value (-127 to 127) into a physical value
43
- float dequantize_val(float q_val, constant FragmentUniforms &uniforms) {
44
- if (abs(q_val - uniforms.missingQuantized) < 0.5) {
45
- return -9999.0;
46
- }
47
- float intermediate = q_val * uniforms.scale + uniforms.offset;
48
- if (uniforms.scaleType == 1) { // 1 = sqrt
49
- return intermediate * abs(intermediate);
50
- }
51
- return intermediate;
52
- }
53
-
54
- // Samples texture, converts 0-255 to signed -128-127 range.
55
- // Returns a quantized value, or a large positive sentinel for missing data.
56
- float get_value(texture2d<float, access::sample> dataTexture, sampler dataSampler, float2 coord, constant FragmentUniforms &uniforms) {
57
- // Note: The sampler should be set to 'nearest' when calling this for ptype logic.
58
- float value_0_to_255 = dataTexture.sample(dataSampler, coord).r * 255.0;
59
- float val = value_0_to_255 - 128.0;
60
- float missing_in_texture_range_0_255 = uniforms.missingQuantized + 128.0;
61
- if (abs(value_0_to_255 - missing_in_texture_range_0_255) < 0.5) {
62
- return 99999.0; // Sentinel for "missing"
63
- }
64
- return val;
65
- }
66
-
67
- // Maps a physical value to a precipitation type category
68
- // Maps a physical value to a precipitation type category
69
- float get_ptype_from_physical(float val, constant FragmentUniforms &uniforms) { // ADD uniforms parameter
70
- if (val < 0.0) return -1.0;
71
-
72
- // Models: 0-100 rain, 100-200 snow, 200-300 freezing rain, 300-400 ice pellets
73
- if (val < 100.0) return 0.0;
74
- if (val < 200.0) return 1.0;
75
- if (val < 300.0) return 2.0;
76
- if (val < 400.0) return 3.0;
77
- return -1.0;
78
- }
79
-
80
- // --- Main Fragment Shader ---
81
- fragment float4 fragment_main(RasterizerData in [[stage_in]],
82
- constant FragmentUniforms &uniforms [[buffer(0)]],
83
- texture2d<float, access::sample> dataTexture [[texture(0)]],
84
- texture2d<float, access::sample> colormapTexture [[texture(1)]],
85
- sampler dataSampler [[sampler(0)]],
86
- sampler colormapSampler [[sampler(1)]])
87
- {
88
- float raw_value;
89
- float alpha_multiplier = 1.0; // Used for alpha feathering at data edges
90
-
91
- if (uniforms.smoothing == 0) { // Nearest neighbor
92
- float quantized_value = get_value(dataTexture, dataSampler, in.texCoord, uniforms);
93
- if (quantized_value >= 99999.0) {
94
- discard_fragment();
95
- }
96
- raw_value = dequantize_val(quantized_value, uniforms);
97
-
98
- } else { // Bilinear interpolation
99
- float2 texel_size = 1.0 / uniforms.textureSize;
100
- float2 tex_coord_in_texels = in.texCoord * uniforms.textureSize;
101
- float2 bl_texel_index = floor(tex_coord_in_texels - 0.5);
102
- float2 f = fract(tex_coord_in_texels - 0.5); // Interpolation factors
103
-
104
- // Coordinates of the 4 neighboring texels
105
- float2 v00_coord = (bl_texel_index + float2(0.5, 0.5)) * texel_size;
106
- float2 v10_coord = (bl_texel_index + float2(1.5, 0.5)) * texel_size;
107
- float2 v01_coord = (bl_texel_index + float2(0.5, 1.5)) * texel_size;
108
- float2 v11_coord = (bl_texel_index + float2(1.5, 1.5)) * texel_size;
109
-
110
- if (uniforms.isPtype == 1) {
111
- // --- ENHANCED PTYPE-SPECIFIC INTERPOLATION ---
112
- float v00 = dequantize_val(get_value(dataTexture, dataSampler, v00_coord, uniforms), uniforms);
113
- float v10 = dequantize_val(get_value(dataTexture, dataSampler, v10_coord, uniforms), uniforms);
114
- float v01 = dequantize_val(get_value(dataTexture, dataSampler, v01_coord, uniforms), uniforms);
115
- float v11 = dequantize_val(get_value(dataTexture, dataSampler, v11_coord, uniforms), uniforms);
116
-
117
- float p00 = get_ptype_from_physical(v00, uniforms);
118
- float p10 = get_ptype_from_physical(v10, uniforms);
119
- float p01 = get_ptype_from_physical(v01, uniforms);
120
- float p11 = get_ptype_from_physical(v11, uniforms);
121
-
122
- // Count unique valid precipitation types
123
- bool has_type_0 = false;
124
- bool has_type_1 = false;
125
- bool has_type_2 = false;
126
- bool has_type_3 = false;
127
- int valid_count = 0;
128
-
129
- if (p00 >= 0.0) {
130
- int ptype = int(p00);
131
- if (ptype == 0) has_type_0 = true;
132
- else if (ptype == 1) has_type_1 = true;
133
- else if (ptype == 2) has_type_2 = true;
134
- else if (ptype == 3) has_type_3 = true;
135
- valid_count++;
136
- }
137
- if (p10 >= 0.0) {
138
- int ptype = int(p10);
139
- if (ptype == 0) has_type_0 = true;
140
- else if (ptype == 1) has_type_1 = true;
141
- else if (ptype == 2) has_type_2 = true;
142
- else if (ptype == 3) has_type_3 = true;
143
- valid_count++;
144
- }
145
- if (p01 >= 0.0) {
146
- int ptype = int(p01);
147
- if (ptype == 0) has_type_0 = true;
148
- else if (ptype == 1) has_type_1 = true;
149
- else if (ptype == 2) has_type_2 = true;
150
- else if (ptype == 3) has_type_3 = true;
151
- valid_count++;
152
- }
153
- if (p11 >= 0.0) {
154
- int ptype = int(p11);
155
- if (ptype == 0) has_type_0 = true;
156
- else if (ptype == 1) has_type_1 = true;
157
- else if (ptype == 2) has_type_2 = true;
158
- else if (ptype == 3) has_type_3 = true;
159
- valid_count++;
160
- }
161
-
162
- if (valid_count == 0) discard_fragment();
163
-
164
- // Count how many unique types we have
165
- int unique_types = 0;
166
- if (has_type_0) unique_types++;
167
- if (has_type_1) unique_types++;
168
- if (has_type_2) unique_types++;
169
- if (has_type_3) unique_types++;
170
-
171
- if (unique_types == 1) {
172
- // ALL SAME TYPE - smooth interpolation across all valid pixels
173
- float total_value = 0.0;
174
- float total_weight = 0.0;
175
-
176
- if (p00 >= 0.0) {
177
- float weight = (1.0 - f.x) * (1.0 - f.y);
178
- total_value += v00 * weight;
179
- total_weight += weight;
180
- }
181
- if (p10 >= 0.0) {
182
- float weight = f.x * (1.0 - f.y);
183
- total_value += v10 * weight;
184
- total_weight += weight;
185
- }
186
- if (p01 >= 0.0) {
187
- float weight = (1.0 - f.x) * f.y;
188
- total_value += v01 * weight;
189
- total_weight += weight;
190
- }
191
- if (p11 >= 0.0) {
192
- float weight = f.x * f.y;
193
- total_value += v11 * weight;
194
- total_weight += weight;
195
- }
196
-
197
- if (total_weight <= 0.0) discard_fragment();
198
- raw_value = total_value / total_weight;
199
-
200
- } else {
201
- // MULTIPLE TYPES - weighted voting to determine dominant type
202
- float type_weight_0 = 0.0;
203
- float type_weight_1 = 0.0;
204
- float type_weight_2 = 0.0;
205
- float type_weight_3 = 0.0;
206
-
207
- if (p00 >= 0.0) {
208
- float w = (1.0 - f.x) * (1.0 - f.y);
209
- int ptype = int(p00);
210
- if (ptype == 0) type_weight_0 += w;
211
- else if (ptype == 1) type_weight_1 += w;
212
- else if (ptype == 2) type_weight_2 += w;
213
- else if (ptype == 3) type_weight_3 += w;
214
- }
215
- if (p10 >= 0.0) {
216
- float w = f.x * (1.0 - f.y);
217
- int ptype = int(p10);
218
- if (ptype == 0) type_weight_0 += w;
219
- else if (ptype == 1) type_weight_1 += w;
220
- else if (ptype == 2) type_weight_2 += w;
221
- else if (ptype == 3) type_weight_3 += w;
222
- }
223
- if (p01 >= 0.0) {
224
- float w = (1.0 - f.x) * f.y;
225
- int ptype = int(p01);
226
- if (ptype == 0) type_weight_0 += w;
227
- else if (ptype == 1) type_weight_1 += w;
228
- else if (ptype == 2) type_weight_2 += w;
229
- else if (ptype == 3) type_weight_3 += w;
230
- }
231
- if (p11 >= 0.0) {
232
- float w = f.x * f.y;
233
- int ptype = int(p11);
234
- if (ptype == 0) type_weight_0 += w;
235
- else if (ptype == 1) type_weight_1 += w;
236
- else if (ptype == 2) type_weight_2 += w;
237
- else if (ptype == 3) type_weight_3 += w;
238
- }
239
-
240
- // Find the type with the highest weight at this pixel location
241
- float max_type_weight = 0.0;
242
- float winning_type = -1.0;
243
- if (type_weight_0 > max_type_weight) { max_type_weight = type_weight_0; winning_type = 0.0; }
244
- if (type_weight_1 > max_type_weight) { max_type_weight = type_weight_1; winning_type = 1.0; }
245
- if (type_weight_2 > max_type_weight) { max_type_weight = type_weight_2; winning_type = 2.0; }
246
- if (type_weight_3 > max_type_weight) { max_type_weight = type_weight_3; winning_type = 3.0; }
247
-
248
- if (winning_type == -1.0) discard_fragment();
249
-
250
- // Now smoothly interpolate only among pixels of the winning type
251
- float total_value = 0.0;
252
- float total_weight = 0.0;
253
-
254
- if (p00 == winning_type) {
255
- float weight = (1.0 - f.x) * (1.0 - f.y);
256
- total_value += v00 * weight;
257
- total_weight += weight;
258
- }
259
- if (p10 == winning_type) {
260
- float weight = f.x * (1.0 - f.y);
261
- total_value += v10 * weight;
262
- total_weight += weight;
263
- }
264
- if (p01 == winning_type) {
265
- float weight = (1.0 - f.x) * f.y;
266
- total_value += v01 * weight;
267
- total_weight += weight;
268
- }
269
- if (p11 == winning_type) {
270
- float weight = f.x * f.y;
271
- total_value += v11 * weight;
272
- total_weight += weight;
273
- }
274
-
275
- if (total_weight <= 0.0) discard_fragment();
276
- raw_value = total_value / total_weight;
277
- }
278
-
279
- // Force full alpha to prevent dark borders between ptype regions
280
- alpha_multiplier = 1.0;
281
-
282
- } else {
283
- // --- STANDARD INTERPOLATION (CONTINUOUS) ---
284
- float v00_q = get_value(dataTexture, dataSampler, v00_coord, uniforms);
285
- float v10_q = get_value(dataTexture, dataSampler, v10_coord, uniforms);
286
- float v01_q = get_value(dataTexture, dataSampler, v01_coord, uniforms);
287
- float v11_q = get_value(dataTexture, dataSampler, v11_coord, uniforms);
288
-
289
- float total_value_q = 0.0;
290
- float total_weight = 0.0;
291
- if (v00_q < 99999.0) { float w = (1.0-f.x)*(1.0-f.y); total_value_q+=v00_q*w; total_weight+=w; }
292
- if (v10_q < 99999.0) { float w = f.x*(1.0-f.y); total_value_q+=v10_q*w; total_weight+=w; }
293
- if (v01_q < 99999.0) { float w = (1.0-f.x)*f.y; total_value_q+=v01_q*w; total_weight+=w; }
294
- if (v11_q < 99999.0) { float w = f.x*f.y; total_value_q+=v11_q*w; total_weight+=w; }
295
-
296
- if (total_weight <= 0.0) discard_fragment();
297
- raw_value = dequantize_val(total_value_q / total_weight, uniforms);
298
- alpha_multiplier = total_weight; // Feather the edges of the data
299
- }
300
- }
301
-
302
- // --- COMMON FINAL STEPS ---
303
-
304
- if (raw_value < uniforms.dataRange.x) {
305
- discard_fragment();
306
- }
307
-
308
- float colormap_coord = (raw_value - uniforms.dataRange.x) / (uniforms.dataRange.y - uniforms.dataRange.x);
309
- colormap_coord = clamp(colormap_coord, 0.0, 1.0);
310
-
311
- float4 color = colormapTexture.sample(colormapSampler, float2(colormap_coord, 0.5));
312
-
313
- // Discard if the colormap specifies transparency
314
- if (color.a < 0.1) {
315
- discard_fragment();
316
- }
317
-
318
- float final_alpha = color.a * uniforms.opacity * alpha_multiplier;
319
- return float4(color.rgb * final_alpha, final_alpha);
320
- }
@@ -1,16 +0,0 @@
1
- #import <React/RCTBridgeModule.h>
2
-
3
- @interface RCT_EXTERN_MODULE(WeatherFrameProcessorModule, NSObject)
4
-
5
- RCT_EXTERN_METHOD(processFrame:(NSDictionary *)options
6
- resolver:(RCTPromiseResolveBlock)resolve
7
- rejecter:(RCTPromiseRejectBlock)reject)
8
-
9
- RCT_EXTERN_METHOD(cancelAllFrames)
10
-
11
- + (BOOL)requiresMainQueueSetup
12
- {
13
- return NO;
14
- }
15
-
16
- @end
@@ -1,153 +0,0 @@
1
- import Foundation
2
- import React
3
-
4
- @objc(WeatherFrameProcessorModule)
5
- class WeatherFrameProcessorModule: NSObject {
6
-
7
- private var currentRunToken = 0
8
- private let session = URLSession(configuration: .default)
9
-
10
- // MARK: - Performance Helper
11
- private func getMemoryUsage() -> String {
12
- var taskInfo = mach_task_basic_info()
13
- var count = mach_msg_type_number_t(MemoryLayout<mach_task_basic_info>.size)/4
14
- let kerr: kern_return_t = withUnsafeMutablePointer(to: &taskInfo) {
15
- $0.withMemoryRebound(to: integer_t.self, capacity: 1) {
16
- task_info(mach_task_self_, task_flavor_t(MACH_TASK_BASIC_INFO), $0, &count)
17
- }
18
- }
19
- if kerr == KERN_SUCCESS {
20
- let usedMB = Float(taskInfo.resident_size) / 1024.0 / 1024.0
21
- return String(format: "%.2f MB", usedMB)
22
- }
23
- return "Unknown"
24
- }
25
-
26
- @objc(cancelAllFrames)
27
- func cancelAllFrames() {
28
- print("⚡️ [PERF] [WeatherFrameProcessor] CancelAllFrames called. RAM: \(getMemoryUsage())")
29
- // Incrementing the token effectively cancels any in-flight tasks
30
- // as they will check their token against the new value upon completion.
31
- currentRunToken += 1
32
- }
33
-
34
- @objc(processFrame:resolver:rejecter:)
35
- func processFrame(options: [String: Any], resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
36
- let taskToken = self.currentRunToken
37
- let startTime = CFAbsoluteTimeGetCurrent()
38
-
39
- guard let urlString = options["url"] as? String, let url = URL(string: urlString) else {
40
- reject("INVALID_URL", "The provided URL is not valid.", nil)
41
- return
42
- }
43
-
44
- // Extract filename for log identification
45
- let fileId = url.lastPathComponent
46
- print("⚡️ [PERF] [WeatherFrameProcessor] START Fetch: \(fileId) | RAM: \(getMemoryUsage())")
47
-
48
- let apiKey = options["apiKey"] as? String ?? ""
49
- let bundleId = options["bundleId"] as? String
50
-
51
- var request = URLRequest(url: url)
52
- request.setValue(apiKey, forHTTPHeaderField: "x-api-key")
53
- if let bundleId = bundleId {
54
- request.setValue(bundleId, forHTTPHeaderField: "x-app-identifier")
55
- }
56
-
57
- let task = session.dataTask(with: request) { data, response, error in
58
- let fetchDuration = (CFAbsoluteTimeGetCurrent() - startTime) * 1000
59
-
60
- if self.currentRunToken != taskToken {
61
- print("⚡️ [PERF] [WeatherFrameProcessor] CANCELLED: \(fileId) after \(String(format: "%.2f", fetchDuration))ms")
62
- return
63
- }
64
-
65
- if let error = error {
66
- reject("NETWORK_ERROR", "Failed to fetch frame data: \(error.localizedDescription)", error)
67
- return
68
- }
69
-
70
- guard let httpResponse = response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else {
71
- let statusCode = (response as? HTTPURLResponse)?.statusCode ?? -1
72
- reject("HTTP_ERROR", "HTTP request failed with status code: \(statusCode)", nil)
73
- return
74
- }
75
-
76
- guard let data = data else {
77
- reject("NO_DATA", "The server returned no data.", nil)
78
- return
79
- }
80
-
81
- print("⚡️ [PERF] [WeatherFrameProcessor] NETWORK DONE: \(fileId) | Time: \(String(format: "%.2f", fetchDuration))ms | Size: \(data.count / 1024)KB | RAM: \(self.getMemoryUsage())")
82
-
83
- do {
84
- // 1. JSON Parsing
85
- let jsonStart = CFAbsoluteTimeGetCurrent()
86
- guard let jsonResponse = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
87
- reject("INVALID_RESPONSE", "The API response format was invalid JSON.", nil)
88
- return
89
- }
90
- let jsonTime = (CFAbsoluteTimeGetCurrent() - jsonStart) * 1000
91
-
92
- guard let b64CompressedData = jsonResponse["data"] as? String,
93
- let encoding = jsonResponse["encoding"] as? [String: Any],
94
- let scale = encoding["scale"] as? NSNumber,
95
- let offset = encoding["offset"] as? NSNumber,
96
- let missing = encoding["missing_quantized"] as? NSNumber else {
97
- reject("INVALID_RESPONSE", "The API response format was invalid structure.", nil)
98
- return
99
- }
100
-
101
- // 2. Base64 Decoding
102
- let decodeStart = CFAbsoluteTimeGetCurrent()
103
- guard let compressedData = Data(base64Encoded: b64CompressedData) else {
104
- reject("DECODING_ERROR", "Failed to decode base64 data string.", nil)
105
- return
106
- }
107
- let decodeTime = (CFAbsoluteTimeGetCurrent() - decodeStart) * 1000
108
-
109
- // 3. Disk Write
110
- let writeStart = CFAbsoluteTimeGetCurrent()
111
- let cacheDir = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
112
- let fileName = "frame_\(urlString.hashValue).zst"
113
- let dataFile = cacheDir.appendingPathComponent(fileName)
114
-
115
- try compressedData.write(to: dataFile)
116
- let writeTime = (CFAbsoluteTimeGetCurrent() - writeStart) * 1000
117
-
118
- var responseMap: [String: Any] = [
119
- "filePath": dataFile.path,
120
- "scale": scale,
121
- "offset": offset,
122
- "missing": missing,
123
- ]
124
-
125
- if let scaleType = encoding["scale_type"] as? String {
126
- responseMap["scaleType"] = scaleType
127
- }
128
-
129
- let totalTime = (CFAbsoluteTimeGetCurrent() - startTime) * 1000
130
-
131
- print("""
132
- ⚡️ [PERF] [WeatherFrameProcessor] FINISHED: \(fileId)
133
- - Total: \(String(format: "%.2f", totalTime))ms
134
- - JSON: \(String(format: "%.2f", jsonTime))ms
135
- - B64 Decode: \(String(format: "%.2f", decodeTime))ms
136
- - Disk Write: \(String(format: "%.2f", writeTime))ms
137
- - RAM End: \(self.getMemoryUsage())
138
- """)
139
-
140
- resolve(responseMap)
141
-
142
- } catch {
143
- reject("PROCESSING_ERROR", "Failed to process the frame data: \(error.localizedDescription)", error)
144
- }
145
- }
146
- task.resume()
147
- }
148
-
149
- @objc
150
- static func requiresMainQueueSetup() -> Bool {
151
- return false
152
- }
153
- }
@@ -1,39 +0,0 @@
1
- #!/bin/bash
2
- set -e
3
-
4
- # Check if we're on macOS (Darwin)
5
- if [[ "$OSTYPE" != "darwin"* ]]; then
6
- echo "⏭️ Skipping shader compilation (macOS only, current OS: $OSTYPE)"
7
- exit 0
8
- fi
9
-
10
- # Check if xcrun is available
11
- if ! command -v xcrun &> /dev/null; then
12
- echo "⚠️ xcrun not found. Skipping shader compilation."
13
- exit 0
14
- fi
15
-
16
- echo "🔨 Compiling Metal shaders for all platforms..."
17
-
18
- SHADER_DIR="ios"
19
- OUTPUT_DIR="ios/compiled-shaders"
20
-
21
- # Create output directory
22
- mkdir -p "$OUTPUT_DIR"
23
-
24
- # Compile for iOS Device (arm64)
25
- echo " 📱 Compiling for iOS device..."
26
- xcrun -sdk iphoneos metal -c "$SHADER_DIR/Shaders.metal" -o "$OUTPUT_DIR/Shaders-device.air"
27
- xcrun -sdk iphoneos metallib "$OUTPUT_DIR/Shaders-device.air" -o "$OUTPUT_DIR/Shaders-device.metallib"
28
-
29
- # Compile for iOS Simulator (x86_64 + arm64)
30
- echo " 💻 Compiling for iOS simulator..."
31
- xcrun -sdk iphonesimulator metal -c "$SHADER_DIR/Shaders.metal" -o "$OUTPUT_DIR/Shaders-simulator.air"
32
- xcrun -sdk iphonesimulator metallib "$OUTPUT_DIR/Shaders-simulator.air" -o "$OUTPUT_DIR/Shaders-simulator.metallib"
33
-
34
- # Clean up intermediate files
35
- rm "$OUTPUT_DIR"/*.air
36
-
37
- echo "✅ Metal shaders compiled:"
38
- echo " - Device: $OUTPUT_DIR/Shaders-device.metallib"
39
- echo " - Simulator: $OUTPUT_DIR/Shaders-simulator.metallib"