@empty-sekai/sekai-custom-profile-sdk 0.3.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.
Files changed (130) hide show
  1. package/LICENSE +235 -0
  2. package/LICENSE-EXCEPTION +32 -0
  3. package/NOTICE +11 -0
  4. package/README.en.md +456 -0
  5. package/README.md +458 -0
  6. package/dist/allium_renderer_wasm.js +14 -0
  7. package/dist/allium_renderer_wasm.wasm +0 -0
  8. package/dist/authoring.d.ts +14 -0
  9. package/dist/authoring.js +34 -0
  10. package/dist/cache/glyphPersistentCache.d.ts +145 -0
  11. package/dist/cache/glyphPersistentCache.js +346 -0
  12. package/dist/cache/indexedDbGlyphRecordStore.d.ts +26 -0
  13. package/dist/cache/indexedDbGlyphRecordStore.js +214 -0
  14. package/dist/cache/sessionImageResourceCache.d.ts +39 -0
  15. package/dist/cache/sessionImageResourceCache.js +156 -0
  16. package/dist/emscripten.d.ts +11 -0
  17. package/dist/emscripten.js +1 -0
  18. package/dist/fontProvider.d.ts +36 -0
  19. package/dist/fontProvider.js +84 -0
  20. package/dist/fontSdfAtlas.d.ts +92 -0
  21. package/dist/fontSdfAtlas.js +296 -0
  22. package/dist/gpu/browserSemanticResources.d.ts +64 -0
  23. package/dist/gpu/browserSemanticResources.js +232 -0
  24. package/dist/gpu/generalTextRenderPlacement.d.ts +8 -0
  25. package/dist/gpu/generalTextRenderPlacement.js +131 -0
  26. package/dist/gpu/previewTransformTextureLayout.d.ts +1 -0
  27. package/dist/gpu/previewTransformTextureLayout.js +12 -0
  28. package/dist/gpu/semanticCommandGeometry.d.ts +21 -0
  29. package/dist/gpu/semanticCommandGeometry.js +226 -0
  30. package/dist/gpu/semanticCommandPlanner.d.ts +131 -0
  31. package/dist/gpu/semanticCommandPlanner.js +203 -0
  32. package/dist/gpu/semanticTextGlyphBridge.d.ts +3 -0
  33. package/dist/gpu/semanticTextGlyphBridge.js +22 -0
  34. package/dist/gpu/semanticWebglSceneRenderer.d.ts +70 -0
  35. package/dist/gpu/semanticWebglSceneRenderer.js +211 -0
  36. package/dist/gpu/slotRanges.d.ts +5 -0
  37. package/dist/gpu/slotRanges.js +14 -0
  38. package/dist/gpu/webglSdfAtlasTexture.d.ts +17 -0
  39. package/dist/gpu/webglSdfAtlasTexture.js +72 -0
  40. package/dist/gpu/webglSdfGlyphPipeline.d.ts +26 -0
  41. package/dist/gpu/webglSdfGlyphPipeline.js +267 -0
  42. package/dist/gpu/webglSemanticCommandExecutor.d.ts +79 -0
  43. package/dist/gpu/webglSemanticCommandExecutor.js +686 -0
  44. package/dist/index.d.ts +18 -0
  45. package/dist/index.js +8 -0
  46. package/dist/interaction/numericTextRegions.d.ts +46 -0
  47. package/dist/interaction/numericTextRegions.js +44 -0
  48. package/dist/localizationProvider.d.ts +33 -0
  49. package/dist/localizationProvider.js +74 -0
  50. package/dist/originPrebuiltSdfAtlasPackage.d.ts +39 -0
  51. package/dist/originPrebuiltSdfAtlasPackage.js +316 -0
  52. package/dist/prebuiltSdfAtlas.d.ts +36 -0
  53. package/dist/prebuiltSdfAtlas.js +261 -0
  54. package/dist/protocol.d.ts +456 -0
  55. package/dist/protocol.js +1 -0
  56. package/dist/renderer.d.ts +218 -0
  57. package/dist/renderer.js +641 -0
  58. package/dist/resourceProvider.d.ts +24 -0
  59. package/dist/resourceProvider.js +41 -0
  60. package/dist/telemetry/rendererTelemetry.d.ts +158 -0
  61. package/dist/telemetry/rendererTelemetry.js +232 -0
  62. package/dist/third-party/freetype/FTL.txt +169 -0
  63. package/dist/types/atlas.d.ts +90 -0
  64. package/dist/types/atlas.js +1 -0
  65. package/dist/types/authoring.d.ts +81 -0
  66. package/dist/types/authoring.js +1 -0
  67. package/dist/types/core.d.ts +128 -0
  68. package/dist/types/core.js +1 -0
  69. package/dist/types/freeType.d.ts +54 -0
  70. package/dist/types/freeType.js +13 -0
  71. package/dist/types/glyph.d.ts +33 -0
  72. package/dist/types/glyph.js +1 -0
  73. package/dist/types/layout.d.ts +25 -0
  74. package/dist/types/layout.js +1 -0
  75. package/dist/types/text.d.ts +28 -0
  76. package/dist/types/text.js +1 -0
  77. package/dist/worker/glyphWorkScheduler.d.ts +29 -0
  78. package/dist/worker/glyphWorkScheduler.js +107 -0
  79. package/dist/worker-client.d.ts +114 -0
  80. package/dist/worker-client.js +413 -0
  81. package/dist/worker.d.ts +1 -0
  82. package/dist/worker.js +708 -0
  83. package/package.json +46 -0
  84. package/src/atlas.rs +652 -0
  85. package/src/authoring.ts +42 -0
  86. package/src/authoring_runtime.rs +303 -0
  87. package/src/cache/glyphPersistentCache.ts +463 -0
  88. package/src/cache/indexedDbGlyphRecordStore.ts +238 -0
  89. package/src/cache/sessionImageResourceCache.ts +186 -0
  90. package/src/edt.rs +97 -0
  91. package/src/emscripten.ts +17 -0
  92. package/src/fontProvider.ts +127 -0
  93. package/src/fontSdfAtlas.ts +431 -0
  94. package/src/geometry.rs +149 -0
  95. package/src/glyph_plan.rs +226 -0
  96. package/src/gpu/browserSemanticResources.ts +294 -0
  97. package/src/gpu/generalTextRenderPlacement.ts +175 -0
  98. package/src/gpu/previewTransformTextureLayout.ts +12 -0
  99. package/src/gpu/semanticCommandGeometry.ts +260 -0
  100. package/src/gpu/semanticCommandPlanner.ts +280 -0
  101. package/src/gpu/semanticTextGlyphBridge.ts +35 -0
  102. package/src/gpu/semanticWebglSceneRenderer.ts +261 -0
  103. package/src/gpu/slotRanges.ts +15 -0
  104. package/src/gpu/webglSdfAtlasTexture.ts +69 -0
  105. package/src/gpu/webglSdfGlyphPipeline.ts +299 -0
  106. package/src/gpu/webglSemanticCommandExecutor.ts +739 -0
  107. package/src/index.ts +84 -0
  108. package/src/interaction/numericTextRegions.ts +80 -0
  109. package/src/layout.rs +1882 -0
  110. package/src/lib.rs +1443 -0
  111. package/src/localizationProvider.ts +113 -0
  112. package/src/main.rs +55 -0
  113. package/src/masterdata_runtime.rs +496 -0
  114. package/src/originPrebuiltSdfAtlasPackage.ts +403 -0
  115. package/src/prebuiltSdfAtlas.ts +306 -0
  116. package/src/protocol.ts +150 -0
  117. package/src/renderer.ts +792 -0
  118. package/src/resourceProvider.ts +69 -0
  119. package/src/scene.rs +665 -0
  120. package/src/telemetry/rendererTelemetry.ts +358 -0
  121. package/src/types/atlas.ts +80 -0
  122. package/src/types/authoring.ts +85 -0
  123. package/src/types/core.ts +110 -0
  124. package/src/types/freeType.ts +63 -0
  125. package/src/types/glyph.ts +33 -0
  126. package/src/types/layout.ts +28 -0
  127. package/src/types/text.ts +28 -0
  128. package/src/worker/glyphWorkScheduler.ts +130 -0
  129. package/src/worker-client.ts +484 -0
  130. package/src/worker.ts +895 -0
