@truewatchtech/cocos-sdk 0.1.0-alpha.4 → 0.1.0-alpha.7
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/README.md +49 -1
- package/bin/cli.cjs +48 -18
- package/bin/legacy-asset-hashes.json +32 -0
- package/bin/managed-assets.cjs +67 -0
- package/dist/creator2/core/client.d.ts +55 -7
- package/dist/creator2/core/client.d.ts.map +1 -1
- package/dist/creator2/core/client.js +74 -28
- package/dist/creator2/core/client.js.map +1 -1
- package/dist/creator2/core/index.d.ts +1 -1
- package/dist/creator2/core/index.d.ts.map +1 -1
- package/dist/creator2/core/index.js.map +1 -1
- package/dist/creator2/core/plugin-api.d.ts +15 -0
- package/dist/creator2/core/plugin-api.d.ts.map +1 -0
- package/dist/creator2/core/plugin-api.js +3 -0
- package/dist/creator2/core/plugin-api.js.map +1 -0
- package/dist/creator2/core/transport.d.ts +20 -0
- package/dist/creator2/core/transport.d.ts.map +1 -1
- package/dist/creator2/core/transport.js.map +1 -1
- package/dist/creator2/core/types.d.ts +0 -78
- package/dist/creator2/core/types.d.ts.map +1 -1
- package/dist/creator2/core/validation.d.ts +0 -11
- package/dist/creator2/core/validation.d.ts.map +1 -1
- package/dist/creator2/core/validation.js +0 -63
- package/dist/creator2/core/validation.js.map +1 -1
- package/dist/creator2/core/version.d.ts +1 -1
- package/dist/creator2/core/version.js +1 -1
- package/dist/creator2/creator2/auto.d.ts +1 -3
- package/dist/creator2/creator2/auto.d.ts.map +1 -1
- package/dist/creator2/creator2/auto.js +0 -25
- package/dist/creator2/creator2/auto.js.map +1 -1
- package/dist/creator2/creator2/index.d.ts +0 -7
- package/dist/creator2/creator2/index.d.ts.map +1 -1
- package/dist/creator2/creator2/index.js +1 -13
- package/dist/creator2/creator2/index.js.map +1 -1
- package/dist/creator2/creator2/transport.d.ts +0 -1
- package/dist/creator2/creator2/transport.d.ts.map +1 -1
- package/dist/creator2/creator2/transport.js +0 -4
- package/dist/creator2/creator2/transport.js.map +1 -1
- package/dist/creator3/core/client.d.ts +55 -7
- package/dist/creator3/core/client.d.ts.map +1 -1
- package/dist/creator3/core/client.js +72 -28
- package/dist/creator3/core/client.js.map +1 -1
- package/dist/creator3/core/index.d.ts +1 -1
- package/dist/creator3/core/index.d.ts.map +1 -1
- package/dist/creator3/core/index.js.map +1 -1
- package/dist/creator3/core/plugin-api.d.ts +15 -0
- package/dist/creator3/core/plugin-api.d.ts.map +1 -0
- package/dist/creator3/core/plugin-api.js +2 -0
- package/dist/creator3/core/plugin-api.js.map +1 -0
- package/dist/creator3/core/transport.d.ts +20 -0
- package/dist/creator3/core/transport.d.ts.map +1 -1
- package/dist/creator3/core/transport.js.map +1 -1
- package/dist/creator3/core/types.d.ts +0 -78
- package/dist/creator3/core/types.d.ts.map +1 -1
- package/dist/creator3/core/validation.d.ts +0 -11
- package/dist/creator3/core/validation.d.ts.map +1 -1
- package/dist/creator3/core/validation.js +0 -61
- package/dist/creator3/core/validation.js.map +1 -1
- package/dist/creator3/core/version.d.ts +1 -1
- package/dist/creator3/core/version.js +1 -1
- package/dist/creator3/creator3/auto.d.ts +1 -3
- package/dist/creator3/creator3/auto.d.ts.map +1 -1
- package/dist/creator3/creator3/auto.js +1 -24
- package/dist/creator3/creator3/auto.js.map +1 -1
- package/dist/creator3/creator3/index.d.ts +0 -7
- package/dist/creator3/creator3/index.d.ts.map +1 -1
- package/dist/creator3/creator3/index.js +1 -12
- package/dist/creator3/creator3/index.js.map +1 -1
- package/dist/creator3/creator3/transport.d.ts +0 -1
- package/dist/creator3/creator3/transport.d.ts.map +1 -1
- package/dist/creator3/creator3/transport.js +0 -4
- package/dist/creator3/creator3/transport.js.map +1 -1
- package/extensions/creator2/install-native.cjs +118 -28
- package/extensions/creator2/install-spm.cjs +198 -0
- package/extensions/creator2/legacy-asset-hashes.json +32 -0
- package/extensions/creator2/managed-assets.cjs +67 -0
- package/extensions/creator3/install-native.cjs +118 -28
- package/extensions/creator3/install-spm.cjs +198 -0
- package/extensions/creator3/legacy-asset-hashes.json +32 -0
- package/extensions/creator3/managed-assets.cjs +67 -0
- package/native/android/src/main/java/com/ft/sdk/cocos/FTBridgeTransport.java +85 -0
- package/native/android/src/main/java/com/ft/sdk/cocos/FTCocosBridge.java +2 -192
- package/native/android/src/main/java/com/ft/sdk/cocos/FTCocosBridgeModules.java +9 -0
- package/native/android/src/main/java/com/ft/sdk/cocos/FTCocosBridgeProvider.java +1 -1
- package/native/ios/FTCocosBridge.m +8 -203
- package/native/ios/FTCocosBridge.podspec +3 -4
- package/native/ios/Package.swift +25 -0
- package/native/ios/include/FTCocosBridge.h +2 -0
- package/package.json +10 -5
- package/plugin-api/package.json +4 -0
- package/components/creator2/ReplayPrivacy.ts +0 -23
- package/components/creator3/ReplayPrivacy.ts +0 -25
- package/dist/creator2/core/replay-async-transport.d.ts +0 -4
- package/dist/creator2/core/replay-async-transport.d.ts.map +0 -1
- package/dist/creator2/core/replay-async-transport.js +0 -67
- package/dist/creator2/core/replay-async-transport.js.map +0 -1
- package/dist/creator2/core/replay-budget.d.ts +0 -28
- package/dist/creator2/core/replay-budget.d.ts.map +0 -1
- package/dist/creator2/core/replay-budget.js +0 -113
- package/dist/creator2/core/replay-budget.js.map +0 -1
- package/dist/creator2/core/replay-diagnostics.d.ts +0 -36
- package/dist/creator2/core/replay-diagnostics.d.ts.map +0 -1
- package/dist/creator2/core/replay-diagnostics.js +0 -40
- package/dist/creator2/core/replay-diagnostics.js.map +0 -1
- package/dist/creator2/core/replay-encoding.d.ts +0 -31
- package/dist/creator2/core/replay-encoding.d.ts.map +0 -1
- package/dist/creator2/core/replay-encoding.js +0 -63
- package/dist/creator2/core/replay-encoding.js.map +0 -1
- package/dist/creator2/core/replay-file.d.ts +0 -5
- package/dist/creator2/core/replay-file.d.ts.map +0 -1
- package/dist/creator2/core/replay-file.js +0 -101
- package/dist/creator2/core/replay-file.js.map +0 -1
- package/dist/creator2/core/replay-pixels.d.ts +0 -3
- package/dist/creator2/core/replay-pixels.d.ts.map +0 -1
- package/dist/creator2/core/replay-pixels.js +0 -16
- package/dist/creator2/core/replay-pixels.js.map +0 -1
- package/dist/creator2/core/replay-privacy-nodes.d.ts +0 -14
- package/dist/creator2/core/replay-privacy-nodes.d.ts.map +0 -1
- package/dist/creator2/core/replay-privacy-nodes.js +0 -18
- package/dist/creator2/core/replay-privacy-nodes.js.map +0 -1
- package/dist/creator2/core/replay-privacy.d.ts +0 -15
- package/dist/creator2/core/replay-privacy.d.ts.map +0 -1
- package/dist/creator2/core/replay-privacy.js +0 -36
- package/dist/creator2/core/replay-privacy.js.map +0 -1
- package/dist/creator2/core/replay.d.ts +0 -99
- package/dist/creator2/core/replay.d.ts.map +0 -1
- package/dist/creator2/core/replay.js +0 -611
- package/dist/creator2/core/replay.js.map +0 -1
- package/dist/creator2/creator2/capture.d.ts +0 -17
- package/dist/creator2/creator2/capture.d.ts.map +0 -1
- package/dist/creator2/creator2/capture.js +0 -168
- package/dist/creator2/creator2/capture.js.map +0 -1
- package/dist/creator3/core/replay-async-transport.d.ts +0 -4
- package/dist/creator3/core/replay-async-transport.d.ts.map +0 -1
- package/dist/creator3/core/replay-async-transport.js +0 -16
- package/dist/creator3/core/replay-async-transport.js.map +0 -1
- package/dist/creator3/core/replay-budget.d.ts +0 -28
- package/dist/creator3/core/replay-budget.d.ts.map +0 -1
- package/dist/creator3/core/replay-budget.js +0 -105
- package/dist/creator3/core/replay-budget.js.map +0 -1
- package/dist/creator3/core/replay-diagnostics.d.ts +0 -36
- package/dist/creator3/core/replay-diagnostics.d.ts.map +0 -1
- package/dist/creator3/core/replay-diagnostics.js +0 -36
- package/dist/creator3/core/replay-diagnostics.js.map +0 -1
- package/dist/creator3/core/replay-encoding.d.ts +0 -31
- package/dist/creator3/core/replay-encoding.d.ts.map +0 -1
- package/dist/creator3/core/replay-encoding.js +0 -62
- package/dist/creator3/core/replay-encoding.js.map +0 -1
- package/dist/creator3/core/replay-file.d.ts +0 -5
- package/dist/creator3/core/replay-file.d.ts.map +0 -1
- package/dist/creator3/core/replay-file.js +0 -31
- package/dist/creator3/core/replay-file.js.map +0 -1
- package/dist/creator3/core/replay-pixels.d.ts +0 -3
- package/dist/creator3/core/replay-pixels.d.ts.map +0 -1
- package/dist/creator3/core/replay-pixels.js +0 -13
- package/dist/creator3/core/replay-pixels.js.map +0 -1
- package/dist/creator3/core/replay-privacy-nodes.d.ts +0 -14
- package/dist/creator3/core/replay-privacy-nodes.d.ts.map +0 -1
- package/dist/creator3/core/replay-privacy-nodes.js +0 -15
- package/dist/creator3/core/replay-privacy-nodes.js.map +0 -1
- package/dist/creator3/core/replay-privacy.d.ts +0 -15
- package/dist/creator3/core/replay-privacy.d.ts.map +0 -1
- package/dist/creator3/core/replay-privacy.js +0 -33
- package/dist/creator3/core/replay-privacy.js.map +0 -1
- package/dist/creator3/core/replay.d.ts +0 -99
- package/dist/creator3/core/replay.d.ts.map +0 -1
- package/dist/creator3/core/replay.js +0 -534
- package/dist/creator3/core/replay.js.map +0 -1
- package/dist/creator3/creator3/capture.d.ts +0 -17
- package/dist/creator3/creator3/capture.d.ts.map +0 -1
- package/dist/creator3/creator3/capture.js +0 -112
- package/dist/creator3/creator3/capture.js.map +0 -1
- package/dist/creator3/creator3/replay-render-cycle.d.ts +0 -9
- package/dist/creator3/creator3/replay-render-cycle.d.ts.map +0 -1
- package/dist/creator3/creator3/replay-render-cycle.js +0 -12
- package/dist/creator3/creator3/replay-render-cycle.js.map +0 -1
- package/native/android/src/main/java/com/ft/sdk/cocos/FTCocosReplayImageJobs.java +0 -55
- package/native/ios/FTCocosReplayImageJobs.h +0 -11
- package/native/ios/FTCocosReplayImageJobs.m +0 -54
- package/native/shared/FTReplayFileBridge.h +0 -62
- package/native/shared/FTReplayFileWorker.h +0 -88
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { Camera, Director, EditBox, RenderTexture, UITransform, Vec3, director, native, sys, view } from 'cc';
|
|
2
|
-
import { frameFingerprint } from '../core/replay.js';
|
|
3
|
-
import { persistReplayFrame, disposeReplayFrame } from '../core/replay-file.js';
|
|
4
|
-
import { projectPrivacyBounds } from '../core/replay-privacy.js';
|
|
5
|
-
import { collectReplayPrivacyNodes } from '../core/replay-privacy-nodes.js';
|
|
6
|
-
import { waitForRenderTextureReadback } from './replay-render-cycle.js';
|
|
7
|
-
export class FTCreator3CanvasCapture {
|
|
8
|
-
constructor() {
|
|
9
|
-
this.privacy = new Map();
|
|
10
|
-
}
|
|
11
|
-
setCamera(camera) {
|
|
12
|
-
this.camera = camera;
|
|
13
|
-
}
|
|
14
|
-
setPrivacy(node, mode) {
|
|
15
|
-
if (mode === 'unmask')
|
|
16
|
-
this.privacy.delete(node);
|
|
17
|
-
else
|
|
18
|
-
this.privacy.set(node, mode);
|
|
19
|
-
}
|
|
20
|
-
getViewportSize() {
|
|
21
|
-
var _a;
|
|
22
|
-
const visible = ((_a = view.getVisibleSizeInPixel) === null || _a === void 0 ? void 0 : _a.call(view)) || view.getVisibleSize();
|
|
23
|
-
return visible ? { width: visible.width, height: visible.height } : undefined;
|
|
24
|
-
}
|
|
25
|
-
async capture(maxImageDimension) {
|
|
26
|
-
var _a, _b;
|
|
27
|
-
const camera = this.camera || ((_a = director.getScene()) === null || _a === void 0 ? void 0 : _a.getComponentInChildren(Camera));
|
|
28
|
-
if (!camera)
|
|
29
|
-
return undefined;
|
|
30
|
-
const visible = this.getViewportSize();
|
|
31
|
-
if (!visible)
|
|
32
|
-
return undefined;
|
|
33
|
-
const scale = Math.min(1, maxImageDimension / Math.max(visible.width, visible.height));
|
|
34
|
-
const width = Math.max(1, Math.round(visible.width * scale));
|
|
35
|
-
const height = Math.max(1, Math.round(visible.height * scale));
|
|
36
|
-
const texture = new RenderTexture();
|
|
37
|
-
texture.reset({ width, height });
|
|
38
|
-
const previous = camera.targetTexture;
|
|
39
|
-
let pixels;
|
|
40
|
-
let privacyRegions = [];
|
|
41
|
-
try {
|
|
42
|
-
camera.targetTexture = texture;
|
|
43
|
-
await waitForRenderTextureReadback(completeDrawCycle);
|
|
44
|
-
pixels = texture.readPixels(0, 0, width, height);
|
|
45
|
-
// worldToScreen uses the active render target dimensions. Keep the
|
|
46
|
-
// capture target attached so projection and pixels share one viewport.
|
|
47
|
-
if (pixels)
|
|
48
|
-
privacyRegions = this.collectPrivacyRegions(camera, width, height);
|
|
49
|
-
}
|
|
50
|
-
finally {
|
|
51
|
-
camera.targetTexture = previous;
|
|
52
|
-
texture.destroy();
|
|
53
|
-
}
|
|
54
|
-
if (!pixels)
|
|
55
|
-
return undefined;
|
|
56
|
-
// Metal returns top-down pixels on iOS. OpenGL/Vulkan-backed native
|
|
57
|
-
// targets use a bottom-left origin and need row reversal for PNG output.
|
|
58
|
-
if (sys.os !== ((_b = sys.OS) === null || _b === void 0 ? void 0 : _b.IOS))
|
|
59
|
-
flipRows(pixels, width, height);
|
|
60
|
-
return {
|
|
61
|
-
rgba: pixels,
|
|
62
|
-
width,
|
|
63
|
-
height,
|
|
64
|
-
timestamp: Date.now(),
|
|
65
|
-
privacyRegions,
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
async persist(frame, fingerprint = frameFingerprint(frame.rgba)) {
|
|
69
|
-
return persistReplayFrame(frame, fingerprint, native.fileUtils.getWritablePath());
|
|
70
|
-
}
|
|
71
|
-
disposeStoredFrame(frame) {
|
|
72
|
-
return disposeReplayFrame(frame);
|
|
73
|
-
}
|
|
74
|
-
collectPrivacyRegions(camera, width, height) {
|
|
75
|
-
const scene = director.getScene();
|
|
76
|
-
const nodes = collectReplayPrivacyNodes(this.privacy, (scene === null || scene === void 0 ? void 0 : scene.getComponentsInChildren('ReplayPrivacy')) || [], (scene === null || scene === void 0 ? void 0 : scene.getComponentsInChildren(EditBox)) || []);
|
|
77
|
-
const regions = [];
|
|
78
|
-
nodes.forEach((mode, node) => {
|
|
79
|
-
var _a, _b, _c, _d;
|
|
80
|
-
const bounds = (_c = (_b = (_a = node === null || node === void 0 ? void 0 : node.getComponent) === null || _a === void 0 ? void 0 : _a.call(node, UITransform)) === null || _b === void 0 ? void 0 : _b.getBoundingBoxToWorld) === null || _c === void 0 ? void 0 : _c.call(_b);
|
|
81
|
-
if (!bounds)
|
|
82
|
-
return;
|
|
83
|
-
const worldZ = ((_d = node.worldPosition) === null || _d === void 0 ? void 0 : _d.z) || 0;
|
|
84
|
-
const projected = projectPrivacyBounds(bounds, width, height, width, height, (x, y) => { var _a; return (_a = camera.worldToScreen) === null || _a === void 0 ? void 0 : _a.call(camera, new Vec3(x, y, worldZ)); });
|
|
85
|
-
if (!projected)
|
|
86
|
-
throw new Error('Unable to project Replay privacy bounds');
|
|
87
|
-
regions.push({ ...projected, mode: mode === 'hide' ? 'hide' : 'mask' });
|
|
88
|
-
});
|
|
89
|
-
return regions;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
async function completeDrawCycle() {
|
|
93
|
-
// capture() may run after the current frame's render graph has already been
|
|
94
|
-
// prepared. Waiting only for EVENT_AFTER_DRAW can then read the newly bound
|
|
95
|
-
// RenderTexture before the camera has rendered into it, producing a black
|
|
96
|
-
// FullSnapshot at a Native -> Cocos boundary. Start at the next draw boundary
|
|
97
|
-
// so the target texture is guaranteed to participate in a complete frame.
|
|
98
|
-
await new Promise((resolve) => director.once(Director.EVENT_BEFORE_DRAW, resolve));
|
|
99
|
-
await new Promise((resolve) => director.once(Director.EVENT_AFTER_DRAW, resolve));
|
|
100
|
-
}
|
|
101
|
-
function flipRows(bytes, width, height) {
|
|
102
|
-
const rowSize = width * 4;
|
|
103
|
-
const swap = new Uint8Array(rowSize);
|
|
104
|
-
for (let top = 0, bottom = height - 1; top < bottom; top += 1, bottom -= 1) {
|
|
105
|
-
const topOffset = top * rowSize;
|
|
106
|
-
const bottomOffset = bottom * rowSize;
|
|
107
|
-
swap.set(bytes.subarray(topOffset, topOffset + rowSize));
|
|
108
|
-
bytes.copyWithin(topOffset, bottomOffset, bottomOffset + rowSize);
|
|
109
|
-
bytes.set(swap, bottomOffset);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
//# sourceMappingURL=capture.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"capture.js","sourceRoot":"","sources":["../../../../../src/creator3/capture.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Waits until a newly attached native RenderTexture is safe to read back.
|
|
3
|
-
*
|
|
4
|
-
* Creator 3 can submit the first draw while the target attachment is still
|
|
5
|
-
* being applied by the native renderer. Keeping the target attached for a
|
|
6
|
-
* second complete draw prevents an empty first Session Replay snapshot.
|
|
7
|
-
*/
|
|
8
|
-
export declare function waitForRenderTextureReadback(drawCycle: () => Promise<void>): Promise<void>;
|
|
9
|
-
//# sourceMappingURL=replay-render-cycle.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"replay-render-cycle.d.ts","sourceRoot":"","sources":["../../../../../src/creator3/replay-render-cycle.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAsB,4BAA4B,CAAC,SAAS,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhG"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Waits until a newly attached native RenderTexture is safe to read back.
|
|
3
|
-
*
|
|
4
|
-
* Creator 3 can submit the first draw while the target attachment is still
|
|
5
|
-
* being applied by the native renderer. Keeping the target attached for a
|
|
6
|
-
* second complete draw prevents an empty first Session Replay snapshot.
|
|
7
|
-
*/
|
|
8
|
-
export async function waitForRenderTextureReadback(drawCycle) {
|
|
9
|
-
await drawCycle();
|
|
10
|
-
await drawCycle();
|
|
11
|
-
}
|
|
12
|
-
//# sourceMappingURL=replay-render-cycle.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"replay-render-cycle.js","sourceRoot":"","sources":["../../../../../src/creator3/replay-render-cycle.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,SAA8B;IAC/E,MAAM,SAAS,EAAE,CAAC;IAClB,MAAM,SAAS,EAAE,CAAC;AACpB,CAAC"}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
package com.ft.sdk.cocos;
|
|
2
|
-
|
|
3
|
-
import org.json.JSONObject;
|
|
4
|
-
import java.util.UUID;
|
|
5
|
-
import java.util.concurrent.ExecutorService;
|
|
6
|
-
import java.util.concurrent.Executors;
|
|
7
|
-
|
|
8
|
-
/** One image in flight across JS runtimes; the caller polls without waiting on disk/encoding. */
|
|
9
|
-
final class FTCocosReplayImageJobs {
|
|
10
|
-
private static final ExecutorService worker = Executors.newSingleThreadExecutor(runnable -> {
|
|
11
|
-
Thread thread = new Thread(runnable, "cocos-replay-image");
|
|
12
|
-
thread.setDaemon(true);
|
|
13
|
-
return thread;
|
|
14
|
-
});
|
|
15
|
-
private static Job current;
|
|
16
|
-
|
|
17
|
-
private static final class Job {
|
|
18
|
-
final String id = UUID.randomUUID().toString();
|
|
19
|
-
String response;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
static synchronized String begin(JSONObject arguments) throws Exception {
|
|
23
|
-
final String method = arguments.getString("method");
|
|
24
|
-
if (!"replay.saveImage".equals(method) && !"replay.saveImageV2".equals(method)) {
|
|
25
|
-
throw new IllegalArgumentException("Unsupported asynchronous Replay method");
|
|
26
|
-
}
|
|
27
|
-
final String payload = arguments.getJSONObject("arguments").toString();
|
|
28
|
-
if (current != null && current.response == null) throw new IllegalStateException("Replay encoder is busy");
|
|
29
|
-
final Job job = new Job();
|
|
30
|
-
current = job;
|
|
31
|
-
try {
|
|
32
|
-
worker.execute(() -> {
|
|
33
|
-
String response = FTCocosBridge.invokeLocal(method, payload);
|
|
34
|
-
synchronized (FTCocosReplayImageJobs.class) {
|
|
35
|
-
job.response = response;
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
} catch (RuntimeException error) {
|
|
39
|
-
current = null;
|
|
40
|
-
throw error;
|
|
41
|
-
}
|
|
42
|
-
return job.id;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
static synchronized JSONObject poll(String id) throws Exception {
|
|
46
|
-
if (current == null || !current.id.equals(id)) throw new IllegalArgumentException("Replay encoding job is unavailable");
|
|
47
|
-
JSONObject result = new JSONObject();
|
|
48
|
-
result.put("pending", current.response == null);
|
|
49
|
-
if (current.response != null) {
|
|
50
|
-
result.put("response", current.response);
|
|
51
|
-
current = null;
|
|
52
|
-
}
|
|
53
|
-
return result;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
#import <Foundation/Foundation.h>
|
|
2
|
-
|
|
3
|
-
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
-
|
|
5
|
-
/** One background image operation, with nonblocking result retrieval from JSB. */
|
|
6
|
-
@interface FTCocosReplayImageJobs : NSObject
|
|
7
|
-
+ (NSString *)beginWithWork:(NSString *(^)(void))work;
|
|
8
|
-
+ (NSDictionary *)poll:(NSString *)identifier;
|
|
9
|
-
@end
|
|
10
|
-
|
|
11
|
-
NS_ASSUME_NONNULL_END
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
#import "FTCocosReplayImageJobs.h"
|
|
2
|
-
|
|
3
|
-
@interface FTCocosReplayImageJob : NSObject
|
|
4
|
-
@property (nonatomic, copy) NSString *identifier;
|
|
5
|
-
@property (nonatomic, copy) NSString *response;
|
|
6
|
-
@end
|
|
7
|
-
@implementation FTCocosReplayImageJob
|
|
8
|
-
@end
|
|
9
|
-
|
|
10
|
-
static FTCocosReplayImageJob *currentJob;
|
|
11
|
-
|
|
12
|
-
@implementation FTCocosReplayImageJobs
|
|
13
|
-
|
|
14
|
-
+ (NSString *)beginWithWork:(NSString *(^)(void))work {
|
|
15
|
-
FTCocosReplayImageJob *job = [FTCocosReplayImageJob new];
|
|
16
|
-
job.identifier = NSUUID.UUID.UUIDString;
|
|
17
|
-
@synchronized (self) {
|
|
18
|
-
if (currentJob && !currentJob.response) {
|
|
19
|
-
[NSException raise:NSInternalInconsistencyException format:@"Replay encoder is busy"];
|
|
20
|
-
}
|
|
21
|
-
currentJob = job;
|
|
22
|
-
}
|
|
23
|
-
dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{
|
|
24
|
-
@autoreleasepool {
|
|
25
|
-
NSString *response;
|
|
26
|
-
@try {
|
|
27
|
-
response = work();
|
|
28
|
-
} @catch (NSException *exception) {
|
|
29
|
-
NSData *data = [NSJSONSerialization dataWithJSONObject:@{
|
|
30
|
-
@"ok": @NO, @"error": exception.reason ?: @"Replay encoding failed"
|
|
31
|
-
} options:0 error:nil];
|
|
32
|
-
response = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
|
33
|
-
}
|
|
34
|
-
@synchronized (self) {
|
|
35
|
-
job.response = response ?: @"{\"ok\":false,\"error\":\"Empty Replay encoding result\"}";
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
return job.identifier;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
+ (NSDictionary *)poll:(NSString *)identifier {
|
|
43
|
-
@synchronized (self) {
|
|
44
|
-
if (![currentJob.identifier isEqualToString:identifier]) {
|
|
45
|
-
[NSException raise:NSInvalidArgumentException format:@"Replay encoding job is unavailable"];
|
|
46
|
-
}
|
|
47
|
-
if (!currentJob.response) return @{ @"pending": @YES };
|
|
48
|
-
NSDictionary *result = @{ @"pending": @NO, @"response": currentJob.response };
|
|
49
|
-
currentJob = nil;
|
|
50
|
-
return result;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
@end
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
#if __has_include("bindings/jswrapper/SeApi.h")
|
|
4
|
-
#define FT_COCOS_CREATOR3 1
|
|
5
|
-
#include "bindings/jswrapper/SeApi.h"
|
|
6
|
-
#else
|
|
7
|
-
#include "cocos/scripting/js-bindings/jswrapper/SeApi.h"
|
|
8
|
-
#endif
|
|
9
|
-
#include "FTReplayFileWorker.h"
|
|
10
|
-
|
|
11
|
-
namespace ft_cocos {
|
|
12
|
-
|
|
13
|
-
static ReplayFileWorker replayFiles;
|
|
14
|
-
|
|
15
|
-
static bool writeReplayFile(se::State& state) {
|
|
16
|
-
const auto& args = state.args();
|
|
17
|
-
if (args.size() != 2 || !args[0].isObject() || !args[1].isString()) return false;
|
|
18
|
-
auto* object = args[0].toObject();
|
|
19
|
-
if (!object->isTypedArray()) return false;
|
|
20
|
-
uint8_t* bytes = nullptr;
|
|
21
|
-
size_t size = 0;
|
|
22
|
-
if (!object->getTypedArrayData(&bytes, &size)) return false;
|
|
23
|
-
state.rval().setBoolean(replayFiles.write(bytes, size, args[1].toString()));
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
26
|
-
SE_BIND_FUNC(writeReplayFile)
|
|
27
|
-
|
|
28
|
-
static bool pollReplayFile(se::State& state) {
|
|
29
|
-
state.rval().setString(replayFiles.poll());
|
|
30
|
-
return true;
|
|
31
|
-
}
|
|
32
|
-
SE_BIND_FUNC(pollReplayFile)
|
|
33
|
-
|
|
34
|
-
static bool removeReplayFile(se::State& state) {
|
|
35
|
-
const auto& args = state.args();
|
|
36
|
-
if (args.size() != 1 || !args[0].isString()) return false;
|
|
37
|
-
state.rval().setBoolean(replayFiles.remove(args[0].toString()));
|
|
38
|
-
return true;
|
|
39
|
-
}
|
|
40
|
-
SE_BIND_FUNC(removeReplayFile)
|
|
41
|
-
|
|
42
|
-
static bool registerReplayFileBridge(se::Object* global) {
|
|
43
|
-
replayFiles.cancel();
|
|
44
|
-
const se::HandleObject bridge(se::Object::createPlainObject());
|
|
45
|
-
bridge->defineFunction("write", _SE(writeReplayFile));
|
|
46
|
-
bridge->defineFunction("poll", _SE(pollReplayFile));
|
|
47
|
-
bridge->defineFunction("remove", _SE(removeReplayFile));
|
|
48
|
-
global->setProperty("__ftCocosReplayFile", se::Value(bridge));
|
|
49
|
-
se::ScriptEngine::getInstance()->addBeforeCleanupHook([]() { replayFiles.cancel(); });
|
|
50
|
-
return true;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
static void installReplayFileBridge() {
|
|
54
|
-
#if FT_COCOS_CREATOR3
|
|
55
|
-
se::ScriptEngine::getInstance()->addPermanentRegisterCallback(registerReplayFileBridge);
|
|
56
|
-
#else
|
|
57
|
-
// Creator 2 calls AppDelegate again when restarting its script VM.
|
|
58
|
-
se::ScriptEngine::getInstance()->addRegisterCallback(registerReplayFileBridge);
|
|
59
|
-
#endif
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
} // namespace ft_cocos
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
#pragma once
|
|
2
|
-
|
|
3
|
-
#include <atomic>
|
|
4
|
-
#include <cerrno>
|
|
5
|
-
#include <cstdio>
|
|
6
|
-
#include <memory>
|
|
7
|
-
#include <string>
|
|
8
|
-
#include <thread>
|
|
9
|
-
#include <vector>
|
|
10
|
-
|
|
11
|
-
namespace ft_cocos {
|
|
12
|
-
|
|
13
|
-
// Accessed only by the script thread. Workers own their buffers and never touch JS.
|
|
14
|
-
class ReplayFileWorker {
|
|
15
|
-
enum Status { Pending, Written, Removed, Error };
|
|
16
|
-
struct Job {
|
|
17
|
-
std::string path;
|
|
18
|
-
std::atomic<Status> status{Pending};
|
|
19
|
-
std::atomic<bool> cancelled{false};
|
|
20
|
-
};
|
|
21
|
-
std::shared_ptr<Job> current;
|
|
22
|
-
|
|
23
|
-
public:
|
|
24
|
-
bool write(const unsigned char* bytes, size_t size, const std::string& path) {
|
|
25
|
-
if (current && current->cancelled.load() && current->status.load() != Pending) current.reset();
|
|
26
|
-
if (current || !bytes || size == 0 || size > 2048U * 2048U * 4U || path.empty()) return false;
|
|
27
|
-
try {
|
|
28
|
-
auto job = std::make_shared<Job>();
|
|
29
|
-
job->path = path;
|
|
30
|
-
// This bounded copy is necessary because the JS buffer can be collected/reused.
|
|
31
|
-
std::vector<unsigned char> pixels(bytes, bytes + size);
|
|
32
|
-
current = job;
|
|
33
|
-
std::thread([job](std::vector<unsigned char> data) {
|
|
34
|
-
FILE* file = std::fopen(job->path.c_str(), "wb");
|
|
35
|
-
bool ok = false;
|
|
36
|
-
if (file) {
|
|
37
|
-
const bool written = std::fwrite(data.data(), 1, data.size(), file) == data.size();
|
|
38
|
-
ok = std::fclose(file) == 0 && written;
|
|
39
|
-
}
|
|
40
|
-
if (!ok || job->cancelled.load()) std::remove(job->path.c_str());
|
|
41
|
-
job->status.store(ok ? Written : Error);
|
|
42
|
-
// Covers cleanup racing with the final status transition.
|
|
43
|
-
if (job->cancelled.load()) std::remove(job->path.c_str());
|
|
44
|
-
}, std::move(pixels)).detach();
|
|
45
|
-
} catch (...) {
|
|
46
|
-
current.reset();
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
return true;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
bool remove(const std::string& path) {
|
|
53
|
-
if (!current || current->path != path || current->status.load() != Written) return false;
|
|
54
|
-
auto job = current;
|
|
55
|
-
job->status.store(Pending);
|
|
56
|
-
try {
|
|
57
|
-
std::thread([job]() {
|
|
58
|
-
const bool ok = std::remove(job->path.c_str()) == 0 || errno == ENOENT;
|
|
59
|
-
job->status.store(ok ? Removed : Error);
|
|
60
|
-
}).detach();
|
|
61
|
-
} catch (...) {
|
|
62
|
-
job->status.store(Written);
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const char* poll() {
|
|
69
|
-
if (!current) return "error";
|
|
70
|
-
switch (current->status.load()) {
|
|
71
|
-
case Pending: return "pending";
|
|
72
|
-
case Written: return "written";
|
|
73
|
-
case Removed: current.reset(); return "removed";
|
|
74
|
-
case Error: current.reset(); return "error";
|
|
75
|
-
}
|
|
76
|
-
return "error";
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
void cancel() {
|
|
80
|
-
if (!current) return;
|
|
81
|
-
auto job = current;
|
|
82
|
-
job->cancelled.store(true);
|
|
83
|
-
if (job->status.load() == Written) remove(job->path);
|
|
84
|
-
// Keep the slot occupied until its worker exits, including across VM restarts.
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
} // namespace ft_cocos
|