@nayan-ui/engine 0.0.0-stage → 1.0.0-beta.3

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 (189) hide show
  1. package/LICENSE +21 -0
  2. package/NayanEngine.podspec +28 -0
  3. package/README.md +210 -2
  4. package/lib/module/assets/AssetBytesCache.js +76 -0
  5. package/lib/module/assets/AssetCache.js +19 -0
  6. package/lib/module/assets/AssetLoader.js +52 -0
  7. package/lib/module/assets/CacheGeneration.js +7 -0
  8. package/lib/module/assets/IndexedDbCache.web.js +149 -0
  9. package/lib/module/assets/ProceduralCache.js +222 -0
  10. package/lib/module/assets/font.js +136 -0
  11. package/lib/module/assets/loft.js +142 -0
  12. package/lib/module/assets/model.js +74 -0
  13. package/lib/module/assets/modelling.js +254 -0
  14. package/lib/module/assets/shape.js +926 -0
  15. package/lib/module/assets/source.js +58 -0
  16. package/lib/module/assets/source.web.js +22 -0
  17. package/lib/module/assets/storage.js +4 -0
  18. package/lib/module/assets/storage.shared.js +36 -0
  19. package/lib/module/assets/storage.web.js +37 -0
  20. package/lib/module/assets/surface.js +47 -0
  21. package/lib/module/assets/texture.js +66 -0
  22. package/lib/module/drawing/DrawingCanvas.js +38 -0
  23. package/lib/module/drawing/DrawingCanvas.web.js +206 -0
  24. package/lib/module/drawing/DrawingDocument.js +256 -0
  25. package/lib/module/drawing/types.js +4 -0
  26. package/lib/module/globals.d.ts +12 -0
  27. package/lib/module/index.js +36 -0
  28. package/lib/module/input/Joystick.js +84 -0
  29. package/lib/module/input/Joystick.web.js +93 -0
  30. package/lib/module/input/keyboard.js +250 -0
  31. package/lib/module/media/audio-worklet.js +34 -0
  32. package/lib/module/media/audio.js +94 -0
  33. package/lib/module/media/haptics.js +82 -0
  34. package/lib/module/media/output.web.js +66 -0
  35. package/lib/module/native/BrowserEngine.js +551 -0
  36. package/lib/module/native/EngineBridge.js +4 -0
  37. package/lib/module/native/NativeNayanEngine.js +7 -0
  38. package/lib/module/native/NativeNayanEngine.web.js +62 -0
  39. package/lib/module/native/prepare.js +7 -0
  40. package/lib/module/native/prepare.web.js +17 -0
  41. package/lib/module/native/spec/NativeNayanEngine.js +17 -0
  42. package/lib/module/package.json +1 -0
  43. package/lib/module/render/GameView.js +249 -0
  44. package/lib/module/render/camera.js +34 -0
  45. package/lib/module/render/host.js +39 -0
  46. package/lib/module/render/host.web.js +104 -0
  47. package/lib/module/render/meshes.js +159 -0
  48. package/lib/module/render/quality.js +112 -0
  49. package/lib/module/render/responder.js +4 -0
  50. package/lib/module/render/responder.web.js +97 -0
  51. package/lib/module/render/touch.js +185 -0
  52. package/lib/module/types.js +30 -0
  53. package/lib/module/world/Scoreboard.js +143 -0
  54. package/lib/module/world/TransformBatch.js +126 -0
  55. package/lib/module/world/World.js +690 -0
  56. package/lib/module/world/desc.js +186 -0
  57. package/lib/module/world/effects.js +451 -0
  58. package/lib/module/world/quat.js +86 -0
  59. package/lib/module/world/types.js +4 -0
  60. package/lib/typescript/package.json +1 -0
  61. package/lib/typescript/src/assets/AssetBytesCache.d.ts +7 -0
  62. package/lib/typescript/src/assets/AssetCache.d.ts +9 -0
  63. package/lib/typescript/src/assets/AssetLoader.d.ts +11 -0
  64. package/lib/typescript/src/assets/CacheGeneration.d.ts +3 -0
  65. package/lib/typescript/src/assets/IndexedDbCache.web.d.ts +20 -0
  66. package/lib/typescript/src/assets/ProceduralCache.d.ts +33 -0
  67. package/lib/typescript/src/assets/font.d.ts +53 -0
  68. package/lib/typescript/src/assets/loft.d.ts +31 -0
  69. package/lib/typescript/src/assets/model.d.ts +48 -0
  70. package/lib/typescript/src/assets/modelling.d.ts +157 -0
  71. package/lib/typescript/src/assets/shape.d.ts +203 -0
  72. package/lib/typescript/src/assets/source.d.ts +10 -0
  73. package/lib/typescript/src/assets/source.web.d.ts +8 -0
  74. package/lib/typescript/src/assets/storage.d.ts +2 -0
  75. package/lib/typescript/src/assets/storage.shared.d.ts +7 -0
  76. package/lib/typescript/src/assets/storage.web.d.ts +7 -0
  77. package/lib/typescript/src/assets/surface.d.ts +17 -0
  78. package/lib/typescript/src/assets/texture.d.ts +30 -0
  79. package/lib/typescript/src/drawing/DrawingCanvas.d.ts +5 -0
  80. package/lib/typescript/src/drawing/DrawingCanvas.web.d.ts +4 -0
  81. package/lib/typescript/src/drawing/DrawingDocument.d.ts +210 -0
  82. package/lib/typescript/src/drawing/types.d.ts +12 -0
  83. package/lib/typescript/src/index.d.ts +42 -0
  84. package/lib/typescript/src/input/Joystick.d.ts +20 -0
  85. package/lib/typescript/src/input/Joystick.web.d.ts +13 -0
  86. package/lib/typescript/src/input/keyboard.d.ts +17 -0
  87. package/lib/typescript/src/media/audio.d.ts +46 -0
  88. package/lib/typescript/src/media/haptics.d.ts +22 -0
  89. package/lib/typescript/src/media/output.web.d.ts +4 -0
  90. package/lib/typescript/src/native/BrowserEngine.d.ts +8 -0
  91. package/lib/typescript/src/native/EngineBridge.d.ts +22 -0
  92. package/lib/typescript/src/native/NativeNayanEngine.d.ts +5 -0
  93. package/lib/typescript/src/native/NativeNayanEngine.web.d.ts +10 -0
  94. package/lib/typescript/src/native/prepare.d.ts +3 -0
  95. package/lib/typescript/src/native/prepare.web.d.ts +2 -0
  96. package/lib/typescript/src/native/spec/NativeNayanEngine.d.ts +182 -0
  97. package/lib/typescript/src/render/GameView.d.ts +95 -0
  98. package/lib/typescript/src/render/camera.d.ts +6 -0
  99. package/lib/typescript/src/render/host.d.ts +29 -0
  100. package/lib/typescript/src/render/host.web.d.ts +16 -0
  101. package/lib/typescript/src/render/meshes.d.ts +45 -0
  102. package/lib/typescript/src/render/quality.d.ts +46 -0
  103. package/lib/typescript/src/render/responder.d.ts +2 -0
  104. package/lib/typescript/src/render/responder.web.d.ts +40 -0
  105. package/lib/typescript/src/render/touch.d.ts +26 -0
  106. package/lib/typescript/src/types.d.ts +72 -0
  107. package/lib/typescript/src/world/Scoreboard.d.ts +65 -0
  108. package/lib/typescript/src/world/TransformBatch.d.ts +39 -0
  109. package/lib/typescript/src/world/World.d.ts +199 -0
  110. package/lib/typescript/src/world/desc.d.ts +17 -0
  111. package/lib/typescript/src/world/effects.d.ts +156 -0
  112. package/lib/typescript/src/world/quat.d.ts +31 -0
  113. package/lib/typescript/src/world/types.d.ts +233 -0
  114. package/lib/web/audio-worklet.js +29 -0
  115. package/lib/web/engine_core_bg.wasm +0 -0
  116. package/lib/web/index.js +7974 -0
  117. package/lib/web/types/src/assets/AssetBytesCache.d.ts +6 -0
  118. package/lib/web/types/src/assets/AssetCache.d.ts +8 -0
  119. package/lib/web/types/src/assets/AssetLoader.d.ts +10 -0
  120. package/lib/web/types/src/assets/CacheGeneration.d.ts +2 -0
  121. package/lib/web/types/src/assets/IndexedDbCache.d.ts +19 -0
  122. package/lib/web/types/src/assets/ProceduralCache.d.ts +32 -0
  123. package/lib/web/types/src/assets/font.d.ts +52 -0
  124. package/lib/web/types/src/assets/loft.d.ts +30 -0
  125. package/lib/web/types/src/assets/model.d.ts +47 -0
  126. package/lib/web/types/src/assets/modelling.d.ts +156 -0
  127. package/lib/web/types/src/assets/shape.d.ts +202 -0
  128. package/lib/web/types/src/assets/source.d.ts +7 -0
  129. package/lib/web/types/src/assets/storage.d.ts +6 -0
  130. package/lib/web/types/src/assets/storage.shared.d.ts +6 -0
  131. package/lib/web/types/src/assets/surface.d.ts +16 -0
  132. package/lib/web/types/src/assets/texture.d.ts +29 -0
  133. package/lib/web/types/src/drawing/DrawingCanvas.d.ts +3 -0
  134. package/lib/web/types/src/drawing/DrawingDocument.d.ts +209 -0
  135. package/lib/web/types/src/drawing/types.d.ts +11 -0
  136. package/lib/web/types/src/index.d.ts +41 -0
  137. package/lib/web/types/src/input/Joystick.d.ts +12 -0
  138. package/lib/web/types/src/input/keyboard.d.ts +16 -0
  139. package/lib/web/types/src/media/audio.d.ts +45 -0
  140. package/lib/web/types/src/media/haptics.d.ts +21 -0
  141. package/lib/web/types/src/media/output.d.ts +3 -0
  142. package/lib/web/types/src/native/BrowserEngine.d.ts +7 -0
  143. package/lib/web/types/src/native/EngineBridge.d.ts +21 -0
  144. package/lib/web/types/src/native/NativeNayanEngine.d.ts +9 -0
  145. package/lib/web/types/src/native/prepare.d.ts +1 -0
  146. package/lib/web/types/src/native/spec/NativeNayanEngine.d.ts +181 -0
  147. package/lib/web/types/src/render/GameView.d.ts +94 -0
  148. package/lib/web/types/src/render/camera.d.ts +5 -0
  149. package/lib/web/types/src/render/host.d.ts +15 -0
  150. package/lib/web/types/src/render/meshes.d.ts +44 -0
  151. package/lib/web/types/src/render/quality.d.ts +45 -0
  152. package/lib/web/types/src/render/responder.d.ts +39 -0
  153. package/lib/web/types/src/render/touch.d.ts +25 -0
  154. package/lib/web/types/src/types.d.ts +71 -0
  155. package/lib/web/types/src/world/Scoreboard.d.ts +64 -0
  156. package/lib/web/types/src/world/TransformBatch.d.ts +38 -0
  157. package/lib/web/types/src/world/World.d.ts +198 -0
  158. package/lib/web/types/src/world/desc.d.ts +16 -0
  159. package/lib/web/types/src/world/effects.d.ts +155 -0
  160. package/lib/web/types/src/world/quat.d.ts +30 -0
  161. package/lib/web/types/src/world/types.d.ts +232 -0
  162. package/native/android/CMakeLists.txt +34 -0
  163. package/native/android/NayanEngineSpec.h +15 -0
  164. package/native/android/build.gradle +26 -0
  165. package/native/android/codegen/CMakeLists.txt +3 -0
  166. package/native/android/proguard-rules.pro +2 -0
  167. package/native/android/src/main/java/com/nayanui/engine/EngineSurfaceView.java +234 -0
  168. package/native/android/src/main/java/com/nayanui/engine/EngineSurfaceViewManager.java +45 -0
  169. package/native/android/src/main/java/com/nayanui/engine/NayanEnginePackage.java +24 -0
  170. package/native/core/build/EngineCore.xcframework/Info.plist +43 -0
  171. package/native/core/build/EngineCore.xcframework/ios-arm64/libengine_core.a +0 -0
  172. package/native/core/build/EngineCore.xcframework/ios-arm64-simulator/libengine_core.a +0 -0
  173. package/native/core/build/android/arm64-v8a/libengine_core.a +0 -0
  174. package/native/core/build/android/armeabi-v7a/libengine_core.a +0 -0
  175. package/native/core/build/android/x86/libengine_core.a +0 -0
  176. package/native/core/build/android/x86_64/libengine_core.a +0 -0
  177. package/native/core/include/drawing-licenses.txt +58 -0
  178. package/native/core/include/engine_core.h +322 -0
  179. package/native/cpp/NayanEngineModule.cpp +827 -0
  180. package/native/cpp/NayanEngineModule.h +144 -0
  181. package/native/cpp/generated/NayanEngineSpecJSI.cpp +2 -0
  182. package/native/cpp/generated/NayanEngineSpecJSI.h +921 -0
  183. package/native/ios/NayanEngineProvider.h +5 -0
  184. package/native/ios/NayanEngineProvider.mm +21 -0
  185. package/native/ios/NayanEngineSurface.mm +223 -0
  186. package/native/scripts/check-package.mjs +39 -0
  187. package/package.json +162 -4
  188. package/react-native.config.js +18 -0
  189. package/src/native/spec/NativeNayanEngine.ts +226 -0
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+
3
+ export { PanResponder } from 'react-native';
4
+ //# sourceMappingURL=responder.js.map
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+
3
+ /** Adapt DOM pointer capture to the gesture recognizer used on mobile. Coordinates stay in CSS pixels. */
4
+ export const PanResponder = {
5
+ create(callbacks) {
6
+ const pointers = new Map();
7
+ let origin = {
8
+ x: 0,
9
+ y: 0
10
+ };
11
+ let last = {
12
+ nativeEvent: {
13
+ pageX: 0,
14
+ pageY: 0,
15
+ locationX: 0,
16
+ locationY: 0,
17
+ touches: []
18
+ }
19
+ };
20
+ let gesture = {
21
+ dx: 0,
22
+ dy: 0
23
+ };
24
+ let primary = -1;
25
+ const event = e => {
26
+ const rect = e.currentTarget.getBoundingClientRect();
27
+ const nativeEvent = {
28
+ pageX: e.clientX,
29
+ pageY: e.clientY,
30
+ locationX: e.clientX - rect.left,
31
+ locationY: e.clientY - rect.top,
32
+ touches: [...pointers.values()]
33
+ };
34
+ if (e.pointerId === primary) gesture = {
35
+ dx: e.clientX - origin.x,
36
+ dy: e.clientY - origin.y
37
+ };
38
+ return last = {
39
+ nativeEvent
40
+ };
41
+ };
42
+ const cancel = () => {
43
+ if (pointers.size) callbacks.onPanResponderTerminate(last, gesture);
44
+ pointers.clear();
45
+ primary = -1;
46
+ };
47
+ return {
48
+ cancel,
49
+ panHandlers: {
50
+ onPointerDown(e) {
51
+ if (e.button !== 0) return;
52
+ e.preventDefault();
53
+ // Keyboard pointers already retain their target; only physical pointers can be captured.
54
+ if (e.isTrusted) e.currentTarget.setPointerCapture(e.pointerId);
55
+ pointers.set(e.pointerId, {
56
+ pageX: e.clientX,
57
+ pageY: e.clientY
58
+ });
59
+ if (pointers.size === 1) {
60
+ primary = e.pointerId;
61
+ origin = {
62
+ x: e.clientX,
63
+ y: e.clientY
64
+ };
65
+ gesture = {
66
+ dx: 0,
67
+ dy: 0
68
+ };
69
+ callbacks.onPanResponderGrant(event(e));
70
+ } else callbacks.onPanResponderMove(event(e), gesture);
71
+ },
72
+ onPointerMove(e) {
73
+ if (!pointers.has(e.pointerId)) return;
74
+ pointers.set(e.pointerId, {
75
+ pageX: e.clientX,
76
+ pageY: e.clientY
77
+ });
78
+ callbacks.onPanResponderMove(event(e), gesture);
79
+ },
80
+ onPointerUp(e) {
81
+ if (!pointers.has(e.pointerId)) return;
82
+ const current = event(e);
83
+ if (e.pointerId === primary || pointers.size >= 2) {
84
+ callbacks.onPanResponderRelease(current, gesture);
85
+ pointers.clear();
86
+ primary = -1;
87
+ } else pointers.delete(e.pointerId);
88
+ },
89
+ onPointerCancel: cancel,
90
+ onLostPointerCapture(e) {
91
+ if (pointers.has(e.pointerId)) cancel();
92
+ }
93
+ }
94
+ };
95
+ }
96
+ };
97
+ //# sourceMappingURL=responder.web.js.map
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+
3
+ // Gesture recognition for GameView: tap, swipe, drag, long press, pinch.
4
+ import { PanResponder } from './responder';
5
+ const TAP_SLOP = 10; // points a finger may wander and still tap
6
+ const TAP_TIME = 300; // ms
7
+ const SWIPE_DISTANCE = 30; // points
8
+ const SWIPE_SPEED = 0.3; // points per ms
9
+ const LONG_PRESS_TIME = 500; // ms
10
+
11
+ /**
12
+ * Creates a PanResponder that recognizes taps, swipes, drags, long presses and pinches.
13
+ * `getHandlers` is called on each event so the caller can swap handlers without recreating the responder.
14
+ */
15
+ export function createTouchResponder(getHandlers) {
16
+ let start = {
17
+ x: 0,
18
+ y: 0,
19
+ time: 0
20
+ };
21
+ let origin = {
22
+ x: 0,
23
+ y: 0
24
+ };
25
+ let mode = 'none';
26
+ let pinch0 = {
27
+ distance: 1,
28
+ angle: 0
29
+ };
30
+ let lastPinch = {
31
+ phase: 'end',
32
+ scale: 1,
33
+ rotation: 0,
34
+ x: 0,
35
+ y: 0
36
+ };
37
+ let longPress;
38
+ let longPressed = false;
39
+ const drag = (phase, x, y, cancelled) => getHandlers().onDrag?.({
40
+ phase,
41
+ x,
42
+ y,
43
+ dx: x - start.x,
44
+ dy: y - start.y,
45
+ ...(cancelled && {
46
+ cancelled
47
+ })
48
+ });
49
+ const twoFingers = (touches, phase) => {
50
+ const [a, b] = touches;
51
+ const distance = Math.max(1, Math.hypot(b.pageX - a.pageX, b.pageY - a.pageY));
52
+ const angle = Math.atan2(b.pageY - a.pageY, b.pageX - a.pageX);
53
+ if (phase === 'start') pinch0 = {
54
+ distance,
55
+ angle
56
+ };
57
+ lastPinch = {
58
+ phase,
59
+ scale: distance / pinch0.distance,
60
+ rotation: angle - pinch0.angle,
61
+ x: (a.pageX + b.pageX) / 2 - origin.x,
62
+ y: (a.pageY + b.pageY) / 2 - origin.y
63
+ };
64
+ getHandlers().onPinch?.(lastPinch);
65
+ };
66
+ const stopLongPress = () => {
67
+ clearTimeout(longPress);
68
+ longPress = undefined;
69
+ };
70
+ const responder = PanResponder.create({
71
+ onStartShouldSetPanResponder: () => true,
72
+ onMoveShouldSetPanResponder: () => true,
73
+ onPanResponderGrant: e => {
74
+ const {
75
+ locationX,
76
+ locationY,
77
+ pageX,
78
+ pageY
79
+ } = e.nativeEvent;
80
+ start = {
81
+ x: locationX,
82
+ y: locationY,
83
+ time: Date.now()
84
+ };
85
+ origin = {
86
+ x: pageX - locationX,
87
+ y: pageY - locationY
88
+ };
89
+ if (getHandlers().onOverlayTouch?.('start', start.x, start.y) === true) {
90
+ mode = 'overlay';
91
+ return;
92
+ }
93
+ mode = 'drag';
94
+ longPressed = false;
95
+ drag('start', start.x, start.y);
96
+ if (getHandlers().onLongPress) {
97
+ longPress = setTimeout(() => {
98
+ longPress = undefined;
99
+ if (mode !== 'drag') return;
100
+ longPressed = true;
101
+ getHandlers().onLongPress?.(start.x, start.y);
102
+ }, LONG_PRESS_TIME);
103
+ }
104
+ },
105
+ onPanResponderMove: (e, g) => {
106
+ if (mode === 'overlay') {
107
+ getHandlers().onOverlayTouch?.('move', start.x + g.dx, start.y + g.dy);
108
+ return;
109
+ }
110
+ const touches = e.nativeEvent.touches;
111
+ if (touches.length >= 2 && getHandlers().onPinch) {
112
+ if (mode === 'drag') {
113
+ stopLongPress();
114
+ drag('end', start.x + g.dx, start.y + g.dy, true);
115
+ mode = 'pinch';
116
+ twoFingers(touches, 'start');
117
+ } else if (mode === 'pinch') {
118
+ twoFingers(touches, 'move');
119
+ }
120
+ return;
121
+ }
122
+ if (mode !== 'drag') return;
123
+ if (Math.hypot(g.dx, g.dy) >= TAP_SLOP) stopLongPress();
124
+ drag('move', start.x + g.dx, start.y + g.dy);
125
+ },
126
+ onPanResponderRelease: (_, g) => {
127
+ stopLongPress();
128
+ const was = mode;
129
+ mode = 'none';
130
+ if (was === 'none') return;
131
+ if (was === 'overlay') {
132
+ getHandlers().onOverlayTouch?.('end', start.x + g.dx, start.y + g.dy);
133
+ return;
134
+ }
135
+ if (was === 'pinch') {
136
+ getHandlers().onPinch?.({
137
+ ...lastPinch,
138
+ phase: 'end'
139
+ });
140
+ return;
141
+ }
142
+ const x = start.x + g.dx;
143
+ const y = start.y + g.dy;
144
+ drag('end', x, y);
145
+ if (longPressed) return;
146
+ const {
147
+ onTap,
148
+ onSwipe
149
+ } = getHandlers();
150
+ const distance = Math.hypot(g.dx, g.dy);
151
+ const time = Date.now() - start.time;
152
+ if (distance < TAP_SLOP && time < TAP_TIME) onTap?.(start.x, start.y);else if (distance > SWIPE_DISTANCE && distance / Math.max(1, time) > SWIPE_SPEED) {
153
+ onSwipe?.(Math.abs(g.dx) > Math.abs(g.dy) ? g.dx > 0 ? 'right' : 'left' : g.dy > 0 ? 'down' : 'up');
154
+ }
155
+ },
156
+ onPanResponderTerminate: (_, g) => {
157
+ stopLongPress();
158
+ const was = mode;
159
+ mode = 'none';
160
+ if (was === 'overlay') getHandlers().onOverlayTouch?.('cancel', start.x + g.dx, start.y + g.dy);else if (was === 'pinch') getHandlers().onPinch?.({
161
+ ...lastPinch,
162
+ phase: 'end'
163
+ });else if (was === 'drag') drag('end', start.x + g.dx, start.y + g.dy, true);
164
+ }
165
+ });
166
+ const cancel = () => {
167
+ responder.cancel?.();
168
+ stopLongPress();
169
+ const was = mode;
170
+ mode = 'none';
171
+ if (was === 'overlay') getHandlers().onOverlayTouch?.('cancel', start.x, start.y);else if (was === 'pinch') getHandlers().onPinch?.({
172
+ ...lastPinch,
173
+ phase: 'end'
174
+ });else if (was === 'drag') drag('end', start.x, start.y, true);
175
+ };
176
+ return {
177
+ responder,
178
+ dispose: cancel,
179
+ cancel
180
+ };
181
+ }
182
+
183
+ // Re-export threshold constants for testing.
184
+ export { TAP_SLOP, TAP_TIME, SWIPE_DISTANCE, SWIPE_SPEED, LONG_PRESS_TIME };
185
+ //# sourceMappingURL=touch.js.map
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ /** Number of mesh ids: built-in shapes (0..15), then loaded models, glyphs and textured variants. */
4
+ export const MAX_MESHES = 4096;
5
+
6
+ /** What the renderer draws. `World` implements it; so can any custom simulation. */
7
+
8
+ /**
9
+ * Built-in shapes, each 1 unit across before scaling. "none" isn't drawn (groups, pivots, trigger zones).
10
+ * "puff" is a soft, round sprite that always faces the camera and is always see-through: overlapping
11
+ * puffs blend into smoke, dust, steam and clouds. "flame" is the same sprite drawn additively: it adds
12
+ * light to what's behind it, so overlapping flames build up to a hot white core and stay bright over
13
+ * smoke (fire, sparks, explosions, magic, glows). Use them as a burst's `mesh`.
14
+ */
15
+
16
+ /** Mesh ids of the built-in shapes, as the core and renderer know them. */
17
+ export const SHAPE_MESH = {
18
+ cube: 0,
19
+ sphere: 1,
20
+ plane: 2,
21
+ cylinder: 3,
22
+ cone: 4,
23
+ capsule: 5,
24
+ torus: 6,
25
+ roundedBox: 7,
26
+ puff: 8,
27
+ flame: 9,
28
+ none: 15
29
+ };
30
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+
3
+ import NativeEngine from '../native/NativeNayanEngine';
4
+ const OP = {
5
+ addScore: 0,
6
+ setScore: 1,
7
+ addLives: 2,
8
+ setLives: 3,
9
+ startClock: 4,
10
+ stopClock: 5,
11
+ resumeClock: 6,
12
+ reset: 7,
13
+ addTime: 8,
14
+ timeBonus: 9
15
+ };
16
+ const S = {
17
+ score: 0,
18
+ lives: 1,
19
+ seconds: 2,
20
+ shown: 3,
21
+ flags: 4,
22
+ running: 5,
23
+ rate: 6,
24
+ best: 7
25
+ };
26
+ const FLAG = {
27
+ score: 1,
28
+ lives: 2,
29
+ second: 4,
30
+ timeUp: 8,
31
+ livesOut: 16
32
+ };
33
+ /**
34
+ * Score, lives and the game clock, kept and advanced in Rust by `world.update`: countdowns, elapsed
35
+ * time and time-based points (survival, distance) cost no JS per frame. Handlers run from `update`
36
+ * only when something they show changed.
37
+ *
38
+ * ```ts
39
+ * world.scoreboard.handlers = { onScore: setScore, onSecond: setTime, onTimeUp: () => end(true) };
40
+ * world.scoreboard.reset(3);
41
+ * world.scoreboard.startCountdown(60);
42
+ * world.scoreboard.add(10);
43
+ * ```
44
+ */
45
+ export class Scoreboard {
46
+ handlers = {};
47
+ /** @internal */
48
+ constructor(world) {
49
+ this.world = world;
50
+ if (!NativeEngine || typeof NativeEngine.getScoreboard !== 'function') {
51
+ throw new Error("Scoreboard: this app's native core predates the scoreboard: rebuild it");
52
+ }
53
+ this.state = new Float64Array(NativeEngine.getScoreboard(world));
54
+ }
55
+ op(op, a = 0, b = 0) {
56
+ return NativeEngine.scoreboard(this.world, op, a, b);
57
+ }
58
+ get score() {
59
+ return this.state[S.score];
60
+ }
61
+ get best() {
62
+ return this.state[S.best];
63
+ }
64
+ get lives() {
65
+ return this.state[S.lives];
66
+ }
67
+ /** Seconds left (countdown) or elapsed, fractional. */
68
+ get seconds() {
69
+ return this.state[S.seconds];
70
+ }
71
+ /** Whole seconds as shown: rounded up while counting down, down while counting up. */
72
+ get shownSeconds() {
73
+ return this.state[S.shown];
74
+ }
75
+ get running() {
76
+ return this.state[S.running] !== 0;
77
+ }
78
+
79
+ /** Adds points (negative to take away). Returns the score. */
80
+ add(points) {
81
+ return this.op(OP.addScore, points);
82
+ }
83
+ set(score) {
84
+ return this.op(OP.setScore, score);
85
+ }
86
+ addLives(n) {
87
+ this.op(OP.addLives, n);
88
+ return this.lives;
89
+ }
90
+ setLives(n) {
91
+ this.op(OP.setLives, n);
92
+ }
93
+ /** Counts `seconds` down to 0 (then `onTimeUp`), earning `pointsPerSecond` meanwhile. */
94
+ startCountdown(seconds, pointsPerSecond = 0) {
95
+ this.op(OP.startClock, Math.max(1e-6, seconds), pointsPerSecond);
96
+ }
97
+ /** Counts up from 0, earning `pointsPerSecond` (survival and distance scores). */
98
+ startClock(pointsPerSecond = 0) {
99
+ this.op(OP.startClock, 0, pointsPerSecond);
100
+ }
101
+ stop() {
102
+ this.op(OP.stopClock);
103
+ }
104
+ resume() {
105
+ this.op(OP.resumeClock);
106
+ }
107
+ /** Time bonus (or penalty) on the clock. */
108
+ addTime(seconds) {
109
+ this.op(OP.addTime, seconds);
110
+ }
111
+ /**
112
+ * Adds `pointsPerSecond` for each whole second saved: the seconds left on a countdown, or
113
+ * `expectedSeconds` minus the seconds elapsed on a clock counting up. Returns the score.
114
+ */
115
+ awardTimeBonus(pointsPerSecond, expectedSeconds = 0) {
116
+ return this.op(OP.timeBonus, pointsPerSecond, expectedSeconds);
117
+ }
118
+ /**
119
+ * A new run: score 0, `lives`, clock stopped at 0. With `countdownSeconds`, the stopped clock shows
120
+ * that countdown in full (a ready screen); `resume()` starts it.
121
+ */
122
+ reset(lives = 0, countdownSeconds = 0) {
123
+ this.op(OP.reset, lives);
124
+ if (countdownSeconds > 0) {
125
+ this.startCountdown(countdownSeconds);
126
+ this.stop();
127
+ }
128
+ }
129
+
130
+ /** @internal Runs handlers for what changed since the last call. */
131
+ dispatch() {
132
+ const flags = this.state[S.flags];
133
+ if (flags === 0) return;
134
+ this.state[S.flags] = 0;
135
+ const h = this.handlers;
136
+ if (flags & FLAG.score) h.onScore?.(this.score);
137
+ if (flags & FLAG.lives) h.onLives?.(this.lives);
138
+ if (flags & FLAG.second) h.onSecond?.(this.shownSeconds);
139
+ if (flags & FLAG.timeUp) h.onTimeUp?.();
140
+ if (flags & FLAG.livesOut) h.onLivesOut?.();
141
+ }
142
+ }
143
+ //# sourceMappingURL=Scoreboard.js.map
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+
3
+ export const TRANSFORM_STRIDE = 16;
4
+
5
+ /**
6
+ * Explicit draw-only updates, applied in one native call by `flush()`. Flush before reading
7
+ * positions, animating, or stepping the world. Records and scratch storage are reused; values are
8
+ * copied when queued, never retained by reference. The scalar methods (`position`, `rotation`,
9
+ * `scale`, `color`, `transform`) allocate nothing; consecutive calls for the same entity share one
10
+ * record.
11
+ *
12
+ * ```ts
13
+ * const batch = world.transforms;
14
+ * for (const p of pieces) batch.transform(p.entity, p.x, 0, p.z, 0, p.qy, 0, p.qw);
15
+ * batch.flush();
16
+ * ```
17
+ */
18
+ export class TransformBatch {
19
+ data = new Float64Array(TRANSFORM_STRIDE * 32);
20
+ count = 0;
21
+ constructor(commit) {
22
+ this.commit = commit;
23
+ }
24
+ record(entity, flags) {
25
+ // Merge into the previous record when it updates the same entity (the layout is fixed per field).
26
+ if (this.count > 0) {
27
+ const last = (this.count - 1) * TRANSFORM_STRIDE;
28
+ if (this.data[last] === entity) {
29
+ this.data[last + 1] = this.data[last + 1] | flags;
30
+ return last;
31
+ }
32
+ }
33
+ const offset = this.count * TRANSFORM_STRIDE;
34
+ if (offset + TRANSFORM_STRIDE > this.data.length) {
35
+ const grown = new Float64Array(this.data.length * 2);
36
+ grown.set(this.data);
37
+ this.data = grown;
38
+ }
39
+ this.count++;
40
+ this.data[offset] = entity;
41
+ this.data[offset + 1] = flags;
42
+ return offset;
43
+ }
44
+ position(entity, x, y, z) {
45
+ const offset = this.record(entity, 2);
46
+ this.data[offset + 2] = x;
47
+ this.data[offset + 3] = y;
48
+ this.data[offset + 4] = z;
49
+ }
50
+
51
+ /** Rotation quaternion [x, y, z, w]. */
52
+ rotation(entity, x, y, z, w) {
53
+ const offset = this.record(entity, 4);
54
+ this.data[offset + 5] = x;
55
+ this.data[offset + 6] = y;
56
+ this.data[offset + 7] = z;
57
+ this.data[offset + 8] = w;
58
+ }
59
+
60
+ /** Uniform scale, or per axis. */
61
+ scale(entity, x, y = x, z = x) {
62
+ const offset = this.record(entity, 8);
63
+ this.data[offset + 9] = x;
64
+ this.data[offset + 10] = y;
65
+ this.data[offset + 11] = z;
66
+ }
67
+
68
+ /** RGBA color; alpha defaults to 1. */
69
+ color(entity, r, g, b, a = 1) {
70
+ const offset = this.record(entity, 16);
71
+ this.data[offset + 12] = r;
72
+ this.data[offset + 13] = g;
73
+ this.data[offset + 14] = b;
74
+ this.data[offset + 15] = a;
75
+ }
76
+
77
+ /** Position and rotation together (the common per-frame update for a moving piece). */
78
+ transform(entity, x, y, z, qx, qy, qz, qw) {
79
+ const offset = this.record(entity, 6);
80
+ this.data[offset + 2] = x;
81
+ this.data[offset + 3] = y;
82
+ this.data[offset + 4] = z;
83
+ this.data[offset + 5] = qx;
84
+ this.data[offset + 6] = qy;
85
+ this.data[offset + 7] = qz;
86
+ this.data[offset + 8] = qw;
87
+ }
88
+
89
+ /** Queued records (merged per entity). */
90
+ get size() {
91
+ return this.count;
92
+ }
93
+ set(entity, options) {
94
+ const {
95
+ position,
96
+ rotation,
97
+ scale,
98
+ color
99
+ } = options;
100
+ const flags = (position ? 2 : 0) | (rotation ? 4 : 0) | (scale !== undefined ? 8 : 0) | (color ? 16 : 0);
101
+ if (!flags) return;
102
+ const offset = this.record(entity, flags);
103
+ if (position) this.data.set(position, offset + 2);
104
+ if (rotation) this.data.set(rotation, offset + 5);
105
+ if (typeof scale === 'number') this.data.fill(scale, offset + 9, offset + 12);else if (scale) this.data.set(scale, offset + 9);
106
+ if (color) this.writeColor(offset, color);
107
+ }
108
+ writeColor(offset, color) {
109
+ this.data[offset + 12] = color[0];
110
+ this.data[offset + 13] = color[1];
111
+ this.data[offset + 14] = color[2];
112
+ this.data[offset + 15] = color[3] ?? 1;
113
+ }
114
+ flush() {
115
+ if (!this.count) return 0;
116
+ try {
117
+ return this.commit(this.data, this.count);
118
+ } finally {
119
+ this.count = 0;
120
+ }
121
+ }
122
+ clear() {
123
+ this.count = 0;
124
+ }
125
+ }
126
+ //# sourceMappingURL=TransformBatch.js.map