@@ -0,0 +1,42 @@
1
+ import {
2
+ RendererAuthoringDocument,
3
+ RendererWorkerClient,
4
+ type RendererWorkerClientOptions,
5
+ } from "./worker-client.js";
6
+ import type { AuthoringCheckpoint } from "./types/authoring.js";
7
+
8
+ /** Worker-backed authoring runtime for game-compatible custom-profile documents. */
9
+ export class BrowserAuthoringClient {
10
+ private destroyed = false;
11
+
12
+ private constructor(private readonly worker: RendererWorkerClient) {}
13
+
14
+ static async create(options: RendererWorkerClientOptions = {}): Promise<BrowserAuthoringClient> {
15
+ return new BrowserAuthoringClient(await RendererWorkerClient.create(options));
16
+ }
17
+
18
+ async createBlank(): Promise<RendererAuthoringDocument> {
19
+ this.assertAlive();
20
+ return this.worker.createAuthoringDocument();
21
+ }
22
+
23
+ async importProfile(profile: unknown): Promise<RendererAuthoringDocument> {
24
+ this.assertAlive();
25
+ return this.worker.createAuthoringDocument(profile);
26
+ }
27
+
28
+ async restoreCheckpoint(checkpoint: AuthoringCheckpoint): Promise<RendererAuthoringDocument> {
29
+ this.assertAlive();
30
+ return this.worker.restoreAuthoringDocument(checkpoint);
31
+ }
32
+
33
+ destroy(): void {
34
+ if (this.destroyed) return;
35
+ this.destroyed = true;
36
+ this.worker.terminate();
37
+ }
38
+
39
+ private assertAlive(): void {
40
+ if (this.destroyed) throw new Error("Browser authoring client is destroyed");
41
+ }
42
+ }
@@ -0,0 +1,303 @@
1
+ use std::cell::RefCell;
2
+ use std::collections::BTreeMap;
3
+
4
+ use allium_renderer_core::authoring_document::GameProfileDocument;
5
+ use allium_renderer_core::authoring_session::{
6
+ AuthoringCommand, AuthoringElementId, AuthoringSession,
7
+ };
8
+ use serde::{Deserialize, Serialize};
9
+ use serde_json::Value;
10
+
11
+ thread_local! {
12
+ static SESSIONS: RefCell<SessionTable> = RefCell::new(SessionTable::default());
13
+ }
14
+
15
+ #[derive(Default)]
16
+ struct SessionTable {
17
+ next_handle: u32,
18
+ sessions: BTreeMap<u32, AuthoringSession>,
19
+ }
20
+
21
+ #[derive(Serialize)]
22
+ #[serde(rename_all = "camelCase")]
23
+ struct CreateResponse {
24
+ handle: u32,
25
+ revision: u64,
26
+ document: Value,
27
+ }
28
+
29
+ pub fn create_blank() -> Result<String, String> {
30
+ create(GameProfileDocument::blank())
31
+ }
32
+
33
+ pub fn import_profile(input: &str) -> Result<String, String> {
34
+ let value = serde_json::from_str(input)
35
+ .map_err(|error| format!("parse game profile failed: {error}"))?;
36
+ let document =
37
+ GameProfileDocument::from_profile_value(value).map_err(|error| error.to_string())?;
38
+ create(document)
39
+ }
40
+
41
+ pub fn restore_checkpoint(input: &str) -> Result<String, String> {
42
+ let value = serde_json::from_str(input)
43
+ .map_err(|error| format!("parse authoring checkpoint failed: {error}"))?;
44
+ let session =
45
+ AuthoringSession::from_checkpoint_value(value).map_err(|error| error.to_string())?;
46
+ create_session(session)
47
+ }
48
+
49
+ fn create(document: GameProfileDocument) -> Result<String, String> {
50
+ create_session(AuthoringSession::new(document))
51
+ }
52
+
53
+ fn create_session(session: AuthoringSession) -> Result<String, String> {
54
+ SESSIONS.with(|table| {
55
+ let mut table = table.borrow_mut();
56
+ table.next_handle = table.next_handle.wrapping_add(1).max(1);
57
+ let handle = table.next_handle;
58
+ let response = CreateResponse {
59
+ handle,
60
+ revision: session.revision(),
61
+ document: session.export_value(),
62
+ };
63
+ table.sessions.insert(handle, session);
64
+ serde_json::to_string(&response).map_err(|error| error.to_string())
65
+ })
66
+ }
67
+
68
+ pub fn apply(handle: u32, input: &str) -> Result<String, String> {
69
+ let command: AuthoringCommand = serde_json::from_str(input)
70
+ .map_err(|error| format!("parse authoring command failed: {error}"))?;
71
+ with_session(handle, |session| {
72
+ let delta = session.apply(command).map_err(|error| error.to_string())?;
73
+ serde_json::to_string(&delta).map_err(|error| error.to_string())
74
+ })
75
+ }
76
+
77
+ #[derive(Deserialize)]
78
+ struct ElementRequest {
79
+ id: AuthoringElementId,
80
+ }
81
+
82
+ #[derive(Deserialize)]
83
+ struct SelectionRequest {
84
+ id: Option<AuthoringElementId>,
85
+ }
86
+
87
+ #[derive(Deserialize)]
88
+ struct PageRequest {
89
+ page: usize,
90
+ }
91
+
92
+ #[derive(Deserialize)]
93
+ #[serde(rename_all = "camelCase")]
94
+ struct MovePageRequest {
95
+ from_page: usize,
96
+ page: usize,
97
+ }
98
+
99
+ pub fn select(handle: u32, input: &str) -> Result<String, String> {
100
+ let request: SelectionRequest = serde_json::from_str(input)
101
+ .map_err(|error| format!("parse authoring selection failed: {error}"))?;
102
+ with_session(handle, |session| {
103
+ serde_json::to_string(
104
+ &session
105
+ .select(request.id)
106
+ .map_err(|error| error.to_string())?,
107
+ )
108
+ .map_err(|error| error.to_string())
109
+ })
110
+ }
111
+
112
+ pub fn elements(handle: u32) -> Result<String, String> {
113
+ with_session(handle, |session| {
114
+ serde_json::to_string(&session.list_elements()).map_err(|error| error.to_string())
115
+ })
116
+ }
117
+
118
+ pub fn begin_gesture(handle: u32, input: &str) -> Result<String, String> {
119
+ let request: ElementRequest = serde_json::from_str(input)
120
+ .map_err(|error| format!("parse authoring gesture failed: {error}"))?;
121
+ with_session(handle, |session| {
122
+ serde_json::to_string(
123
+ &session
124
+ .begin_gesture(request.id)
125
+ .map_err(|error| error.to_string())?,
126
+ )
127
+ .map_err(|error| error.to_string())
128
+ })
129
+ }
130
+
131
+ pub fn preview_gesture(handle: u32, input: &str) -> Result<String, String> {
132
+ let command: AuthoringCommand = serde_json::from_str(input)
133
+ .map_err(|error| format!("parse authoring gesture command failed: {error}"))?;
134
+ with_session(handle, |session| {
135
+ serde_json::to_string(
136
+ &session
137
+ .preview_gesture(command)
138
+ .map_err(|error| error.to_string())?,
139
+ )
140
+ .map_err(|error| error.to_string())
141
+ })
142
+ }
143
+
144
+ pub fn commit_gesture(handle: u32) -> Result<String, String> {
145
+ with_session(handle, |session| {
146
+ serde_json::to_string(
147
+ &session
148
+ .commit_gesture()
149
+ .map_err(|error| error.to_string())?,
150
+ )
151
+ .map_err(|error| error.to_string())
152
+ })
153
+ }
154
+
155
+ pub fn cancel_gesture(handle: u32) -> Result<String, String> {
156
+ with_session(handle, |session| {
157
+ serde_json::to_string(
158
+ &session
159
+ .cancel_gesture()
160
+ .map_err(|error| error.to_string())?,
161
+ )
162
+ .map_err(|error| error.to_string())
163
+ })
164
+ }
165
+
166
+ pub fn append_page(handle: u32) -> Result<String, String> {
167
+ with_session(handle, |session| {
168
+ serde_json::to_string(
169
+ &session
170
+ .append_blank_page()
171
+ .map_err(|error| error.to_string())?,
172
+ )
173
+ .map_err(|error| error.to_string())
174
+ })
175
+ }
176
+
177
+ pub fn duplicate_page(handle: u32, input: &str) -> Result<String, String> {
178
+ let request: PageRequest = serde_json::from_str(input)
179
+ .map_err(|error| format!("parse authoring page failed: {error}"))?;
180
+ with_session(handle, |session| {
181
+ serde_json::to_string(
182
+ &session
183
+ .duplicate_page(request.page)
184
+ .map_err(|error| error.to_string())?,
185
+ )
186
+ .map_err(|error| error.to_string())
187
+ })
188
+ }
189
+
190
+ pub fn delete_page(handle: u32, input: &str) -> Result<String, String> {
191
+ let request: PageRequest = serde_json::from_str(input)
192
+ .map_err(|error| format!("parse authoring page failed: {error}"))?;
193
+ with_session(handle, |session| {
194
+ serde_json::to_string(
195
+ &session
196
+ .delete_page(request.page)
197
+ .map_err(|error| error.to_string())?,
198
+ )
199
+ .map_err(|error| error.to_string())
200
+ })
201
+ }
202
+
203
+ pub fn move_page(handle: u32, input: &str) -> Result<String, String> {
204
+ let request: MovePageRequest = serde_json::from_str(input)
205
+ .map_err(|error| format!("parse authoring page move failed: {error}"))?;
206
+ with_session(handle, |session| {
207
+ serde_json::to_string(
208
+ &session
209
+ .move_page(request.from_page, request.page)
210
+ .map_err(|error| error.to_string())?,
211
+ )
212
+ .map_err(|error| error.to_string())
213
+ })
214
+ }
215
+
216
+ pub fn undo(handle: u32) -> Result<String, String> {
217
+ with_session(handle, |session| {
218
+ serde_json::to_string(&session.undo().map_err(|error| error.to_string())?)
219
+ .map_err(|error| error.to_string())
220
+ })
221
+ }
222
+
223
+ pub fn redo(handle: u32) -> Result<String, String> {
224
+ with_session(handle, |session| {
225
+ serde_json::to_string(&session.redo().map_err(|error| error.to_string())?)
226
+ .map_err(|error| error.to_string())
227
+ })
228
+ }
229
+
230
+ pub fn export(handle: u32) -> Result<String, String> {
231
+ with_session(handle, |session| {
232
+ serde_json::to_string(&session.export_value()).map_err(|error| error.to_string())
233
+ })
234
+ }
235
+
236
+ pub fn checkpoint(handle: u32) -> Result<String, String> {
237
+ with_session(handle, |session| {
238
+ serde_json::to_string(
239
+ &session
240
+ .export_checkpoint_value()
241
+ .map_err(|error| error.to_string())?,
242
+ )
243
+ .map_err(|error| error.to_string())
244
+ })
245
+ }
246
+
247
+ pub fn destroy(handle: u32) -> bool {
248
+ SESSIONS.with(|table| table.borrow_mut().sessions.remove(&handle).is_some())
249
+ }
250
+
251
+ fn with_session<T>(
252
+ handle: u32,
253
+ call: impl FnOnce(&mut AuthoringSession) -> Result<T, String>,
254
+ ) -> Result<T, String> {
255
+ SESSIONS.with(|table| {
256
+ let mut table = table.borrow_mut();
257
+ let session = table
258
+ .sessions
259
+ .get_mut(&handle)
260
+ .ok_or_else(|| format!("unknown authoring session handle {handle}"))?;
261
+ call(session)
262
+ })
263
+ }
264
+
265
+ #[cfg(test)]
266
+ mod tests {
267
+ use super::*;
268
+ use serde_json::json;
269
+
270
+ #[test]
271
+ fn runtime_handle_applies_and_exports_without_browser_metadata() {
272
+ let created: Value = serde_json::from_str(&create_blank().unwrap()).unwrap();
273
+ let handle = created["handle"].as_u64().unwrap() as u32;
274
+ let command = json!({
275
+ "kind": "create",
276
+ "page": 0,
277
+ "category": "texts",
278
+ "element": {
279
+ "objectData": {
280
+ "position": {"x": 0.0, "y": 0.0, "z": 0.0},
281
+ "scale": {"x": 1.0, "y": 1.0, "z": 1.0},
282
+ "rotation": {"x": 0.0, "y": 0.0, "z": 0.0, "w": 1.0},
283
+ "layer": 0, "lock": false, "visible": true
284
+ },
285
+ "text": "请多关照!", "fontId": 1, "type": 513, "colorId": 1,
286
+ "size": 24.0, "outlineColorId": 1, "outlineSize": 0.0, "lineSpacing": 0.0
287
+ }
288
+ });
289
+ let delta: Value =
290
+ serde_json::from_str(&apply(handle, &command.to_string()).unwrap()).unwrap();
291
+ assert_eq!(delta["revision"], 1);
292
+ let exported: Value = serde_json::from_str(&export(handle).unwrap()).unwrap();
293
+ assert_eq!(
294
+ exported["userCustomProfileCards"][0]["customProfileCard"]["texts"]
295
+ .as_array()
296
+ .unwrap()
297
+ .len(),
298
+ 1
299
+ );
300
+ assert!(exported.get("handle").is_none());
301
+ assert!(destroy(handle));
302
+ }
303
+ }