canvasengine 2.0.0-beta.2 → 2.0.0-beta.4
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/dist/index.d.ts +1085 -0
- package/dist/index.js +3042 -0
- package/dist/index.js.map +1 -0
- package/index.d.ts +4 -0
- package/package.json +1 -9
- package/src/components/index.ts +1 -3
- package/src/engine/reactive.ts +17 -0
- package/src/engine/trigger.ts +65 -9
- package/src/engine/utils.ts +84 -8
- package/src/index.ts +3 -1
- package/src/utils/RadialGradient.ts +29 -0
- package/src/components/DrawMap/index.ts +0 -65
- package/src/components/Tilemap/Tile.ts +0 -79
- package/src/components/Tilemap/TileGroup.ts +0 -207
- package/src/components/Tilemap/TileLayer.ts +0 -163
- package/src/components/Tilemap/TileSet.ts +0 -41
- package/src/components/Tilemap/index.ts +0 -80
package/dist/index.js
ADDED
|
@@ -0,0 +1,3042 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __typeError = (msg) => {
|
|
3
|
+
throw TypeError(msg);
|
|
4
|
+
};
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
10
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
11
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
12
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
13
|
+
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
14
|
+
|
|
15
|
+
// src/engine/directive.ts
|
|
16
|
+
var directives = {};
|
|
17
|
+
var Directive = class {
|
|
18
|
+
};
|
|
19
|
+
function registerDirective(name, directive) {
|
|
20
|
+
directives[name] = directive;
|
|
21
|
+
}
|
|
22
|
+
function applyDirective(element, directiveName) {
|
|
23
|
+
if (!directives[directiveName]) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const directive = new directives[directiveName]();
|
|
27
|
+
directive.onInit?.(element);
|
|
28
|
+
return directive;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// src/engine/utils.ts
|
|
32
|
+
var utils_exports = {};
|
|
33
|
+
__export(utils_exports, {
|
|
34
|
+
arrayEquals: () => arrayEquals,
|
|
35
|
+
calculateDistance: () => calculateDistance,
|
|
36
|
+
error: () => error,
|
|
37
|
+
fps2ms: () => fps2ms,
|
|
38
|
+
get: () => get,
|
|
39
|
+
isBrowser: () => isBrowser,
|
|
40
|
+
isFunction: () => isFunction,
|
|
41
|
+
isObject: () => isObject,
|
|
42
|
+
isPromise: () => isPromise,
|
|
43
|
+
log: () => log,
|
|
44
|
+
preciseNow: () => preciseNow,
|
|
45
|
+
set: () => set,
|
|
46
|
+
setObservablePoint: () => setObservablePoint
|
|
47
|
+
});
|
|
48
|
+
function isBrowser() {
|
|
49
|
+
return typeof window !== "undefined";
|
|
50
|
+
}
|
|
51
|
+
function preciseNow() {
|
|
52
|
+
return typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
53
|
+
}
|
|
54
|
+
function fps2ms(fps) {
|
|
55
|
+
return 1e3 / fps;
|
|
56
|
+
}
|
|
57
|
+
function isPromise(value) {
|
|
58
|
+
return value && value instanceof Promise;
|
|
59
|
+
}
|
|
60
|
+
function arrayEquals(a, b) {
|
|
61
|
+
if (a.length !== b.length) return false;
|
|
62
|
+
for (let i = 0; i < a.length; i++) {
|
|
63
|
+
const v = a[i];
|
|
64
|
+
const bv = b[i];
|
|
65
|
+
if (typeof v === "object" && v !== null) {
|
|
66
|
+
if (typeof bv !== "object" || bv === null) return false;
|
|
67
|
+
if (Array.isArray(v)) {
|
|
68
|
+
if (!Array.isArray(bv) || !arrayEquals(v, bv)) return false;
|
|
69
|
+
} else if (!objectEquals(v, bv)) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
} else if (v !== bv) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
function objectEquals(a, b) {
|
|
79
|
+
const keysA = Object.keys(a);
|
|
80
|
+
const keysB = Object.keys(b);
|
|
81
|
+
if (keysA.length !== keysB.length) return false;
|
|
82
|
+
for (let key of keysA) {
|
|
83
|
+
if (!b.hasOwnProperty(key)) return false;
|
|
84
|
+
if (!deepEquals(a[key], b[key])) return false;
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
function deepEquals(a, b) {
|
|
89
|
+
if (a === b) return true;
|
|
90
|
+
if (typeof a !== typeof b) return false;
|
|
91
|
+
if (typeof a === "object" && a !== null) {
|
|
92
|
+
if (Array.isArray(a)) {
|
|
93
|
+
return Array.isArray(b) && arrayEquals(a, b);
|
|
94
|
+
}
|
|
95
|
+
return objectEquals(a, b);
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
function isFunction(val) {
|
|
100
|
+
return {}.toString.call(val) === "[object Function]";
|
|
101
|
+
}
|
|
102
|
+
function isObject(val) {
|
|
103
|
+
return typeof val == "object" && val != null && !Array.isArray(val);
|
|
104
|
+
}
|
|
105
|
+
function set(obj, path, value, onlyPlainObject = false) {
|
|
106
|
+
if (Object(obj) !== obj) return obj;
|
|
107
|
+
if (typeof path === "string") {
|
|
108
|
+
path = path.split(".");
|
|
109
|
+
}
|
|
110
|
+
let len = path.length;
|
|
111
|
+
if (!len) return obj;
|
|
112
|
+
let current = obj;
|
|
113
|
+
for (let i = 0; i < len - 1; i++) {
|
|
114
|
+
let segment = path[i];
|
|
115
|
+
let nextSegment = path[i + 1];
|
|
116
|
+
let isNextNumeric = !isNaN(Number(nextSegment)) && isFinite(Number(nextSegment));
|
|
117
|
+
if (!current[segment] || typeof current[segment] !== "object") {
|
|
118
|
+
current[segment] = isNextNumeric && !onlyPlainObject ? [] : {};
|
|
119
|
+
}
|
|
120
|
+
current = current[segment];
|
|
121
|
+
}
|
|
122
|
+
current[path[len - 1]] = value;
|
|
123
|
+
return obj;
|
|
124
|
+
}
|
|
125
|
+
function get(obj, path) {
|
|
126
|
+
const keys = path.split(".");
|
|
127
|
+
let current = obj;
|
|
128
|
+
for (let key of keys) {
|
|
129
|
+
if (current[key] === void 0) {
|
|
130
|
+
return void 0;
|
|
131
|
+
}
|
|
132
|
+
current = current[key];
|
|
133
|
+
}
|
|
134
|
+
return current;
|
|
135
|
+
}
|
|
136
|
+
function log(text) {
|
|
137
|
+
console.log(text);
|
|
138
|
+
}
|
|
139
|
+
function error(text) {
|
|
140
|
+
console.error(text);
|
|
141
|
+
}
|
|
142
|
+
function setObservablePoint(observablePoint, point) {
|
|
143
|
+
if (typeof point === "number") {
|
|
144
|
+
observablePoint.set(point);
|
|
145
|
+
} else if (Array.isArray(point)) {
|
|
146
|
+
observablePoint.set(point[0], point[1]);
|
|
147
|
+
} else {
|
|
148
|
+
observablePoint.set(point.x, point.y);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function calculateDistance(x1, y1, x2, y2) {
|
|
152
|
+
const dx = x1 - x2;
|
|
153
|
+
const dy = y1 - y2;
|
|
154
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// src/directives/KeyboardControls.ts
|
|
158
|
+
var keyCodeTable = {
|
|
159
|
+
3: "break",
|
|
160
|
+
8: "backspace",
|
|
161
|
+
// backspace / delete
|
|
162
|
+
9: "tab",
|
|
163
|
+
12: "clear",
|
|
164
|
+
13: "enter",
|
|
165
|
+
16: "shift",
|
|
166
|
+
17: "ctrl",
|
|
167
|
+
18: "alt",
|
|
168
|
+
19: "pause/break",
|
|
169
|
+
20: "caps lock",
|
|
170
|
+
27: "escape",
|
|
171
|
+
28: "conversion",
|
|
172
|
+
29: "non-conversion",
|
|
173
|
+
32: "space",
|
|
174
|
+
33: "page up",
|
|
175
|
+
34: "page down",
|
|
176
|
+
35: "end",
|
|
177
|
+
36: "home",
|
|
178
|
+
37: "left",
|
|
179
|
+
38: "up",
|
|
180
|
+
39: "right",
|
|
181
|
+
40: "down",
|
|
182
|
+
41: "select",
|
|
183
|
+
42: "print",
|
|
184
|
+
43: "execute",
|
|
185
|
+
44: "Print Screen",
|
|
186
|
+
45: "insert",
|
|
187
|
+
46: "delete",
|
|
188
|
+
48: "n0",
|
|
189
|
+
49: "n1",
|
|
190
|
+
50: "n2",
|
|
191
|
+
51: "n3",
|
|
192
|
+
52: "n4",
|
|
193
|
+
53: "n5",
|
|
194
|
+
54: "n6",
|
|
195
|
+
55: "n7",
|
|
196
|
+
56: "n8",
|
|
197
|
+
57: "n9",
|
|
198
|
+
58: ":",
|
|
199
|
+
59: "semicolon (firefox), equals",
|
|
200
|
+
60: "<",
|
|
201
|
+
61: "equals (firefox)",
|
|
202
|
+
63: "\xDF",
|
|
203
|
+
64: "@",
|
|
204
|
+
65: "a",
|
|
205
|
+
66: "b",
|
|
206
|
+
67: "c",
|
|
207
|
+
68: "d",
|
|
208
|
+
69: "e",
|
|
209
|
+
70: "f",
|
|
210
|
+
71: "g",
|
|
211
|
+
72: "h",
|
|
212
|
+
73: "i",
|
|
213
|
+
74: "j",
|
|
214
|
+
75: "k",
|
|
215
|
+
76: "l",
|
|
216
|
+
77: "m",
|
|
217
|
+
78: "n",
|
|
218
|
+
79: "o",
|
|
219
|
+
80: "p",
|
|
220
|
+
81: "q",
|
|
221
|
+
82: "r",
|
|
222
|
+
83: "s",
|
|
223
|
+
84: "t",
|
|
224
|
+
85: "u",
|
|
225
|
+
86: "v",
|
|
226
|
+
87: "w",
|
|
227
|
+
88: "x",
|
|
228
|
+
89: "y",
|
|
229
|
+
90: "z",
|
|
230
|
+
91: "Windows Key / Left \u2318 / Chromebook Search key",
|
|
231
|
+
92: "right window key",
|
|
232
|
+
93: "Windows Menu / Right \u2318",
|
|
233
|
+
96: "numpad 0",
|
|
234
|
+
97: "numpad 1",
|
|
235
|
+
98: "numpad 2",
|
|
236
|
+
99: "numpad 3",
|
|
237
|
+
100: "numpad 4",
|
|
238
|
+
101: "numpad 5",
|
|
239
|
+
102: "numpad 6",
|
|
240
|
+
103: "numpad 7",
|
|
241
|
+
104: "numpad 8",
|
|
242
|
+
105: "numpad 9",
|
|
243
|
+
106: "multiply",
|
|
244
|
+
107: "add",
|
|
245
|
+
108: "numpad period (firefox)",
|
|
246
|
+
109: "subtract",
|
|
247
|
+
110: "decimal point",
|
|
248
|
+
111: "divide",
|
|
249
|
+
112: "f1",
|
|
250
|
+
113: "f2",
|
|
251
|
+
114: "f3",
|
|
252
|
+
115: "f4",
|
|
253
|
+
116: "f5",
|
|
254
|
+
117: "f6",
|
|
255
|
+
118: "f7",
|
|
256
|
+
119: "f8",
|
|
257
|
+
120: "f9",
|
|
258
|
+
121: "f10",
|
|
259
|
+
122: "f11",
|
|
260
|
+
123: "f12",
|
|
261
|
+
124: "f13",
|
|
262
|
+
125: "f14",
|
|
263
|
+
126: "f15",
|
|
264
|
+
127: "f16",
|
|
265
|
+
128: "f17",
|
|
266
|
+
129: "f18",
|
|
267
|
+
130: "f19",
|
|
268
|
+
131: "f20",
|
|
269
|
+
132: "f21",
|
|
270
|
+
133: "f22",
|
|
271
|
+
134: "f23",
|
|
272
|
+
135: "f24",
|
|
273
|
+
144: "num lock",
|
|
274
|
+
145: "scroll lock",
|
|
275
|
+
160: "^",
|
|
276
|
+
161: "!",
|
|
277
|
+
163: "#",
|
|
278
|
+
164: "$",
|
|
279
|
+
165: "\xF9",
|
|
280
|
+
166: "page backward",
|
|
281
|
+
167: "page forward",
|
|
282
|
+
169: "closing paren (AZERTY)",
|
|
283
|
+
170: "*",
|
|
284
|
+
171: "~ + * key",
|
|
285
|
+
173: "minus (firefox), mute/unmute",
|
|
286
|
+
174: "decrease volume level",
|
|
287
|
+
175: "increase volume level",
|
|
288
|
+
176: "next",
|
|
289
|
+
177: "previous",
|
|
290
|
+
178: "stop",
|
|
291
|
+
179: "play/pause",
|
|
292
|
+
180: "e-mail",
|
|
293
|
+
181: "mute/unmute (firefox)",
|
|
294
|
+
182: "decrease volume level (firefox)",
|
|
295
|
+
183: "increase volume level (firefox)",
|
|
296
|
+
186: "semi-colon / \xF1",
|
|
297
|
+
187: "equal sign",
|
|
298
|
+
188: "comma",
|
|
299
|
+
189: "dash",
|
|
300
|
+
190: "period",
|
|
301
|
+
191: "forward slash / \xE7",
|
|
302
|
+
192: "grave accent / \xF1 / \xE6",
|
|
303
|
+
193: "?, / or \xB0",
|
|
304
|
+
194: "numpad period (chrome)",
|
|
305
|
+
219: "open bracket",
|
|
306
|
+
220: "back slash",
|
|
307
|
+
221: "close bracket / \xE5",
|
|
308
|
+
222: "single quote / \xF8",
|
|
309
|
+
223: "`",
|
|
310
|
+
224: "left or right \u2318 key (firefox)",
|
|
311
|
+
225: "altgr",
|
|
312
|
+
226: "< /git >",
|
|
313
|
+
230: "GNOME Compose Key",
|
|
314
|
+
231: "\xE7",
|
|
315
|
+
233: "XF86Forward",
|
|
316
|
+
234: "XF86Back",
|
|
317
|
+
240: "alphanumeric",
|
|
318
|
+
242: "hiragana/katakana",
|
|
319
|
+
243: "half-width/full-width",
|
|
320
|
+
244: "kanji",
|
|
321
|
+
255: "toggle touchpad"
|
|
322
|
+
};
|
|
323
|
+
var inverse = (obj) => {
|
|
324
|
+
const newObj = {};
|
|
325
|
+
for (let key in obj) {
|
|
326
|
+
const val = obj[key];
|
|
327
|
+
newObj[val] = key;
|
|
328
|
+
}
|
|
329
|
+
return newObj;
|
|
330
|
+
};
|
|
331
|
+
var inverseKeyCodeTable = inverse(keyCodeTable);
|
|
332
|
+
var KeyboardControls = class extends Directive {
|
|
333
|
+
constructor() {
|
|
334
|
+
super(...arguments);
|
|
335
|
+
this.keyState = {};
|
|
336
|
+
this.boundKeys = {};
|
|
337
|
+
this.stop = false;
|
|
338
|
+
this.lastKeyPressed = null;
|
|
339
|
+
this._controlsOptions = {};
|
|
340
|
+
// TODO: This should be dynamic
|
|
341
|
+
this.serverFps = 60;
|
|
342
|
+
this.directionState = {
|
|
343
|
+
up: false,
|
|
344
|
+
down: false,
|
|
345
|
+
left: false,
|
|
346
|
+
right: false
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
onInit(element) {
|
|
350
|
+
this.setupListeners();
|
|
351
|
+
this.setInputs(element.props.controls.value);
|
|
352
|
+
this.interval = setInterval(() => {
|
|
353
|
+
this.preStep();
|
|
354
|
+
}, fps2ms(this.serverFps ?? 60));
|
|
355
|
+
}
|
|
356
|
+
onMount(element) {
|
|
357
|
+
}
|
|
358
|
+
onUpdate(props) {
|
|
359
|
+
this.setInputs(props);
|
|
360
|
+
}
|
|
361
|
+
onDestroy() {
|
|
362
|
+
clearInterval(this.interval);
|
|
363
|
+
document.removeEventListener("keydown", (e) => {
|
|
364
|
+
this.onKeyChange(e, true);
|
|
365
|
+
});
|
|
366
|
+
document.removeEventListener("keyup", (e) => {
|
|
367
|
+
this.onKeyChange(e, false);
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
/** @internal */
|
|
371
|
+
preStep() {
|
|
372
|
+
if (this.stop) return;
|
|
373
|
+
const direction = this.getDirection();
|
|
374
|
+
if (direction !== "none") {
|
|
375
|
+
const directionControl = this.boundKeys[direction];
|
|
376
|
+
if (directionControl) {
|
|
377
|
+
const { keyDown } = directionControl.options;
|
|
378
|
+
if (keyDown) {
|
|
379
|
+
this.applyInput(direction);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
} else {
|
|
383
|
+
const boundKeys = Object.keys(this.boundKeys);
|
|
384
|
+
for (let keyName of boundKeys) {
|
|
385
|
+
this.applyInput(keyName);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
applyInput(keyName) {
|
|
390
|
+
const keyState = this.keyState[keyName];
|
|
391
|
+
if (!keyState) return;
|
|
392
|
+
const { isDown, count } = keyState;
|
|
393
|
+
if (isDown) {
|
|
394
|
+
const { repeat, keyDown } = this.boundKeys[keyName].options;
|
|
395
|
+
if (repeat || count == 0) {
|
|
396
|
+
let parameters = this.boundKeys[keyName].parameters;
|
|
397
|
+
if (typeof parameters === "function") {
|
|
398
|
+
parameters = parameters();
|
|
399
|
+
}
|
|
400
|
+
if (keyDown) {
|
|
401
|
+
keyDown(this.boundKeys[keyName]);
|
|
402
|
+
}
|
|
403
|
+
this.keyState[keyName].count++;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
setupListeners() {
|
|
408
|
+
document.addEventListener("keydown", (e) => {
|
|
409
|
+
this.onKeyChange(e, true);
|
|
410
|
+
});
|
|
411
|
+
document.addEventListener("keyup", (e) => {
|
|
412
|
+
this.onKeyChange(e, false);
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
bindKey(keys, actionName, options, parameters) {
|
|
416
|
+
if (!Array.isArray(keys)) keys = [keys];
|
|
417
|
+
const keyOptions = Object.assign({
|
|
418
|
+
repeat: false
|
|
419
|
+
}, options);
|
|
420
|
+
keys.forEach((keyName) => {
|
|
421
|
+
this.boundKeys[keyName] = { actionName, options: keyOptions, parameters };
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
applyKeyDown(name) {
|
|
425
|
+
const code = inverseKeyCodeTable[name];
|
|
426
|
+
const e = new Event("keydown");
|
|
427
|
+
e.keyCode = code;
|
|
428
|
+
this.onKeyChange(e, true);
|
|
429
|
+
}
|
|
430
|
+
applyKeyUp(name) {
|
|
431
|
+
const code = inverseKeyCodeTable[name];
|
|
432
|
+
const e = new Event("keyup");
|
|
433
|
+
e.keyCode = code;
|
|
434
|
+
this.onKeyChange(e, false);
|
|
435
|
+
}
|
|
436
|
+
applyKeyPress(name) {
|
|
437
|
+
return new Promise((resolve) => {
|
|
438
|
+
this.applyKeyDown(name);
|
|
439
|
+
setTimeout(() => {
|
|
440
|
+
this.applyKeyUp(name);
|
|
441
|
+
resolve();
|
|
442
|
+
}, 200);
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
onKeyChange(e, isDown) {
|
|
446
|
+
e = e || window.event;
|
|
447
|
+
const keyName = keyCodeTable[e.keyCode];
|
|
448
|
+
if (keyName && this.boundKeys[keyName]) {
|
|
449
|
+
if (this.keyState[keyName] == null) {
|
|
450
|
+
this.keyState[keyName] = {
|
|
451
|
+
count: 0,
|
|
452
|
+
isDown: true
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
this.keyState[keyName].isDown = isDown;
|
|
456
|
+
if (!isDown) {
|
|
457
|
+
this.keyState[keyName].count = 0;
|
|
458
|
+
const { keyUp } = this.boundKeys[keyName].options;
|
|
459
|
+
if (keyUp) {
|
|
460
|
+
keyUp(this.boundKeys[keyName]);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
this.lastKeyPressed = isDown ? e.keyCode : null;
|
|
464
|
+
}
|
|
465
|
+
if (keyName) {
|
|
466
|
+
this.updateDirectionState(keyName, isDown);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
updateDirectionState(keyName, isDown) {
|
|
470
|
+
switch (keyName) {
|
|
471
|
+
case "up":
|
|
472
|
+
this.directionState.up = isDown;
|
|
473
|
+
break;
|
|
474
|
+
case "down":
|
|
475
|
+
this.directionState.down = isDown;
|
|
476
|
+
break;
|
|
477
|
+
case "left":
|
|
478
|
+
this.directionState.left = isDown;
|
|
479
|
+
break;
|
|
480
|
+
case "right":
|
|
481
|
+
this.directionState.right = isDown;
|
|
482
|
+
break;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
getDirection() {
|
|
486
|
+
const { up, down, left, right } = this.directionState;
|
|
487
|
+
if (up && left) return "up_left";
|
|
488
|
+
if (up && right) return "up_right";
|
|
489
|
+
if (down && left) return "down_left";
|
|
490
|
+
if (down && right) return "down_right";
|
|
491
|
+
if (up) return "up";
|
|
492
|
+
if (down) return "down";
|
|
493
|
+
if (left) return "left";
|
|
494
|
+
if (right) return "right";
|
|
495
|
+
return "none";
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* From the name of the entry, we retrieve the control information
|
|
499
|
+
*
|
|
500
|
+
* ```ts
|
|
501
|
+
* import { Input, inject, KeyboardControls } from '@rpgjs/client'
|
|
502
|
+
*
|
|
503
|
+
* const controls = inject(KeyboardControls)
|
|
504
|
+
* controls.getControl(Input.Enter)
|
|
505
|
+
|
|
506
|
+
* if (control) {
|
|
507
|
+
* console.log(control.actionName) // action
|
|
508
|
+
* }
|
|
509
|
+
* ```
|
|
510
|
+
* @title Get Control
|
|
511
|
+
* @method getControl(inputName)
|
|
512
|
+
* @param {string} inputName
|
|
513
|
+
* @returns { { actionName: string, options: any } | undefined }
|
|
514
|
+
* @memberof KeyboardControls
|
|
515
|
+
*/
|
|
516
|
+
getControl(inputName) {
|
|
517
|
+
return this.boundKeys[inputName];
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Returns all controls
|
|
521
|
+
*
|
|
522
|
+
* @method getControls()
|
|
523
|
+
* @since 4.2.0
|
|
524
|
+
* @returns { { [key: string]: BoundKey } }
|
|
525
|
+
* @memberof KeyboardControls
|
|
526
|
+
*/
|
|
527
|
+
getControls() {
|
|
528
|
+
return this.boundKeys;
|
|
529
|
+
}
|
|
530
|
+
/**
|
|
531
|
+
* Triggers an input according to the name of the control
|
|
532
|
+
*
|
|
533
|
+
* ```ts
|
|
534
|
+
* import { Control, inject, KeyboardControls } from '@rpgjs/client'
|
|
535
|
+
*
|
|
536
|
+
* const controls = inject(KeyboardControls)
|
|
537
|
+
* controls.applyControl(Control.Action)
|
|
538
|
+
* ```
|
|
539
|
+
*
|
|
540
|
+
* You can put a second parameter or indicate on whether the key is pressed or released
|
|
541
|
+
*
|
|
542
|
+
* ```ts
|
|
543
|
+
* import { Control, inject, KeyboardControls } from '@rpgjs/client'
|
|
544
|
+
*
|
|
545
|
+
* const controls = inject(KeyboardControls)
|
|
546
|
+
* controls.applyControl(Control.Up, true) // keydown
|
|
547
|
+
* controls.applyControl(Control.Up, false) // keyup
|
|
548
|
+
* ```
|
|
549
|
+
* @title Apply Control
|
|
550
|
+
* @method applyControl(controlName,isDown)
|
|
551
|
+
* @param {string} controlName
|
|
552
|
+
* @param {boolean} [isDown]
|
|
553
|
+
* @returns {Promise<void>}
|
|
554
|
+
* @memberof KeyboardControls
|
|
555
|
+
*/
|
|
556
|
+
async applyControl(controlName, isDown) {
|
|
557
|
+
const control = this._controlsOptions[controlName];
|
|
558
|
+
if (control) {
|
|
559
|
+
const input = Array.isArray(control.bind) ? control.bind[0] : control.bind;
|
|
560
|
+
if (isDown === void 0) {
|
|
561
|
+
await this.applyKeyPress(input);
|
|
562
|
+
} else if (isDown) {
|
|
563
|
+
this.applyKeyDown(input);
|
|
564
|
+
} else {
|
|
565
|
+
this.applyKeyUp(input);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Stop listening to the inputs. Pressing a key won't do anything
|
|
571
|
+
*
|
|
572
|
+
* @title Stop Inputs
|
|
573
|
+
* @method stopInputs()
|
|
574
|
+
* @returns {void}
|
|
575
|
+
* @memberof KeyboardControls
|
|
576
|
+
*/
|
|
577
|
+
stopInputs() {
|
|
578
|
+
this.stop = true;
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* Listen to the inputs again
|
|
582
|
+
*
|
|
583
|
+
* @title Listen Inputs
|
|
584
|
+
* @method listenInputs()
|
|
585
|
+
* @returns {void}
|
|
586
|
+
* @memberof KeyboardControls
|
|
587
|
+
*/
|
|
588
|
+
listenInputs() {
|
|
589
|
+
this.stop = false;
|
|
590
|
+
this.keyState = {};
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Assign custom inputs to the scene
|
|
594
|
+
*
|
|
595
|
+
* The object is the following:
|
|
596
|
+
*
|
|
597
|
+
* * the key of the object is the name of the control. Either it is existing controls (Up, Dow, Left, Right, Action, Back) or customized controls
|
|
598
|
+
* * The value is an object representing control information:
|
|
599
|
+
* * repeat {boolean} The key can be held down to repeat the action. (false by default)
|
|
600
|
+
* * bind {string | string[]} To which key is linked the control
|
|
601
|
+
* * method {Function} Function to be triggered. If you do not set this property, the name of the control is sent directly to the server.
|
|
602
|
+
* * delay {object|number} (since v3.2.0) Indicates how long (in milliseconds) the player can press the key again to perform the action
|
|
603
|
+
* * delay.duration
|
|
604
|
+
* * delay.otherControls {string | string[]} Indicates the other controls that will also have the delay at the same time
|
|
605
|
+
*
|
|
606
|
+
* ```ts
|
|
607
|
+
* import { Control, Input, inject, KeyboardControls } from '@rpgjs/client'
|
|
608
|
+
*
|
|
609
|
+
* const controls = inject(KeyboardControls)
|
|
610
|
+
* controls.setInputs({
|
|
611
|
+
[Control.Up]: {
|
|
612
|
+
repeat: true,
|
|
613
|
+
bind: Input.Up
|
|
614
|
+
},
|
|
615
|
+
[Control.Down]: {
|
|
616
|
+
repeat: true,
|
|
617
|
+
bind: Input.Down
|
|
618
|
+
},
|
|
619
|
+
[Control.Right]: {
|
|
620
|
+
repeat: true,
|
|
621
|
+
bind: Input.Right
|
|
622
|
+
},
|
|
623
|
+
[Control.Left]: {
|
|
624
|
+
repeat: true,
|
|
625
|
+
bind: Input.Left
|
|
626
|
+
},
|
|
627
|
+
[Control.Action]: {
|
|
628
|
+
bind: [Input.Space, Input.Enter]
|
|
629
|
+
},
|
|
630
|
+
[Control.Back]: {
|
|
631
|
+
bind: Input.Escape
|
|
632
|
+
},
|
|
633
|
+
|
|
634
|
+
// The myscustom1 control is sent to the server when the A key is pressed.
|
|
635
|
+
mycustom1: {
|
|
636
|
+
bind: Input.A
|
|
637
|
+
},
|
|
638
|
+
|
|
639
|
+
// the myAction method is executed when the B key is pressed
|
|
640
|
+
mycustom2: {
|
|
641
|
+
bind: Input.B,
|
|
642
|
+
method({ actionName }) {
|
|
643
|
+
console.log('cool', actionName)
|
|
644
|
+
}
|
|
645
|
+
},
|
|
646
|
+
|
|
647
|
+
// The player can redo the action after 400ms
|
|
648
|
+
mycustom3: {
|
|
649
|
+
bind: Input.C,
|
|
650
|
+
delay: 400 // ms
|
|
651
|
+
},
|
|
652
|
+
|
|
653
|
+
// The player can redo the action (mycustom4) and the directions after 400ms
|
|
654
|
+
mycustom4: {
|
|
655
|
+
bind: Input.C,
|
|
656
|
+
delay: {
|
|
657
|
+
duration: 400,
|
|
658
|
+
otherControls: [Control.Up, Control.Down, Control.Left, Control.Right]
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
})
|
|
662
|
+
*
|
|
663
|
+
* ```
|
|
664
|
+
* @enum {string} Control
|
|
665
|
+
*
|
|
666
|
+
* Control.Up | up
|
|
667
|
+
* Control.Down | down
|
|
668
|
+
* Control.Left | left
|
|
669
|
+
* Control.Right | right
|
|
670
|
+
* Control.Action | action
|
|
671
|
+
* Control.Back | back
|
|
672
|
+
*
|
|
673
|
+
* @enum {string} Mouse Event
|
|
674
|
+
*
|
|
675
|
+
* click | Click
|
|
676
|
+
* dblclick | Double Click
|
|
677
|
+
* mousedown | Mouse Down
|
|
678
|
+
* mouseup | Mouse Up
|
|
679
|
+
* mouseover | Mouse Over
|
|
680
|
+
* mousemove | Mouse Move
|
|
681
|
+
* mouseout | Mouse Out
|
|
682
|
+
* contextmenu | Context Menu
|
|
683
|
+
*
|
|
684
|
+
*
|
|
685
|
+
* @enum {string} Input
|
|
686
|
+
*
|
|
687
|
+
* break | Pause
|
|
688
|
+
* backspace | Backspace / Delete
|
|
689
|
+
* tab | Tab
|
|
690
|
+
* clear | Clear
|
|
691
|
+
* enter | Enter
|
|
692
|
+
* shift | Shift
|
|
693
|
+
* ctrl | Control
|
|
694
|
+
* alt | Alt
|
|
695
|
+
* pause/break | Pause / Break
|
|
696
|
+
* caps lock | Caps Lock
|
|
697
|
+
* escape | Escape
|
|
698
|
+
* conversion | Conversion
|
|
699
|
+
* non-conversion | Non-conversion
|
|
700
|
+
* space | Space
|
|
701
|
+
* page up | Page Up
|
|
702
|
+
* page down | Page Down
|
|
703
|
+
* end | End
|
|
704
|
+
* home | Home
|
|
705
|
+
* left | Left Arrow
|
|
706
|
+
* up | Up Arrow
|
|
707
|
+
* right | Right Arrow
|
|
708
|
+
* down | Down Arrow
|
|
709
|
+
* select | Select
|
|
710
|
+
* print | Print
|
|
711
|
+
* execute | Execute
|
|
712
|
+
* Print Screen | Print Screen
|
|
713
|
+
* insert | Insert
|
|
714
|
+
* delete | Delete
|
|
715
|
+
* n0 | 0
|
|
716
|
+
* n1 | 1
|
|
717
|
+
* n2 | 2
|
|
718
|
+
* n3 | 3
|
|
719
|
+
* n4 | 4
|
|
720
|
+
* n5 | 5
|
|
721
|
+
* n6 | 6
|
|
722
|
+
* n7 | 7
|
|
723
|
+
* n8 | 8
|
|
724
|
+
* n9 | 9
|
|
725
|
+
* : | Colon
|
|
726
|
+
* semicolon (firefox), equals | Semicolon (Firefox), Equals
|
|
727
|
+
* < | Less Than
|
|
728
|
+
* equals (firefox) | Equals (Firefox)
|
|
729
|
+
* ß | Eszett
|
|
730
|
+
* @ | At
|
|
731
|
+
* a | A
|
|
732
|
+
* b | B
|
|
733
|
+
* c | C
|
|
734
|
+
* d | D
|
|
735
|
+
* e | E
|
|
736
|
+
* f | F
|
|
737
|
+
* g | G
|
|
738
|
+
* h | H
|
|
739
|
+
* i | I
|
|
740
|
+
* j | J
|
|
741
|
+
* k | K
|
|
742
|
+
* l | L
|
|
743
|
+
* m | M
|
|
744
|
+
* n | N
|
|
745
|
+
* o | O
|
|
746
|
+
* p | P
|
|
747
|
+
* q | Q
|
|
748
|
+
* r | R
|
|
749
|
+
* s | S
|
|
750
|
+
* t | T
|
|
751
|
+
* u | U
|
|
752
|
+
* v | V
|
|
753
|
+
* w | W
|
|
754
|
+
* x | X
|
|
755
|
+
* y | Y
|
|
756
|
+
* z | Z
|
|
757
|
+
* Windows Key / Left ⌘ / Chromebook Search key | Windows Key / Left Command ⌘ / Chromebook Search Key
|
|
758
|
+
* right window key | Right Windows Key
|
|
759
|
+
* Windows Menu / Right ⌘ | Windows Menu / Right Command ⌘
|
|
760
|
+
* numpad 0 | Numpad 0
|
|
761
|
+
* numpad 1 | Numpad 1
|
|
762
|
+
* numpad 2 | Numpad 2
|
|
763
|
+
* numpad 3 | Numpad 3
|
|
764
|
+
* numpad 4 | Numpad 4
|
|
765
|
+
* numpad 5 | Numpad 5
|
|
766
|
+
* numpad 6 | Numpad 6
|
|
767
|
+
* numpad 7 | Numpad 7
|
|
768
|
+
* numpad 8 | Numpad 8
|
|
769
|
+
* numpad 9 | Numpad 9
|
|
770
|
+
* multiply | Multiply
|
|
771
|
+
* add | Add
|
|
772
|
+
* numpad period (firefox) | Numpad Period (Firefox)
|
|
773
|
+
* subtract | Subtract
|
|
774
|
+
* decimal point | Decimal Point
|
|
775
|
+
* divide | Divide
|
|
776
|
+
* f1 | F1
|
|
777
|
+
* f2 | F2
|
|
778
|
+
* f3 | F3
|
|
779
|
+
* f4 | F4
|
|
780
|
+
* f5 | F5
|
|
781
|
+
* f6 | F6
|
|
782
|
+
* f7 | F7
|
|
783
|
+
* f8 | F8
|
|
784
|
+
* f9 | F9
|
|
785
|
+
* f10 | F10
|
|
786
|
+
* f11 | F11
|
|
787
|
+
* f12 | F12
|
|
788
|
+
* f13 | F13
|
|
789
|
+
* f14 | F14
|
|
790
|
+
* f15 | F15
|
|
791
|
+
* f16 | F16
|
|
792
|
+
* f17 | F17
|
|
793
|
+
* f18 | F18
|
|
794
|
+
* f19 | F19
|
|
795
|
+
* f20 | F20
|
|
796
|
+
* f21 | F21
|
|
797
|
+
* f22 | F22
|
|
798
|
+
* f23 | F23
|
|
799
|
+
* f24 | F24
|
|
800
|
+
* num lock | Num Lock
|
|
801
|
+
* scroll lock | Scroll Lock
|
|
802
|
+
* ^ | Caret
|
|
803
|
+
* ! | Exclamation Point
|
|
804
|
+
* # | Hash
|
|
805
|
+
* $ | Dollar Sign
|
|
806
|
+
* ù | Grave Accent U
|
|
807
|
+
* page backward | Page Backward
|
|
808
|
+
* page forward | Page Forward
|
|
809
|
+
* closing paren (AZERTY) | Closing Parenthesis (AZERTY)
|
|
810
|
+
* * | Asterisk
|
|
811
|
+
* ~ + * key | Tilde + Asterisk Key
|
|
812
|
+
* minus (firefox), mute/unmute | Minus (Firefox), Mute/Unmute
|
|
813
|
+
* decrease volume level | Decrease Volume Level
|
|
814
|
+
* increase volume level | Increase Volume Level
|
|
815
|
+
* next | Next
|
|
816
|
+
* previous | Previous
|
|
817
|
+
* stop | Stop
|
|
818
|
+
* play/pause | Play/Pause
|
|
819
|
+
* e-mail | Email
|
|
820
|
+
* mute/unmute (firefox) | Mute/Unmute (Firefox)
|
|
821
|
+
* decrease volume level (firefox) | Decrease Volume Level (Firefox)
|
|
822
|
+
* increase volume level (firefox) | Increase Volume Level (Firefox)
|
|
823
|
+
* semi-colon / ñ | Semicolon / ñ
|
|
824
|
+
* equal sign | Equal Sign
|
|
825
|
+
* comma | Comma
|
|
826
|
+
* dash | Dash
|
|
827
|
+
* period | Period
|
|
828
|
+
* forward slash / ç | Forward Slash / ç
|
|
829
|
+
* grave accent / ñ / æ | Grave Accent / ñ / æ
|
|
830
|
+
* ?, / or ° | ?, / or °
|
|
831
|
+
* numpad period (chrome) | Numpad Period (Chrome)
|
|
832
|
+
* open bracket | Open Bracket
|
|
833
|
+
* back slash | Backslash
|
|
834
|
+
* close bracket / å | Close Bracket / å
|
|
835
|
+
* single quote / ø | Single Quote / ø
|
|
836
|
+
* \` | Backtick
|
|
837
|
+
* left or right ⌘ key (firefox) | Left or Right Command Key (Firefox)
|
|
838
|
+
* altgr | AltGr
|
|
839
|
+
* < /git > | < /git >
|
|
840
|
+
* GNOME Compose Key | GNOME Compose Key
|
|
841
|
+
* ç | ç
|
|
842
|
+
* XF86Forward | XF86Forward
|
|
843
|
+
* XF86Back | XF86Back
|
|
844
|
+
* alphanumeric | Alphanumeric
|
|
845
|
+
* hiragana/katakana | Hiragana/Katakana
|
|
846
|
+
* half-width/full-width | Half-Width/Full-Width
|
|
847
|
+
* kanji | Kanji
|
|
848
|
+
* toggle touchpad | Toggle Touchpad
|
|
849
|
+
*
|
|
850
|
+
* @title Set Inputs
|
|
851
|
+
* @method setInputs(inputs)
|
|
852
|
+
* @param {object} inputs
|
|
853
|
+
* @memberof KeyboardControls
|
|
854
|
+
*/
|
|
855
|
+
setInputs(inputs) {
|
|
856
|
+
if (!inputs) return;
|
|
857
|
+
this.boundKeys = {};
|
|
858
|
+
let inputsTransformed = {};
|
|
859
|
+
for (let control in inputs) {
|
|
860
|
+
const option = inputs[control];
|
|
861
|
+
const { bind } = option;
|
|
862
|
+
let inputsKey = bind;
|
|
863
|
+
if (!Array.isArray(inputsKey)) {
|
|
864
|
+
inputsKey = [bind];
|
|
865
|
+
}
|
|
866
|
+
for (let input of inputsKey) {
|
|
867
|
+
this.bindKey(input, control, option);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
this._controlsOptions = inputs;
|
|
871
|
+
}
|
|
872
|
+
get options() {
|
|
873
|
+
return this._controlsOptions;
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
registerDirective("controls", KeyboardControls);
|
|
877
|
+
|
|
878
|
+
// src/directives/Scheduler.ts
|
|
879
|
+
var Scheduler = class extends Directive {
|
|
880
|
+
constructor() {
|
|
881
|
+
super(...arguments);
|
|
882
|
+
this.fps = 60;
|
|
883
|
+
this.deltaTime = 0;
|
|
884
|
+
this.frame = 0;
|
|
885
|
+
this.timestamp = 0;
|
|
886
|
+
this.requestedDelay = 0;
|
|
887
|
+
this.lastTimestamp = 0;
|
|
888
|
+
this._stop = false;
|
|
889
|
+
}
|
|
890
|
+
onInit(element) {
|
|
891
|
+
this.tick = element.propObservables?.tick;
|
|
892
|
+
}
|
|
893
|
+
onDestroy() {
|
|
894
|
+
}
|
|
895
|
+
onMount(element) {
|
|
896
|
+
}
|
|
897
|
+
onUpdate(props) {
|
|
898
|
+
}
|
|
899
|
+
nextTick(timestamp) {
|
|
900
|
+
this.lastTimestamp = this.lastTimestamp || this.timestamp;
|
|
901
|
+
this.deltaTime = preciseNow() - this.timestamp;
|
|
902
|
+
this.timestamp = timestamp;
|
|
903
|
+
this.tick.set({
|
|
904
|
+
timestamp: this.timestamp,
|
|
905
|
+
deltaTime: this.deltaTime,
|
|
906
|
+
frame: this.frame,
|
|
907
|
+
deltaRatio: ~~this.deltaTime / ~~fps2ms(this.fps)
|
|
908
|
+
});
|
|
909
|
+
this.lastTimestamp = this.timestamp;
|
|
910
|
+
this.frame++;
|
|
911
|
+
}
|
|
912
|
+
/**
|
|
913
|
+
* start the schedule
|
|
914
|
+
* @return {Scheduler} returns this scheduler instance
|
|
915
|
+
*/
|
|
916
|
+
start(options = {}) {
|
|
917
|
+
if (options.maxFps) this.maxFps = options.maxFps;
|
|
918
|
+
if (options.fps) this.fps = options.fps;
|
|
919
|
+
if (options.delay) this.requestedDelay = options.delay;
|
|
920
|
+
const requestAnimationFrame = (fn) => {
|
|
921
|
+
if (isBrowser()) {
|
|
922
|
+
window.requestAnimationFrame(fn.bind(this));
|
|
923
|
+
} else {
|
|
924
|
+
setTimeout(() => {
|
|
925
|
+
this.requestedDelay = 0;
|
|
926
|
+
fn(preciseNow());
|
|
927
|
+
}, fps2ms(this.fps) + this.requestedDelay);
|
|
928
|
+
}
|
|
929
|
+
};
|
|
930
|
+
if (!this.maxFps) {
|
|
931
|
+
const loop2 = (timestamp) => {
|
|
932
|
+
requestAnimationFrame(loop2);
|
|
933
|
+
this.nextTick(timestamp);
|
|
934
|
+
};
|
|
935
|
+
requestAnimationFrame(loop2);
|
|
936
|
+
} else {
|
|
937
|
+
const msInterval = fps2ms(this.maxFps);
|
|
938
|
+
let now = preciseNow();
|
|
939
|
+
let then = preciseNow();
|
|
940
|
+
const loop2 = (timestamp) => {
|
|
941
|
+
if (this._stop) return;
|
|
942
|
+
requestAnimationFrame(loop2);
|
|
943
|
+
now = preciseNow();
|
|
944
|
+
const elapsed = now - then;
|
|
945
|
+
if (elapsed > msInterval) {
|
|
946
|
+
then = now - elapsed % msInterval;
|
|
947
|
+
this.nextTick(timestamp);
|
|
948
|
+
}
|
|
949
|
+
};
|
|
950
|
+
requestAnimationFrame(loop2);
|
|
951
|
+
}
|
|
952
|
+
return this;
|
|
953
|
+
}
|
|
954
|
+
stop() {
|
|
955
|
+
this._stop = true;
|
|
956
|
+
}
|
|
957
|
+
};
|
|
958
|
+
registerDirective("tick", Scheduler);
|
|
959
|
+
|
|
960
|
+
// src/directives/ViewportFollow.ts
|
|
961
|
+
var ViewportFollow = class extends Directive {
|
|
962
|
+
onInit(element) {
|
|
963
|
+
}
|
|
964
|
+
onMount(element) {
|
|
965
|
+
const { viewportFollow } = element.props;
|
|
966
|
+
const { viewport } = element.props.context;
|
|
967
|
+
if (!viewport) {
|
|
968
|
+
throw error("ViewportFollow directive requires a Viewport component to be mounted in the same context");
|
|
969
|
+
}
|
|
970
|
+
viewport.follow(element.componentInstance);
|
|
971
|
+
}
|
|
972
|
+
onUpdate(props) {
|
|
973
|
+
}
|
|
974
|
+
onDestroy() {
|
|
975
|
+
}
|
|
976
|
+
};
|
|
977
|
+
registerDirective("viewportFollow", ViewportFollow);
|
|
978
|
+
|
|
979
|
+
// src/directives/Sound.ts
|
|
980
|
+
import { effect } from "@signe/reactive";
|
|
981
|
+
import { Howl } from "howler";
|
|
982
|
+
var EVENTS = ["load", "loaderror", "playerror", "play", "end", "pause", "stop", "mute", "volume", "rate", "seek", "fade", "unlock"];
|
|
983
|
+
var Sound = class extends Directive {
|
|
984
|
+
constructor() {
|
|
985
|
+
super(...arguments);
|
|
986
|
+
this.eventsFn = [];
|
|
987
|
+
this.maxVolume = 1;
|
|
988
|
+
this.maxDistance = 100;
|
|
989
|
+
}
|
|
990
|
+
onInit(element) {
|
|
991
|
+
}
|
|
992
|
+
onMount(element) {
|
|
993
|
+
const { props } = element;
|
|
994
|
+
const tick2 = props.context.tick;
|
|
995
|
+
const { src, autoplay, loop: loop2, volume, spatial } = props.sound;
|
|
996
|
+
this.sound = new Howl({
|
|
997
|
+
src,
|
|
998
|
+
autoplay,
|
|
999
|
+
loop: loop2,
|
|
1000
|
+
volume
|
|
1001
|
+
});
|
|
1002
|
+
for (let event of EVENTS) {
|
|
1003
|
+
if (!props.sound[event]) continue;
|
|
1004
|
+
const fn = props.sound[event];
|
|
1005
|
+
this.eventsFn.push(fn);
|
|
1006
|
+
this.sound.on(event, fn);
|
|
1007
|
+
}
|
|
1008
|
+
if (spatial) {
|
|
1009
|
+
const { soundListenerPosition } = props.context;
|
|
1010
|
+
if (!soundListenerPosition) {
|
|
1011
|
+
throw new error("SoundListenerPosition directive is required for spatial sound in component parent");
|
|
1012
|
+
}
|
|
1013
|
+
const { x: listenerX, y: listenerY } = soundListenerPosition;
|
|
1014
|
+
this.tickSubscription = effect(() => {
|
|
1015
|
+
tick2();
|
|
1016
|
+
const { x, y } = element.componentInstance;
|
|
1017
|
+
const distance = calculateDistance(x, y, listenerX(), listenerY());
|
|
1018
|
+
const volume2 = Math.max(this.maxVolume - distance / this.maxDistance, 0);
|
|
1019
|
+
this.sound.volume(volume2);
|
|
1020
|
+
}).subscription;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
onUpdate(props) {
|
|
1024
|
+
const { volume, loop: loop2, mute, seek, playing, rate, spatial } = props;
|
|
1025
|
+
if (volume != void 0) this.sound.volume(volume);
|
|
1026
|
+
if (loop2 != void 0) this.sound.loop(loop2);
|
|
1027
|
+
if (mute != void 0) this.sound.mute(mute);
|
|
1028
|
+
if (seek != void 0) this.sound.seek(seek);
|
|
1029
|
+
if (playing != void 0) {
|
|
1030
|
+
if (playing) this.sound.play();
|
|
1031
|
+
else this.sound.pause();
|
|
1032
|
+
}
|
|
1033
|
+
if (spatial) {
|
|
1034
|
+
this.maxVolume = spatial.maxVolume ?? this.maxVolume;
|
|
1035
|
+
this.maxDistance = spatial.maxDistance ?? this.maxDistance;
|
|
1036
|
+
}
|
|
1037
|
+
if (rate != void 0) this.sound.rate(rate);
|
|
1038
|
+
}
|
|
1039
|
+
onDestroy() {
|
|
1040
|
+
this.sound.stop();
|
|
1041
|
+
this.tickSubscription?.unsubscribe();
|
|
1042
|
+
for (let event of EVENTS) {
|
|
1043
|
+
if (this.eventsFn[event]) {
|
|
1044
|
+
this.sound.off(event, this.eventsFn[event]);
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
1049
|
+
var SoundListenerPosition = class extends Directive {
|
|
1050
|
+
onMount(element) {
|
|
1051
|
+
element.props.context.soundListenerPosition = element.propObservables?.soundListenerPosition;
|
|
1052
|
+
}
|
|
1053
|
+
onInit(element) {
|
|
1054
|
+
}
|
|
1055
|
+
onUpdate(props) {
|
|
1056
|
+
}
|
|
1057
|
+
onDestroy() {
|
|
1058
|
+
}
|
|
1059
|
+
};
|
|
1060
|
+
registerDirective("sound", Sound);
|
|
1061
|
+
registerDirective("soundListenerPosition", SoundListenerPosition);
|
|
1062
|
+
|
|
1063
|
+
// src/directives/Drag.ts
|
|
1064
|
+
import { effect as effect2, isSignal } from "@signe/reactive";
|
|
1065
|
+
import { Rectangle } from "pixi.js";
|
|
1066
|
+
import { snap } from "popmotion";
|
|
1067
|
+
|
|
1068
|
+
// src/directives/Transition.ts
|
|
1069
|
+
import { DisplacementFilter, Sprite, Texture, WRAP_MODES } from "pixi.js";
|
|
1070
|
+
import { animate } from "popmotion";
|
|
1071
|
+
var Transition = class extends Directive {
|
|
1072
|
+
onInit(element) {
|
|
1073
|
+
}
|
|
1074
|
+
onMount(element) {
|
|
1075
|
+
const { image } = element.props.transition;
|
|
1076
|
+
const displacementSprite = new Sprite(Texture.from(image));
|
|
1077
|
+
displacementSprite.texture.baseTexture.wrapMode = WRAP_MODES.REPEAT;
|
|
1078
|
+
const displacementFilter = new DisplacementFilter(displacementSprite);
|
|
1079
|
+
const instance = element.componentInstance;
|
|
1080
|
+
instance.filters = [displacementFilter];
|
|
1081
|
+
instance.addChild(displacementSprite);
|
|
1082
|
+
setTimeout(() => {
|
|
1083
|
+
animate({
|
|
1084
|
+
from: 0,
|
|
1085
|
+
to: 1,
|
|
1086
|
+
duration: 500,
|
|
1087
|
+
onUpdate: (progress) => {
|
|
1088
|
+
displacementFilter.scale.x = progress;
|
|
1089
|
+
displacementFilter.scale.y = progress;
|
|
1090
|
+
}
|
|
1091
|
+
});
|
|
1092
|
+
}, 5e3);
|
|
1093
|
+
}
|
|
1094
|
+
onUpdate(props) {
|
|
1095
|
+
}
|
|
1096
|
+
onDestroy() {
|
|
1097
|
+
}
|
|
1098
|
+
};
|
|
1099
|
+
registerDirective("transition", Transition);
|
|
1100
|
+
|
|
1101
|
+
// src/index.ts
|
|
1102
|
+
export * from "@signe/reactive";
|
|
1103
|
+
import { Howler } from "howler";
|
|
1104
|
+
|
|
1105
|
+
// src/components/Canvas.ts
|
|
1106
|
+
import { effect as effect4, signal as signal3 } from "@signe/reactive";
|
|
1107
|
+
import { Container as Container3, autoDetectRenderer } from "pixi.js";
|
|
1108
|
+
import { loadYoga } from "yoga-layout";
|
|
1109
|
+
|
|
1110
|
+
// src/engine/reactive.ts
|
|
1111
|
+
import { isSignal as isSignal2 } from "@signe/reactive";
|
|
1112
|
+
import {
|
|
1113
|
+
Observable,
|
|
1114
|
+
Subject,
|
|
1115
|
+
defer,
|
|
1116
|
+
from,
|
|
1117
|
+
map,
|
|
1118
|
+
of,
|
|
1119
|
+
switchMap
|
|
1120
|
+
} from "rxjs";
|
|
1121
|
+
var components = {};
|
|
1122
|
+
var isElement = (value) => {
|
|
1123
|
+
return value && typeof value === "object" && "tag" in value && "props" in value && "componentInstance" in value;
|
|
1124
|
+
};
|
|
1125
|
+
var isPrimitive = (value) => {
|
|
1126
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null || value === void 0;
|
|
1127
|
+
};
|
|
1128
|
+
function registerComponent(name, component) {
|
|
1129
|
+
components[name] = component;
|
|
1130
|
+
}
|
|
1131
|
+
function destroyElement(element) {
|
|
1132
|
+
if (Array.isArray(element)) {
|
|
1133
|
+
element.forEach((e) => destroyElement(e));
|
|
1134
|
+
return;
|
|
1135
|
+
}
|
|
1136
|
+
if (!element) {
|
|
1137
|
+
return;
|
|
1138
|
+
}
|
|
1139
|
+
element.propSubscriptions.forEach((sub) => sub.unsubscribe());
|
|
1140
|
+
element.effectSubscriptions.forEach((sub) => sub.unsubscribe());
|
|
1141
|
+
for (let name in element.directives) {
|
|
1142
|
+
element.directives[name].onDestroy?.();
|
|
1143
|
+
}
|
|
1144
|
+
element.componentInstance.onDestroy?.(element.parent);
|
|
1145
|
+
element.effectUnmounts.forEach((fn) => fn?.());
|
|
1146
|
+
}
|
|
1147
|
+
function createComponent(tag, props) {
|
|
1148
|
+
if (!components[tag]) {
|
|
1149
|
+
throw new Error(`Component ${tag} is not registered`);
|
|
1150
|
+
}
|
|
1151
|
+
const instance = new components[tag]();
|
|
1152
|
+
const element = {
|
|
1153
|
+
tag,
|
|
1154
|
+
props: {},
|
|
1155
|
+
componentInstance: instance,
|
|
1156
|
+
propSubscriptions: [],
|
|
1157
|
+
propObservables: props,
|
|
1158
|
+
parent: null,
|
|
1159
|
+
directives: {},
|
|
1160
|
+
effectUnmounts: [],
|
|
1161
|
+
effectSubscriptions: [],
|
|
1162
|
+
effectMounts: [],
|
|
1163
|
+
destroy() {
|
|
1164
|
+
destroyElement(this);
|
|
1165
|
+
},
|
|
1166
|
+
allElements: new Subject()
|
|
1167
|
+
};
|
|
1168
|
+
if (props) {
|
|
1169
|
+
const recursiveProps = (props2, path = "") => {
|
|
1170
|
+
const _set = (path2, key, value) => {
|
|
1171
|
+
if (path2 == "") {
|
|
1172
|
+
element.props[key] = value;
|
|
1173
|
+
return;
|
|
1174
|
+
}
|
|
1175
|
+
set(element.props, path2 + "." + key, value);
|
|
1176
|
+
};
|
|
1177
|
+
Object.entries(props2).forEach(([key, value]) => {
|
|
1178
|
+
if (isSignal2(value)) {
|
|
1179
|
+
const _value = value;
|
|
1180
|
+
if ("dependencies" in _value && _value.dependencies.size == 0) {
|
|
1181
|
+
_set(path, key, _value());
|
|
1182
|
+
return;
|
|
1183
|
+
}
|
|
1184
|
+
element.propSubscriptions.push(
|
|
1185
|
+
_value.observable.subscribe((value2) => {
|
|
1186
|
+
_set(path, key, value2);
|
|
1187
|
+
if (element.directives[key]) {
|
|
1188
|
+
element.directives[key].onUpdate?.(value2);
|
|
1189
|
+
}
|
|
1190
|
+
if (key == "tick") {
|
|
1191
|
+
return;
|
|
1192
|
+
}
|
|
1193
|
+
instance.onUpdate?.(
|
|
1194
|
+
path == "" ? {
|
|
1195
|
+
[key]: value2
|
|
1196
|
+
} : set({}, path + "." + key, value2)
|
|
1197
|
+
);
|
|
1198
|
+
})
|
|
1199
|
+
);
|
|
1200
|
+
} else {
|
|
1201
|
+
if (isObject(value) && key != "context" && !isElement(value)) {
|
|
1202
|
+
recursiveProps(value, (path ? path + "." : "") + key);
|
|
1203
|
+
} else {
|
|
1204
|
+
_set(path, key, value);
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
});
|
|
1208
|
+
};
|
|
1209
|
+
recursiveProps(props);
|
|
1210
|
+
}
|
|
1211
|
+
instance.onInit?.(element.props);
|
|
1212
|
+
instance.onUpdate?.(element.props);
|
|
1213
|
+
const onMount = (parent, element2, index) => {
|
|
1214
|
+
element2.props.context = parent.props.context;
|
|
1215
|
+
element2.parent = parent;
|
|
1216
|
+
element2.componentInstance.onMount?.(element2, index);
|
|
1217
|
+
for (let name in element2.directives) {
|
|
1218
|
+
element2.directives[name].onMount?.(element2);
|
|
1219
|
+
}
|
|
1220
|
+
element2.effectMounts.forEach((fn) => {
|
|
1221
|
+
element2.effectUnmounts.push(fn(element2));
|
|
1222
|
+
});
|
|
1223
|
+
};
|
|
1224
|
+
const elementsListen = new Subject();
|
|
1225
|
+
if (props?.isRoot) {
|
|
1226
|
+
const propagateContext = async (element2) => {
|
|
1227
|
+
if (element2.props.attach) {
|
|
1228
|
+
const isReactiveAttach = isSignal2(element2.propObservables?.attach);
|
|
1229
|
+
if (!isReactiveAttach) {
|
|
1230
|
+
element2.props.children.push(element2.props.attach);
|
|
1231
|
+
} else {
|
|
1232
|
+
let lastElement = null;
|
|
1233
|
+
element2.propObservables.attach.observable.subscribe(({ value, type }) => {
|
|
1234
|
+
if (type != "init") {
|
|
1235
|
+
destroyElement(lastElement);
|
|
1236
|
+
}
|
|
1237
|
+
lastElement = value;
|
|
1238
|
+
onMount(element2, value);
|
|
1239
|
+
propagateContext(value);
|
|
1240
|
+
});
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
if (!element2.props.children) {
|
|
1244
|
+
return;
|
|
1245
|
+
}
|
|
1246
|
+
for (let child of element2.props.children) {
|
|
1247
|
+
if (!child) continue;
|
|
1248
|
+
if (isPromise(child)) {
|
|
1249
|
+
child = await child;
|
|
1250
|
+
}
|
|
1251
|
+
if (child instanceof Observable) {
|
|
1252
|
+
child.subscribe(
|
|
1253
|
+
({
|
|
1254
|
+
elements: comp,
|
|
1255
|
+
prev
|
|
1256
|
+
}) => {
|
|
1257
|
+
const components2 = comp.filter((c) => c !== null);
|
|
1258
|
+
if (prev) {
|
|
1259
|
+
components2.forEach((c) => {
|
|
1260
|
+
const index = element2.props.children.indexOf(prev.props.key);
|
|
1261
|
+
onMount(element2, c, index + 1);
|
|
1262
|
+
propagateContext(c);
|
|
1263
|
+
});
|
|
1264
|
+
return;
|
|
1265
|
+
}
|
|
1266
|
+
components2.forEach((component) => {
|
|
1267
|
+
if (!Array.isArray(component)) {
|
|
1268
|
+
onMount(element2, component);
|
|
1269
|
+
propagateContext(component);
|
|
1270
|
+
} else {
|
|
1271
|
+
component.forEach((comp2) => {
|
|
1272
|
+
onMount(element2, comp2);
|
|
1273
|
+
propagateContext(comp2);
|
|
1274
|
+
});
|
|
1275
|
+
}
|
|
1276
|
+
});
|
|
1277
|
+
elementsListen.next(void 0);
|
|
1278
|
+
}
|
|
1279
|
+
);
|
|
1280
|
+
} else {
|
|
1281
|
+
onMount(element2, child);
|
|
1282
|
+
await propagateContext(child);
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
};
|
|
1286
|
+
element.allElements = elementsListen;
|
|
1287
|
+
element.props.context.rootElement = element;
|
|
1288
|
+
element.componentInstance.onMount?.(element);
|
|
1289
|
+
propagateContext(element);
|
|
1290
|
+
}
|
|
1291
|
+
if (props) {
|
|
1292
|
+
for (let key in props) {
|
|
1293
|
+
const directive = applyDirective(element, key);
|
|
1294
|
+
if (directive) element.directives[key] = directive;
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
return element;
|
|
1298
|
+
}
|
|
1299
|
+
function loop(itemsSubject, createElementFn) {
|
|
1300
|
+
let elements = [];
|
|
1301
|
+
const addAt = (items, insertIndex) => {
|
|
1302
|
+
return items.map((item, index) => {
|
|
1303
|
+
const element = createElementFn(item, insertIndex + index);
|
|
1304
|
+
elements.splice(insertIndex + index, 0, element);
|
|
1305
|
+
return element;
|
|
1306
|
+
});
|
|
1307
|
+
};
|
|
1308
|
+
return defer(() => {
|
|
1309
|
+
let initialItems = [...itemsSubject._subject.items];
|
|
1310
|
+
let init = true;
|
|
1311
|
+
return itemsSubject.observable.pipe(
|
|
1312
|
+
map((event) => {
|
|
1313
|
+
const { type, items, index } = event;
|
|
1314
|
+
if (init) {
|
|
1315
|
+
if (elements.length > 0) {
|
|
1316
|
+
return {
|
|
1317
|
+
elements,
|
|
1318
|
+
fullElements: elements
|
|
1319
|
+
};
|
|
1320
|
+
}
|
|
1321
|
+
const newElements = addAt(initialItems, 0);
|
|
1322
|
+
initialItems = [];
|
|
1323
|
+
init = false;
|
|
1324
|
+
return {
|
|
1325
|
+
elements: newElements,
|
|
1326
|
+
fullElements: elements
|
|
1327
|
+
};
|
|
1328
|
+
} else if (type == "reset") {
|
|
1329
|
+
if (elements.length != 0) {
|
|
1330
|
+
elements.forEach((element) => {
|
|
1331
|
+
destroyElement(element);
|
|
1332
|
+
});
|
|
1333
|
+
elements = [];
|
|
1334
|
+
}
|
|
1335
|
+
const newElements = addAt(items, 0);
|
|
1336
|
+
return {
|
|
1337
|
+
elements: newElements,
|
|
1338
|
+
fullElements: elements
|
|
1339
|
+
};
|
|
1340
|
+
} else if (type == "add" && index != void 0) {
|
|
1341
|
+
const lastElement = elements[index - 1];
|
|
1342
|
+
const newElements = addAt(items, index);
|
|
1343
|
+
return {
|
|
1344
|
+
prev: lastElement,
|
|
1345
|
+
elements: newElements,
|
|
1346
|
+
fullElements: elements
|
|
1347
|
+
};
|
|
1348
|
+
} else if (index != void 0 && type == "remove") {
|
|
1349
|
+
const currentElement = elements[index];
|
|
1350
|
+
destroyElement(currentElement);
|
|
1351
|
+
elements.splice(index, 1);
|
|
1352
|
+
return {
|
|
1353
|
+
elements: []
|
|
1354
|
+
};
|
|
1355
|
+
}
|
|
1356
|
+
return {
|
|
1357
|
+
elements: [],
|
|
1358
|
+
fullElements: elements
|
|
1359
|
+
};
|
|
1360
|
+
})
|
|
1361
|
+
);
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1364
|
+
function cond(condition, createElementFn) {
|
|
1365
|
+
let element = null;
|
|
1366
|
+
return condition.observable.pipe(
|
|
1367
|
+
switchMap((bool) => {
|
|
1368
|
+
if (bool) {
|
|
1369
|
+
let _el = createElementFn();
|
|
1370
|
+
if (isPromise(_el)) {
|
|
1371
|
+
return from(_el).pipe(
|
|
1372
|
+
map((el) => {
|
|
1373
|
+
element = _el;
|
|
1374
|
+
return {
|
|
1375
|
+
type: "init",
|
|
1376
|
+
elements: [el]
|
|
1377
|
+
};
|
|
1378
|
+
})
|
|
1379
|
+
);
|
|
1380
|
+
}
|
|
1381
|
+
element = _el;
|
|
1382
|
+
return of({
|
|
1383
|
+
type: "init",
|
|
1384
|
+
elements: [element]
|
|
1385
|
+
});
|
|
1386
|
+
} else if (element) {
|
|
1387
|
+
destroyElement(element);
|
|
1388
|
+
}
|
|
1389
|
+
return of({
|
|
1390
|
+
elements: []
|
|
1391
|
+
});
|
|
1392
|
+
})
|
|
1393
|
+
);
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
// src/hooks/useProps.ts
|
|
1397
|
+
import { isSignal as isSignal3, signal } from "@signe/reactive";
|
|
1398
|
+
var useProps = (props, defaults = {}) => {
|
|
1399
|
+
if (isSignal3(props)) {
|
|
1400
|
+
return props();
|
|
1401
|
+
}
|
|
1402
|
+
const obj = {};
|
|
1403
|
+
for (let key in props) {
|
|
1404
|
+
const value = props[key];
|
|
1405
|
+
obj[key] = isPrimitive(value) ? signal(value) : value;
|
|
1406
|
+
}
|
|
1407
|
+
for (let key in defaults) {
|
|
1408
|
+
if (!(key in obj)) {
|
|
1409
|
+
obj[key] = signal(defaults[key]);
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
return obj;
|
|
1413
|
+
};
|
|
1414
|
+
var useDefineProps = (props) => {
|
|
1415
|
+
return (schema) => {
|
|
1416
|
+
const rawProps = isSignal3(props) ? props() : props;
|
|
1417
|
+
const validatedProps = {};
|
|
1418
|
+
for (const key in schema) {
|
|
1419
|
+
const propConfig = schema[key];
|
|
1420
|
+
const value = rawProps[key];
|
|
1421
|
+
let validatedValue;
|
|
1422
|
+
if (typeof propConfig === "function") {
|
|
1423
|
+
validateType(key, value, [propConfig]);
|
|
1424
|
+
validatedValue = value;
|
|
1425
|
+
} else if (Array.isArray(propConfig)) {
|
|
1426
|
+
validateType(key, value, propConfig);
|
|
1427
|
+
validatedValue = value;
|
|
1428
|
+
} else if (propConfig && typeof propConfig === "object") {
|
|
1429
|
+
if (propConfig.required && value === void 0) {
|
|
1430
|
+
throw new Error(`Missing required prop: ${key}`);
|
|
1431
|
+
}
|
|
1432
|
+
if (propConfig.type) {
|
|
1433
|
+
const types = Array.isArray(propConfig.type) ? propConfig.type : [propConfig.type];
|
|
1434
|
+
validateType(key, value, types);
|
|
1435
|
+
}
|
|
1436
|
+
if (propConfig.validator && !propConfig.validator(value, rawProps)) {
|
|
1437
|
+
throw new Error(`Invalid prop: custom validation failed for prop "${key}"`);
|
|
1438
|
+
}
|
|
1439
|
+
if (value === void 0 && "default" in propConfig) {
|
|
1440
|
+
validatedValue = typeof propConfig.default === "function" ? propConfig.default(rawProps) : propConfig.default;
|
|
1441
|
+
} else {
|
|
1442
|
+
validatedValue = value;
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
validatedProps[key] = isSignal3(validatedValue) ? validatedValue : signal(validatedValue);
|
|
1446
|
+
}
|
|
1447
|
+
return {
|
|
1448
|
+
...useProps(rawProps),
|
|
1449
|
+
...validatedProps
|
|
1450
|
+
};
|
|
1451
|
+
};
|
|
1452
|
+
};
|
|
1453
|
+
function validateType(key, value, types) {
|
|
1454
|
+
if (value === void 0 || value === null) return;
|
|
1455
|
+
const valueToCheck = isSignal3(value) ? value() : value;
|
|
1456
|
+
const valid = types.some((type) => {
|
|
1457
|
+
if (type === Number) return typeof valueToCheck === "number";
|
|
1458
|
+
if (type === String) return typeof valueToCheck === "string";
|
|
1459
|
+
if (type === Boolean) return typeof valueToCheck === "boolean";
|
|
1460
|
+
if (type === Function) return typeof valueToCheck === "function";
|
|
1461
|
+
if (type === Object) return typeof valueToCheck === "object";
|
|
1462
|
+
if (type === Array) return Array.isArray(valueToCheck);
|
|
1463
|
+
if (type === null) return valueToCheck === null;
|
|
1464
|
+
return valueToCheck instanceof type;
|
|
1465
|
+
});
|
|
1466
|
+
if (!valid) {
|
|
1467
|
+
throw new Error(
|
|
1468
|
+
`Invalid prop: type check failed for prop "${key}". Expected ${types.map((t) => t.name).join(" or ")}`
|
|
1469
|
+
);
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
// src/components/DisplayObject.ts
|
|
1474
|
+
import { effect as effect3, signal as signal2 } from "@signe/reactive";
|
|
1475
|
+
import { DropShadowFilter } from "pixi-filters";
|
|
1476
|
+
import { BlurFilter, ObservablePoint } from "pixi.js";
|
|
1477
|
+
var EVENTS2 = [
|
|
1478
|
+
"added",
|
|
1479
|
+
"childAdded",
|
|
1480
|
+
"childRemoved",
|
|
1481
|
+
"click",
|
|
1482
|
+
"clickcapture",
|
|
1483
|
+
"destroyed",
|
|
1484
|
+
"globalmousemove",
|
|
1485
|
+
"globalpointermove",
|
|
1486
|
+
"globaltouchmove",
|
|
1487
|
+
"mousedown",
|
|
1488
|
+
"mousedowncapture",
|
|
1489
|
+
"mouseenter",
|
|
1490
|
+
"mouseentercapture",
|
|
1491
|
+
"mouseleave",
|
|
1492
|
+
"mouseleavecapture",
|
|
1493
|
+
"mousemove",
|
|
1494
|
+
"mousemovecapture",
|
|
1495
|
+
"mouseout",
|
|
1496
|
+
"mouseoutcapture",
|
|
1497
|
+
"mouseover",
|
|
1498
|
+
"mouseovercapture",
|
|
1499
|
+
"mouseup",
|
|
1500
|
+
"mouseupcapture",
|
|
1501
|
+
"mouseupoutside",
|
|
1502
|
+
"mouseupoutsidecapture",
|
|
1503
|
+
"pointercancel",
|
|
1504
|
+
"pointercancelcapture",
|
|
1505
|
+
"pointerdown",
|
|
1506
|
+
"pointerdowncapture",
|
|
1507
|
+
"pointerenter",
|
|
1508
|
+
"pointerentercapture",
|
|
1509
|
+
"pointerleave",
|
|
1510
|
+
"pointerleavecapture",
|
|
1511
|
+
"pointermove",
|
|
1512
|
+
"pointermovecapture",
|
|
1513
|
+
"pointerout",
|
|
1514
|
+
"pointeroutcapture",
|
|
1515
|
+
"pointerover",
|
|
1516
|
+
"pointerovercapture",
|
|
1517
|
+
"pointertap",
|
|
1518
|
+
"pointertapcapture",
|
|
1519
|
+
"pointerup",
|
|
1520
|
+
"pointerupcapture",
|
|
1521
|
+
"pointerupoutside",
|
|
1522
|
+
"pointerupoutsidecapture",
|
|
1523
|
+
"removed",
|
|
1524
|
+
"rightclick",
|
|
1525
|
+
"rightclickcapture",
|
|
1526
|
+
"rightdown",
|
|
1527
|
+
"rightdowncapture",
|
|
1528
|
+
"rightup",
|
|
1529
|
+
"rightupcapture",
|
|
1530
|
+
"rightupoutside",
|
|
1531
|
+
"rightupoutsidecapture",
|
|
1532
|
+
"tap",
|
|
1533
|
+
"tapcapture",
|
|
1534
|
+
"touchcancel",
|
|
1535
|
+
"touchcancelcapture",
|
|
1536
|
+
"touchend",
|
|
1537
|
+
"touchendcapture",
|
|
1538
|
+
"touchendoutside",
|
|
1539
|
+
"touchendoutsidecapture",
|
|
1540
|
+
"touchmove",
|
|
1541
|
+
"touchmovecapture",
|
|
1542
|
+
"touchstart",
|
|
1543
|
+
"touchstartcapture",
|
|
1544
|
+
"wheel",
|
|
1545
|
+
"wheelcapture"
|
|
1546
|
+
];
|
|
1547
|
+
function DisplayObject(extendClass) {
|
|
1548
|
+
var _canvasContext, _DisplayObject_instances, applyFlexLayout_fn, flexRender_fn, setAlign_fn, setEdgeSize_fn, _a;
|
|
1549
|
+
return _a = class extends extendClass {
|
|
1550
|
+
constructor() {
|
|
1551
|
+
super(...arguments);
|
|
1552
|
+
__privateAdd(this, _DisplayObject_instances);
|
|
1553
|
+
__privateAdd(this, _canvasContext, null);
|
|
1554
|
+
this.isFlex = false;
|
|
1555
|
+
this.fullProps = {};
|
|
1556
|
+
this.isMounted = false;
|
|
1557
|
+
this._anchorPoints = new ObservablePoint(
|
|
1558
|
+
{ _onUpdate: () => {
|
|
1559
|
+
} },
|
|
1560
|
+
0,
|
|
1561
|
+
0
|
|
1562
|
+
);
|
|
1563
|
+
this.isCustomAnchor = false;
|
|
1564
|
+
this.displayWidth = signal2(0);
|
|
1565
|
+
this.displayHeight = signal2(0);
|
|
1566
|
+
this.overrideProps = [];
|
|
1567
|
+
}
|
|
1568
|
+
get yoga() {
|
|
1569
|
+
return __privateGet(this, _canvasContext)?.Yoga;
|
|
1570
|
+
}
|
|
1571
|
+
get deltaRatio() {
|
|
1572
|
+
return __privateGet(this, _canvasContext)?.scheduler?.tick.value.deltaRatio;
|
|
1573
|
+
}
|
|
1574
|
+
onInit(props) {
|
|
1575
|
+
this._id = props.id;
|
|
1576
|
+
for (let event of EVENTS2) {
|
|
1577
|
+
if (props[event] && !this.overrideProps.includes(event)) {
|
|
1578
|
+
this.eventMode = "static";
|
|
1579
|
+
this.on(event, props[event]);
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
onMount({ parent, props }, index) {
|
|
1584
|
+
__privateSet(this, _canvasContext, props.context);
|
|
1585
|
+
this.node = this.yoga.Node.create();
|
|
1586
|
+
if (parent) {
|
|
1587
|
+
const instance = parent.componentInstance;
|
|
1588
|
+
if (index === void 0) {
|
|
1589
|
+
instance.addChild(this);
|
|
1590
|
+
} else {
|
|
1591
|
+
instance.addChildAt(this, index);
|
|
1592
|
+
}
|
|
1593
|
+
if (instance.layer) this.parentLayer = instance.layer;
|
|
1594
|
+
this.isMounted = true;
|
|
1595
|
+
this.effectSize(props.width, props.height);
|
|
1596
|
+
this.onUpdate(props);
|
|
1597
|
+
this.parent.node.insertChild(
|
|
1598
|
+
this.node,
|
|
1599
|
+
this.parent.node.getChildCount()
|
|
1600
|
+
);
|
|
1601
|
+
if (parent.props.flexDirection) {
|
|
1602
|
+
this.parent.node.calculateLayout();
|
|
1603
|
+
for (let child of this.parent.children) {
|
|
1604
|
+
const { left, top } = child.getComputedLayout();
|
|
1605
|
+
child.x = left;
|
|
1606
|
+
child.y = top;
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
effectSize(width, height) {
|
|
1612
|
+
const handleSize = (size, setter, parentSize) => {
|
|
1613
|
+
if (typeof size === "string" && size.endsWith("%")) {
|
|
1614
|
+
effect3(() => {
|
|
1615
|
+
setter(parentSize() * (parseInt(size) / 100));
|
|
1616
|
+
if (this.isFlex) {
|
|
1617
|
+
__privateMethod(this, _DisplayObject_instances, applyFlexLayout_fn).call(this);
|
|
1618
|
+
}
|
|
1619
|
+
});
|
|
1620
|
+
} else {
|
|
1621
|
+
setter(+size);
|
|
1622
|
+
}
|
|
1623
|
+
};
|
|
1624
|
+
if (width != void 0)
|
|
1625
|
+
handleSize(width, this.setWidth.bind(this), this.parent.displayWidth);
|
|
1626
|
+
if (height != void 0)
|
|
1627
|
+
handleSize(
|
|
1628
|
+
height,
|
|
1629
|
+
this.setHeight.bind(this),
|
|
1630
|
+
this.parent.displayHeight
|
|
1631
|
+
);
|
|
1632
|
+
}
|
|
1633
|
+
onUpdate(props) {
|
|
1634
|
+
this.fullProps = {
|
|
1635
|
+
...this.fullProps,
|
|
1636
|
+
...props
|
|
1637
|
+
};
|
|
1638
|
+
if (!__privateGet(this, _canvasContext) || !this.parent) return;
|
|
1639
|
+
if (props.x !== void 0) this.setX(props.x);
|
|
1640
|
+
if (props.y !== void 0) this.setY(props.y);
|
|
1641
|
+
if (props.scale !== void 0)
|
|
1642
|
+
setObservablePoint(this.scale, props.scale);
|
|
1643
|
+
if (props.anchor !== void 0 && !this.isCustomAnchor) {
|
|
1644
|
+
setObservablePoint(this.anchor, props.anchor);
|
|
1645
|
+
}
|
|
1646
|
+
if (props.skew !== void 0) setObservablePoint(this.skew, props.skew);
|
|
1647
|
+
if (props.tint) this.tint = props.tint;
|
|
1648
|
+
if (props.rotation !== void 0) this.rotation = props.rotation;
|
|
1649
|
+
if (props.angle !== void 0) this.angle = props.angle;
|
|
1650
|
+
if (props.zIndex !== void 0) this.zIndex = props.zIndex;
|
|
1651
|
+
if (props.roundPixels !== void 0) this.roundPixels = props.roundPixels;
|
|
1652
|
+
if (props.cursor) this.cursor = props.cursor;
|
|
1653
|
+
if (props.visible !== void 0) this.visible = props.visible;
|
|
1654
|
+
if (props.alpha !== void 0) this.alpha = props.alpha;
|
|
1655
|
+
if (props.pivot) setObservablePoint(this.pivot, props.pivot);
|
|
1656
|
+
if (props.flexDirection) this.setFlexDirection(props.flexDirection);
|
|
1657
|
+
if (props.flexWrap) this.setFlexWrap(props.flexWrap);
|
|
1658
|
+
if (props.justifyContent) this.setJustifyContent(props.justifyContent);
|
|
1659
|
+
if (props.alignItems) this.setAlignItems(props.alignItems);
|
|
1660
|
+
if (props.alignContent) this.setAlignContent(props.alignContent);
|
|
1661
|
+
if (props.alignSelf) this.setAlignSelf(props.alignSelf);
|
|
1662
|
+
if (props.margin) this.setMargin(props.margin);
|
|
1663
|
+
if (props.padding) this.setPadding(props.padding);
|
|
1664
|
+
if (props.gap) this.setGap(props.gap);
|
|
1665
|
+
if (props.border) this.setBorder(props.border);
|
|
1666
|
+
if (props.positionType) this.setPositionType(props.positionType);
|
|
1667
|
+
if (props.filters) this.filters = props.filters;
|
|
1668
|
+
if (props.maskOf) {
|
|
1669
|
+
if (isElement(props.maskOf)) {
|
|
1670
|
+
props.maskOf.componentInstance.mask = this;
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
if (props.blendMode) this.blendMode = props.blendMode;
|
|
1674
|
+
if (props.filterArea) this.filterArea = props.filterArea;
|
|
1675
|
+
const currentFilters = this.filters || [];
|
|
1676
|
+
if (props.shadow) {
|
|
1677
|
+
let dropShadowFilter = currentFilters.find(
|
|
1678
|
+
(filter) => filter instanceof DropShadowFilter
|
|
1679
|
+
);
|
|
1680
|
+
if (!dropShadowFilter) {
|
|
1681
|
+
dropShadowFilter = new DropShadowFilter();
|
|
1682
|
+
currentFilters.push(dropShadowFilter);
|
|
1683
|
+
}
|
|
1684
|
+
Object.assign(dropShadowFilter, props.shadow);
|
|
1685
|
+
}
|
|
1686
|
+
if (props.blur) {
|
|
1687
|
+
let blurFilter = currentFilters.find(
|
|
1688
|
+
(filter) => filter instanceof BlurFilter
|
|
1689
|
+
);
|
|
1690
|
+
if (!blurFilter) {
|
|
1691
|
+
const options = typeof props.blur === "number" ? {
|
|
1692
|
+
strength: props.blur
|
|
1693
|
+
} : props.blur;
|
|
1694
|
+
blurFilter = new BlurFilter(options);
|
|
1695
|
+
currentFilters.push(blurFilter);
|
|
1696
|
+
}
|
|
1697
|
+
Object.assign(blurFilter, props.blur);
|
|
1698
|
+
}
|
|
1699
|
+
this.filters = currentFilters;
|
|
1700
|
+
__privateMethod(this, _DisplayObject_instances, flexRender_fn).call(this, props);
|
|
1701
|
+
}
|
|
1702
|
+
onDestroy() {
|
|
1703
|
+
super.destroy();
|
|
1704
|
+
this.node?.freeRecursive();
|
|
1705
|
+
}
|
|
1706
|
+
getComputedLayout() {
|
|
1707
|
+
return this.node.getComputedLayout();
|
|
1708
|
+
}
|
|
1709
|
+
applyComputedLayout() {
|
|
1710
|
+
const layout = this.getComputedLayout();
|
|
1711
|
+
this.x = layout.left;
|
|
1712
|
+
this.y = layout.top;
|
|
1713
|
+
}
|
|
1714
|
+
calculateLayout() {
|
|
1715
|
+
this.node.calculateLayout();
|
|
1716
|
+
}
|
|
1717
|
+
setFlexDirection(direction) {
|
|
1718
|
+
const mapping = {
|
|
1719
|
+
row: this.yoga.FLEX_DIRECTION_ROW,
|
|
1720
|
+
column: this.yoga.FLEX_DIRECTION_COLUMN,
|
|
1721
|
+
"row-reverse": this.yoga.FLEX_DIRECTION_ROW_REVERSE,
|
|
1722
|
+
"column-reverse": this.yoga.FLEX_DIRECTION_COLUMN_REVERSE
|
|
1723
|
+
};
|
|
1724
|
+
this.node.setFlexDirection(mapping[direction]);
|
|
1725
|
+
}
|
|
1726
|
+
setFlexWrap(wrap) {
|
|
1727
|
+
const mapping = {
|
|
1728
|
+
wrap: this.yoga.WRAP_WRAP,
|
|
1729
|
+
nowrap: this.yoga.WRAP_NO_WRAP,
|
|
1730
|
+
"wrap-reverse": this.yoga.WRAP_WRAP_REVERSE
|
|
1731
|
+
};
|
|
1732
|
+
this.node.setFlexWrap(mapping[wrap]);
|
|
1733
|
+
}
|
|
1734
|
+
setAlignContent(align) {
|
|
1735
|
+
__privateMethod(this, _DisplayObject_instances, setAlign_fn).call(this, "setAlignContent", align);
|
|
1736
|
+
}
|
|
1737
|
+
setAlignSelf(align) {
|
|
1738
|
+
__privateMethod(this, _DisplayObject_instances, setAlign_fn).call(this, "setAlignSelf", align);
|
|
1739
|
+
}
|
|
1740
|
+
setAlignItems(align) {
|
|
1741
|
+
__privateMethod(this, _DisplayObject_instances, setAlign_fn).call(this, "setAlignItems", align);
|
|
1742
|
+
}
|
|
1743
|
+
setJustifyContent(justifyContent) {
|
|
1744
|
+
const mapping = {
|
|
1745
|
+
"flex-start": this.yoga.JUSTIFY_FLEX_START,
|
|
1746
|
+
"flex-end": this.yoga.JUSTIFY_FLEX_END,
|
|
1747
|
+
center: this.yoga.JUSTIFY_CENTER,
|
|
1748
|
+
"space-between": this.yoga.JUSTIFY_SPACE_BETWEEN,
|
|
1749
|
+
"space-around": this.yoga.JUSTIFY_SPACE_AROUND
|
|
1750
|
+
};
|
|
1751
|
+
this.node.setJustifyContent(mapping[justifyContent]);
|
|
1752
|
+
}
|
|
1753
|
+
setPosition(position) {
|
|
1754
|
+
__privateMethod(this, _DisplayObject_instances, setEdgeSize_fn).call(this, "setPosition", position);
|
|
1755
|
+
}
|
|
1756
|
+
setX(x) {
|
|
1757
|
+
x = x + this.getWidth() * this._anchorPoints.x;
|
|
1758
|
+
if (!this.parent.isFlex) {
|
|
1759
|
+
this.x = x;
|
|
1760
|
+
}
|
|
1761
|
+
this.node.setPosition(this.yoga.EDGE_LEFT, x);
|
|
1762
|
+
}
|
|
1763
|
+
setY(y) {
|
|
1764
|
+
y = y + this.getHeight() * this._anchorPoints.y;
|
|
1765
|
+
if (!this.parent.isFlex) {
|
|
1766
|
+
this.y = y;
|
|
1767
|
+
}
|
|
1768
|
+
this.node.setPosition(this.yoga.EDGE_TOP, y);
|
|
1769
|
+
}
|
|
1770
|
+
setPadding(padding) {
|
|
1771
|
+
__privateMethod(this, _DisplayObject_instances, setEdgeSize_fn).call(this, "setPadding", padding);
|
|
1772
|
+
}
|
|
1773
|
+
setMargin(margin) {
|
|
1774
|
+
__privateMethod(this, _DisplayObject_instances, setEdgeSize_fn).call(this, "setMargin", margin);
|
|
1775
|
+
}
|
|
1776
|
+
setGap(gap) {
|
|
1777
|
+
this.node.setGap(this.yoga.GAP_ALL, +gap);
|
|
1778
|
+
}
|
|
1779
|
+
setBorder(border) {
|
|
1780
|
+
__privateMethod(this, _DisplayObject_instances, setEdgeSize_fn).call(this, "setBorder", border);
|
|
1781
|
+
}
|
|
1782
|
+
setPositionType(positionType) {
|
|
1783
|
+
const mapping = {
|
|
1784
|
+
relative: this.yoga.POSITION_TYPE_RELATIVE,
|
|
1785
|
+
absolute: this.yoga.POSITION_TYPE_ABSOLUTE
|
|
1786
|
+
};
|
|
1787
|
+
this.node.setPositionType(mapping[positionType]);
|
|
1788
|
+
}
|
|
1789
|
+
calculateBounds() {
|
|
1790
|
+
super.calculateBounds();
|
|
1791
|
+
if (!this._geometry) return;
|
|
1792
|
+
const bounds = this._geometry.bounds;
|
|
1793
|
+
const width = Math.abs(bounds.minX - bounds.maxX);
|
|
1794
|
+
const height = Math.abs(bounds.minY - bounds.maxY);
|
|
1795
|
+
}
|
|
1796
|
+
setWidth(width) {
|
|
1797
|
+
this.displayWidth.set(width);
|
|
1798
|
+
this.node?.setWidth(width);
|
|
1799
|
+
}
|
|
1800
|
+
setHeight(height) {
|
|
1801
|
+
this.displayHeight.set(height);
|
|
1802
|
+
this.node?.setHeight(height);
|
|
1803
|
+
}
|
|
1804
|
+
getWidth() {
|
|
1805
|
+
return this.displayWidth();
|
|
1806
|
+
}
|
|
1807
|
+
getHeight() {
|
|
1808
|
+
return this.displayHeight();
|
|
1809
|
+
}
|
|
1810
|
+
}, _canvasContext = new WeakMap(), _DisplayObject_instances = new WeakSet(), applyFlexLayout_fn = function() {
|
|
1811
|
+
this.calculateLayout();
|
|
1812
|
+
for (let child of this.children) {
|
|
1813
|
+
const { left, top } = child.node.getComputedLayout();
|
|
1814
|
+
child.x = left;
|
|
1815
|
+
child.y = top;
|
|
1816
|
+
}
|
|
1817
|
+
}, flexRender_fn = function(props) {
|
|
1818
|
+
if (!this.parent) return;
|
|
1819
|
+
if (props.flexDirection || props.justifyContent) {
|
|
1820
|
+
this.isFlex = true;
|
|
1821
|
+
__privateMethod(this, _DisplayObject_instances, applyFlexLayout_fn).call(this);
|
|
1822
|
+
}
|
|
1823
|
+
}, setAlign_fn = function(methodName, align) {
|
|
1824
|
+
const mapping = {
|
|
1825
|
+
auto: this.yoga.ALIGN_AUTO,
|
|
1826
|
+
"flex-start": this.yoga.ALIGN_FLEX_START,
|
|
1827
|
+
"flex-end": this.yoga.ALIGN_FLEX_END,
|
|
1828
|
+
center: this.yoga.ALIGN_CENTER,
|
|
1829
|
+
stretch: this.yoga.ALIGN_STRETCH,
|
|
1830
|
+
baseline: this.yoga.ALIGN_BASELINE,
|
|
1831
|
+
"space-between": this.yoga.ALIGN_SPACE_BETWEEN,
|
|
1832
|
+
"space-around": this.yoga.ALIGN_SPACE_AROUND
|
|
1833
|
+
};
|
|
1834
|
+
const method = this.node[methodName].bind(this.node);
|
|
1835
|
+
method(mapping[align]);
|
|
1836
|
+
}, setEdgeSize_fn = function(methodName, size) {
|
|
1837
|
+
const method = this.node[methodName].bind(this.node);
|
|
1838
|
+
if (size instanceof Array) {
|
|
1839
|
+
if (size.length === 2) {
|
|
1840
|
+
method(this.yoga.EDGE_VERTICAL, size[0]);
|
|
1841
|
+
method(this.yoga.EDGE_HORIZONTAL, size[1]);
|
|
1842
|
+
} else if (size.length === 4) {
|
|
1843
|
+
method(this.yoga.EDGE_TOP, size[0]);
|
|
1844
|
+
method(this.yoga.EDGE_RIGHT, size[1]);
|
|
1845
|
+
method(this.yoga.EDGE_BOTTOM, size[2]);
|
|
1846
|
+
method(this.yoga.EDGE_LEFT, size[3]);
|
|
1847
|
+
}
|
|
1848
|
+
} else {
|
|
1849
|
+
method(this.yoga.EDGE_ALL, size);
|
|
1850
|
+
}
|
|
1851
|
+
}, _a;
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1854
|
+
// src/components/Canvas.ts
|
|
1855
|
+
registerComponent("Canvas", class Canvas extends DisplayObject(Container3) {
|
|
1856
|
+
});
|
|
1857
|
+
var Canvas2 = async (props = {}) => {
|
|
1858
|
+
let { cursorStyles, width, height, class: className } = useProps(props);
|
|
1859
|
+
const Yoga = await loadYoga();
|
|
1860
|
+
if (!props.width) width = signal3(800);
|
|
1861
|
+
if (!props.height) height = signal3(600);
|
|
1862
|
+
const renderer = await autoDetectRenderer({
|
|
1863
|
+
...props,
|
|
1864
|
+
width: width?.(),
|
|
1865
|
+
height: height?.()
|
|
1866
|
+
});
|
|
1867
|
+
const canvasSize = signal3({
|
|
1868
|
+
width: renderer.width,
|
|
1869
|
+
height: renderer.height
|
|
1870
|
+
});
|
|
1871
|
+
props.isRoot = true;
|
|
1872
|
+
const options = {
|
|
1873
|
+
...props,
|
|
1874
|
+
context: {
|
|
1875
|
+
Yoga,
|
|
1876
|
+
renderer,
|
|
1877
|
+
canvasSize
|
|
1878
|
+
},
|
|
1879
|
+
width: width?.(),
|
|
1880
|
+
height: height?.()
|
|
1881
|
+
};
|
|
1882
|
+
if (!props.tick) {
|
|
1883
|
+
options.context.tick = options.tick = signal3({
|
|
1884
|
+
timestamp: 0,
|
|
1885
|
+
deltaTime: 0,
|
|
1886
|
+
frame: 0,
|
|
1887
|
+
deltaRatio: 1
|
|
1888
|
+
});
|
|
1889
|
+
}
|
|
1890
|
+
const canvasElement = createComponent("Canvas", options);
|
|
1891
|
+
canvasElement.render = (rootElement) => {
|
|
1892
|
+
const canvasEl = renderer.view.canvas;
|
|
1893
|
+
globalThis.__PIXI_STAGE__ = canvasElement.componentInstance;
|
|
1894
|
+
globalThis.__PIXI_RENDERER__ = renderer;
|
|
1895
|
+
if (props.tickStart !== false) canvasElement.directives.tick.start();
|
|
1896
|
+
effect4(() => {
|
|
1897
|
+
canvasElement.propObservables.tick();
|
|
1898
|
+
renderer.render(canvasElement.componentInstance);
|
|
1899
|
+
});
|
|
1900
|
+
if (cursorStyles) {
|
|
1901
|
+
effect4(() => {
|
|
1902
|
+
renderer.events.cursorStyles = cursorStyles();
|
|
1903
|
+
});
|
|
1904
|
+
}
|
|
1905
|
+
if (className) {
|
|
1906
|
+
effect4(() => {
|
|
1907
|
+
canvasEl.classList.add(className());
|
|
1908
|
+
});
|
|
1909
|
+
}
|
|
1910
|
+
const resizeCanvas = async () => {
|
|
1911
|
+
let w, h2;
|
|
1912
|
+
if (width?.() === "100%" && height?.() === "100%") {
|
|
1913
|
+
const parent = canvasEl.parentElement;
|
|
1914
|
+
w = parent ? parent.clientWidth : window.innerWidth;
|
|
1915
|
+
h2 = parent ? parent.clientHeight : window.innerHeight;
|
|
1916
|
+
} else {
|
|
1917
|
+
w = width?.() ?? canvasEl.offsetWidth;
|
|
1918
|
+
h2 = height?.() ?? canvasEl.offsetHeight;
|
|
1919
|
+
}
|
|
1920
|
+
renderer.resize(w, h2);
|
|
1921
|
+
canvasSize.set({ width: w, height: h2 });
|
|
1922
|
+
canvasElement.componentInstance.setWidth(w);
|
|
1923
|
+
canvasElement.componentInstance.setHeight(h2);
|
|
1924
|
+
};
|
|
1925
|
+
window.addEventListener("resize", resizeCanvas);
|
|
1926
|
+
const existingCanvas = rootElement.querySelector("canvas");
|
|
1927
|
+
if (existingCanvas) {
|
|
1928
|
+
rootElement.replaceChild(canvasEl, existingCanvas);
|
|
1929
|
+
} else {
|
|
1930
|
+
rootElement.appendChild(canvasEl);
|
|
1931
|
+
}
|
|
1932
|
+
resizeCanvas();
|
|
1933
|
+
};
|
|
1934
|
+
return canvasElement;
|
|
1935
|
+
};
|
|
1936
|
+
|
|
1937
|
+
// src/components/Container.ts
|
|
1938
|
+
import { Container as PixiContainer } from "pixi.js";
|
|
1939
|
+
var CanvasContainer = class extends DisplayObject(PixiContainer) {
|
|
1940
|
+
constructor() {
|
|
1941
|
+
super(...arguments);
|
|
1942
|
+
this.isCustomAnchor = true;
|
|
1943
|
+
}
|
|
1944
|
+
onUpdate(props) {
|
|
1945
|
+
if (props.anchor) {
|
|
1946
|
+
setObservablePoint(this._anchorPoints, props.anchor);
|
|
1947
|
+
props.pivot = [
|
|
1948
|
+
this.getWidth() * this._anchorPoints.x,
|
|
1949
|
+
this.getHeight() * this._anchorPoints.y
|
|
1950
|
+
];
|
|
1951
|
+
}
|
|
1952
|
+
super.onUpdate(props);
|
|
1953
|
+
if (props.sortableChildren != void 0) {
|
|
1954
|
+
this.sortableChildren = props.sortableChildren;
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
onMount(args) {
|
|
1958
|
+
super.onMount(args);
|
|
1959
|
+
const { componentInstance, props } = args;
|
|
1960
|
+
const { pixiChildren } = props;
|
|
1961
|
+
if (pixiChildren) {
|
|
1962
|
+
pixiChildren.forEach((child) => {
|
|
1963
|
+
componentInstance.addChild(child);
|
|
1964
|
+
});
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
};
|
|
1968
|
+
registerComponent("Container", CanvasContainer);
|
|
1969
|
+
var Container4 = (props) => {
|
|
1970
|
+
return createComponent("Container", props);
|
|
1971
|
+
};
|
|
1972
|
+
|
|
1973
|
+
// src/components/Graphic.ts
|
|
1974
|
+
import { effect as effect5 } from "@signe/reactive";
|
|
1975
|
+
import { Graphics as PixiGraphics } from "pixi.js";
|
|
1976
|
+
var CanvasGraphics = class extends DisplayObject(PixiGraphics) {
|
|
1977
|
+
onInit(props) {
|
|
1978
|
+
super.onInit(props);
|
|
1979
|
+
if (props.draw) {
|
|
1980
|
+
effect5(() => {
|
|
1981
|
+
this.clear();
|
|
1982
|
+
props.draw?.(this);
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
};
|
|
1987
|
+
registerComponent("Graphics", CanvasGraphics);
|
|
1988
|
+
function Graphics(props) {
|
|
1989
|
+
return createComponent("Graphics", props);
|
|
1990
|
+
}
|
|
1991
|
+
function Rect(props) {
|
|
1992
|
+
const { width, height, color, borderRadius, border } = useProps(props, {
|
|
1993
|
+
borderRadius: null,
|
|
1994
|
+
border: null
|
|
1995
|
+
});
|
|
1996
|
+
return Graphics({
|
|
1997
|
+
draw: (g) => {
|
|
1998
|
+
if (borderRadius()) {
|
|
1999
|
+
g.roundRect(0, 0, width(), height(), borderRadius());
|
|
2000
|
+
} else {
|
|
2001
|
+
g.rect(0, 0, width(), height());
|
|
2002
|
+
}
|
|
2003
|
+
if (border) {
|
|
2004
|
+
g.stroke(border);
|
|
2005
|
+
}
|
|
2006
|
+
g.fill(color());
|
|
2007
|
+
},
|
|
2008
|
+
...props
|
|
2009
|
+
});
|
|
2010
|
+
}
|
|
2011
|
+
function drawShape(g, shape, props) {
|
|
2012
|
+
const { color, border } = props;
|
|
2013
|
+
if ("radius" in props) {
|
|
2014
|
+
g.circle(0, 0, props.radius());
|
|
2015
|
+
} else {
|
|
2016
|
+
g.ellipse(0, 0, props.width() / 2, props.height() / 2);
|
|
2017
|
+
}
|
|
2018
|
+
if (border()) {
|
|
2019
|
+
g.stroke(border());
|
|
2020
|
+
}
|
|
2021
|
+
g.fill(color());
|
|
2022
|
+
}
|
|
2023
|
+
function Circle(props) {
|
|
2024
|
+
const { radius, color, border } = useProps(props, {
|
|
2025
|
+
border: null
|
|
2026
|
+
});
|
|
2027
|
+
return Graphics({
|
|
2028
|
+
draw: (g) => drawShape(g, "circle", { radius, color, border }),
|
|
2029
|
+
...props
|
|
2030
|
+
});
|
|
2031
|
+
}
|
|
2032
|
+
function Ellipse(props) {
|
|
2033
|
+
const { width, height, color, border } = useProps(props, {
|
|
2034
|
+
border: null
|
|
2035
|
+
});
|
|
2036
|
+
return Graphics({
|
|
2037
|
+
draw: (g) => drawShape(g, "ellipse", { width, height, color, border }),
|
|
2038
|
+
...props
|
|
2039
|
+
});
|
|
2040
|
+
}
|
|
2041
|
+
function Triangle(props) {
|
|
2042
|
+
const { width, height, color, border } = useProps(props, {
|
|
2043
|
+
border: null,
|
|
2044
|
+
color: "#000"
|
|
2045
|
+
});
|
|
2046
|
+
return Graphics({
|
|
2047
|
+
draw: (g) => {
|
|
2048
|
+
g.moveTo(0, height());
|
|
2049
|
+
g.lineTo(width() / 2, 0);
|
|
2050
|
+
g.lineTo(width(), height());
|
|
2051
|
+
g.lineTo(0, height());
|
|
2052
|
+
g.fill(color());
|
|
2053
|
+
if (border) {
|
|
2054
|
+
g.stroke(border);
|
|
2055
|
+
}
|
|
2056
|
+
},
|
|
2057
|
+
...props
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
function Svg(props) {
|
|
2061
|
+
return Graphics({
|
|
2062
|
+
draw: (g) => g.svg(props.svg),
|
|
2063
|
+
...props
|
|
2064
|
+
});
|
|
2065
|
+
}
|
|
2066
|
+
|
|
2067
|
+
// src/engine/signal.ts
|
|
2068
|
+
var currentSubscriptionsTracker = null;
|
|
2069
|
+
var mountTracker = null;
|
|
2070
|
+
function mount(fn) {
|
|
2071
|
+
mountTracker?.(fn);
|
|
2072
|
+
}
|
|
2073
|
+
function tick(fn) {
|
|
2074
|
+
mount((el) => {
|
|
2075
|
+
const { context } = el.props;
|
|
2076
|
+
let subscription;
|
|
2077
|
+
if (context.tick) {
|
|
2078
|
+
subscription = context.tick.observable.subscribe(({ value }) => {
|
|
2079
|
+
fn(value, el);
|
|
2080
|
+
});
|
|
2081
|
+
}
|
|
2082
|
+
return () => {
|
|
2083
|
+
subscription?.unsubscribe();
|
|
2084
|
+
};
|
|
2085
|
+
});
|
|
2086
|
+
}
|
|
2087
|
+
function h(componentFunction, props = {}, ...children) {
|
|
2088
|
+
const allSubscriptions = /* @__PURE__ */ new Set();
|
|
2089
|
+
const allMounts = /* @__PURE__ */ new Set();
|
|
2090
|
+
currentSubscriptionsTracker = (subscription) => {
|
|
2091
|
+
allSubscriptions.add(subscription);
|
|
2092
|
+
};
|
|
2093
|
+
mountTracker = (fn) => {
|
|
2094
|
+
allMounts.add(fn);
|
|
2095
|
+
};
|
|
2096
|
+
if (children[0] instanceof Array) {
|
|
2097
|
+
children = children[0];
|
|
2098
|
+
}
|
|
2099
|
+
let component = componentFunction({ ...props, children });
|
|
2100
|
+
if (!component) {
|
|
2101
|
+
component = {};
|
|
2102
|
+
}
|
|
2103
|
+
component.effectSubscriptions = Array.from(allSubscriptions);
|
|
2104
|
+
component.effectMounts = [
|
|
2105
|
+
...Array.from(allMounts),
|
|
2106
|
+
...component.effectMounts ?? []
|
|
2107
|
+
];
|
|
2108
|
+
if (component instanceof Promise) {
|
|
2109
|
+
component.then((component2) => {
|
|
2110
|
+
if (component2.props.isRoot) {
|
|
2111
|
+
allMounts.forEach((fn) => fn(component2));
|
|
2112
|
+
}
|
|
2113
|
+
});
|
|
2114
|
+
}
|
|
2115
|
+
currentSubscriptionsTracker = null;
|
|
2116
|
+
mountTracker = null;
|
|
2117
|
+
return component;
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
// src/components/Scene.ts
|
|
2121
|
+
function Scene(props) {
|
|
2122
|
+
return h(Container4);
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
// src/components/ParticleEmitter.ts
|
|
2126
|
+
import * as particles from "@barvynkoa/particle-emitter";
|
|
2127
|
+
var CanvasParticlesEmitter = class extends CanvasContainer {
|
|
2128
|
+
constructor() {
|
|
2129
|
+
super(...arguments);
|
|
2130
|
+
this.elapsed = Date.now();
|
|
2131
|
+
}
|
|
2132
|
+
onMount(params) {
|
|
2133
|
+
super.onMount(params);
|
|
2134
|
+
const { props } = params;
|
|
2135
|
+
const tick2 = props.context.tick;
|
|
2136
|
+
this.emitter = new particles.Emitter(this, props.config);
|
|
2137
|
+
this.subscriptionTick = tick2.observable.subscribe((value) => {
|
|
2138
|
+
if (!this.emitter) return;
|
|
2139
|
+
const now = Date.now();
|
|
2140
|
+
this.emitter.update((now - this.elapsed) * 1e-3);
|
|
2141
|
+
this.elapsed = now;
|
|
2142
|
+
});
|
|
2143
|
+
}
|
|
2144
|
+
onUpdate(props) {
|
|
2145
|
+
}
|
|
2146
|
+
onDestroy() {
|
|
2147
|
+
super.onDestroy();
|
|
2148
|
+
this.emitter?.destroy();
|
|
2149
|
+
this.emitter = null;
|
|
2150
|
+
this.subscriptionTick.unsubscribe();
|
|
2151
|
+
}
|
|
2152
|
+
};
|
|
2153
|
+
registerComponent("ParticlesEmitter", CanvasParticlesEmitter);
|
|
2154
|
+
function ParticlesEmitter(props) {
|
|
2155
|
+
return createComponent("ParticlesEmitter", props);
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
// src/components/Sprite.ts
|
|
2159
|
+
import { computed, effect as effect7, isSignal as isSignal4 } from "@signe/reactive";
|
|
2160
|
+
import {
|
|
2161
|
+
Assets,
|
|
2162
|
+
Container as Container5,
|
|
2163
|
+
Sprite as PixiSprite,
|
|
2164
|
+
Rectangle as Rectangle2,
|
|
2165
|
+
Texture as Texture2
|
|
2166
|
+
} from "pixi.js";
|
|
2167
|
+
|
|
2168
|
+
// src/engine/animation.ts
|
|
2169
|
+
import { effect as effect6, signal as signal4 } from "@signe/reactive";
|
|
2170
|
+
import { animate as animatePopmotion } from "popmotion";
|
|
2171
|
+
function isAnimatedSignal(signal6) {
|
|
2172
|
+
return signal6.animatedState !== void 0;
|
|
2173
|
+
}
|
|
2174
|
+
function animatedSignal(initialValue, options = {}) {
|
|
2175
|
+
const state = {
|
|
2176
|
+
current: initialValue,
|
|
2177
|
+
start: initialValue,
|
|
2178
|
+
end: initialValue
|
|
2179
|
+
};
|
|
2180
|
+
let animation;
|
|
2181
|
+
const publicSignal = signal4(initialValue);
|
|
2182
|
+
const privateSignal = signal4(state);
|
|
2183
|
+
effect6(() => {
|
|
2184
|
+
const currentState = privateSignal();
|
|
2185
|
+
publicSignal.set(currentState.current);
|
|
2186
|
+
});
|
|
2187
|
+
function animatedSignal2(newValue) {
|
|
2188
|
+
if (newValue === void 0) {
|
|
2189
|
+
return privateSignal();
|
|
2190
|
+
}
|
|
2191
|
+
const prevState = privateSignal();
|
|
2192
|
+
const newState = {
|
|
2193
|
+
current: prevState.current,
|
|
2194
|
+
start: prevState.current,
|
|
2195
|
+
end: newValue
|
|
2196
|
+
};
|
|
2197
|
+
privateSignal.set(newState);
|
|
2198
|
+
if (animation) {
|
|
2199
|
+
animation.stop();
|
|
2200
|
+
}
|
|
2201
|
+
animation = animatePopmotion({
|
|
2202
|
+
// TODO
|
|
2203
|
+
duration: 20,
|
|
2204
|
+
...options,
|
|
2205
|
+
from: prevState.current,
|
|
2206
|
+
to: newValue,
|
|
2207
|
+
onUpdate: (value) => {
|
|
2208
|
+
privateSignal.update((s) => ({ ...s, current: value }));
|
|
2209
|
+
if (options.onUpdate) {
|
|
2210
|
+
options.onUpdate(value);
|
|
2211
|
+
}
|
|
2212
|
+
}
|
|
2213
|
+
});
|
|
2214
|
+
}
|
|
2215
|
+
const fn = function() {
|
|
2216
|
+
return privateSignal().current;
|
|
2217
|
+
};
|
|
2218
|
+
for (const key in publicSignal) {
|
|
2219
|
+
fn[key] = publicSignal[key];
|
|
2220
|
+
}
|
|
2221
|
+
fn.animatedState = privateSignal;
|
|
2222
|
+
fn.update = (updater) => {
|
|
2223
|
+
animatedSignal2(updater(privateSignal().current));
|
|
2224
|
+
};
|
|
2225
|
+
fn.set = (newValue) => {
|
|
2226
|
+
animatedSignal2(newValue);
|
|
2227
|
+
};
|
|
2228
|
+
return fn;
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2231
|
+
// src/components/Sprite.ts
|
|
2232
|
+
var log2 = console.log;
|
|
2233
|
+
var CanvasSprite = class extends DisplayObject(PixiSprite) {
|
|
2234
|
+
constructor() {
|
|
2235
|
+
super(...arguments);
|
|
2236
|
+
this.currentAnimation = null;
|
|
2237
|
+
this.time = 0;
|
|
2238
|
+
this.frameIndex = 0;
|
|
2239
|
+
this.animations = /* @__PURE__ */ new Map();
|
|
2240
|
+
this.subscriptionSheet = [];
|
|
2241
|
+
this.sheetParams = {};
|
|
2242
|
+
this.sheetCurrentAnimation = "stand" /* Stand */;
|
|
2243
|
+
this.currentAnimationContainer = null;
|
|
2244
|
+
}
|
|
2245
|
+
async createTextures(options) {
|
|
2246
|
+
const { width, height, framesHeight, framesWidth, image, offset } = options;
|
|
2247
|
+
const texture = await Assets.load(image);
|
|
2248
|
+
const spriteWidth = options.spriteWidth;
|
|
2249
|
+
const spriteHeight = options.spriteHeight;
|
|
2250
|
+
const frames = [];
|
|
2251
|
+
const offsetX = offset && offset.x || 0;
|
|
2252
|
+
const offsetY = offset && offset.y || 0;
|
|
2253
|
+
for (let i = 0; i < framesHeight; i++) {
|
|
2254
|
+
frames[i] = [];
|
|
2255
|
+
for (let j = 0; j < framesWidth; j++) {
|
|
2256
|
+
const rectX = j * spriteWidth + offsetX;
|
|
2257
|
+
const rectY = i * spriteHeight + offsetY;
|
|
2258
|
+
if (rectY > height) {
|
|
2259
|
+
throw log2(
|
|
2260
|
+
`Warning, there is a problem with the height of the "${this.id}" spritesheet. When cutting into frames, the frame exceeds the height of the image.`
|
|
2261
|
+
);
|
|
2262
|
+
}
|
|
2263
|
+
if (rectX > width) {
|
|
2264
|
+
throw log2(
|
|
2265
|
+
`Warning, there is a problem with the width of the "${this.id}" spritesheet. When cutting into frames, the frame exceeds the width of the image.`
|
|
2266
|
+
);
|
|
2267
|
+
}
|
|
2268
|
+
frames[i].push(
|
|
2269
|
+
new Texture2({
|
|
2270
|
+
source: texture.source,
|
|
2271
|
+
frame: new Rectangle2(rectX, rectY, spriteWidth, spriteHeight)
|
|
2272
|
+
})
|
|
2273
|
+
);
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
return frames;
|
|
2277
|
+
}
|
|
2278
|
+
async createAnimations() {
|
|
2279
|
+
const { textures } = this.spritesheet;
|
|
2280
|
+
if (!textures) {
|
|
2281
|
+
return;
|
|
2282
|
+
}
|
|
2283
|
+
for (let animationName in textures) {
|
|
2284
|
+
const props = [
|
|
2285
|
+
"width",
|
|
2286
|
+
"height",
|
|
2287
|
+
"framesHeight",
|
|
2288
|
+
"framesWidth",
|
|
2289
|
+
"rectWidth",
|
|
2290
|
+
"rectHeight",
|
|
2291
|
+
"offset",
|
|
2292
|
+
"image",
|
|
2293
|
+
"sound"
|
|
2294
|
+
];
|
|
2295
|
+
const parentObj = props.reduce(
|
|
2296
|
+
(prev, val) => ({ ...prev, [val]: this.spritesheet[val] }),
|
|
2297
|
+
{}
|
|
2298
|
+
);
|
|
2299
|
+
const optionsTextures = {
|
|
2300
|
+
...parentObj,
|
|
2301
|
+
...textures[animationName]
|
|
2302
|
+
};
|
|
2303
|
+
const {
|
|
2304
|
+
rectWidth,
|
|
2305
|
+
width = 0,
|
|
2306
|
+
framesWidth = 1,
|
|
2307
|
+
rectHeight,
|
|
2308
|
+
height = 0,
|
|
2309
|
+
framesHeight = 1
|
|
2310
|
+
} = optionsTextures;
|
|
2311
|
+
optionsTextures.spriteWidth = rectWidth ? rectWidth : width / framesWidth;
|
|
2312
|
+
optionsTextures.spriteHeight = rectHeight ? rectHeight : height / framesHeight;
|
|
2313
|
+
this.animations.set(animationName, {
|
|
2314
|
+
frames: await this.createTextures(
|
|
2315
|
+
optionsTextures
|
|
2316
|
+
),
|
|
2317
|
+
name: animationName,
|
|
2318
|
+
animations: textures[animationName].animations,
|
|
2319
|
+
params: [],
|
|
2320
|
+
data: optionsTextures,
|
|
2321
|
+
sprites: []
|
|
2322
|
+
});
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
async onMount(params) {
|
|
2326
|
+
const { props, propObservables } = params;
|
|
2327
|
+
const tick2 = props.context.tick;
|
|
2328
|
+
const sheet = props.sheet ?? {};
|
|
2329
|
+
if (sheet?.onFinish) {
|
|
2330
|
+
this.onFinish = sheet.onFinish;
|
|
2331
|
+
}
|
|
2332
|
+
this.subscriptionTick = tick2.observable.subscribe((value) => {
|
|
2333
|
+
this.update(value);
|
|
2334
|
+
});
|
|
2335
|
+
if (props.sheet?.definition) {
|
|
2336
|
+
this.spritesheet = props.sheet.definition;
|
|
2337
|
+
await this.createAnimations();
|
|
2338
|
+
}
|
|
2339
|
+
if (sheet.params) {
|
|
2340
|
+
for (let key in propObservables?.sheet["params"]) {
|
|
2341
|
+
const value = propObservables?.sheet["params"][key];
|
|
2342
|
+
if (isSignal4(value)) {
|
|
2343
|
+
this.subscriptionSheet.push(
|
|
2344
|
+
value.observable.subscribe((value2) => {
|
|
2345
|
+
if (this.animations.size == 0) return;
|
|
2346
|
+
this.play(this.sheetCurrentAnimation, [{ [key]: value2 }]);
|
|
2347
|
+
})
|
|
2348
|
+
);
|
|
2349
|
+
} else {
|
|
2350
|
+
this.play(this.sheetCurrentAnimation, [{ [key]: value }]);
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
const isMoving = computed(() => {
|
|
2355
|
+
const { x, y } = propObservables ?? {};
|
|
2356
|
+
if (!x || !y) return false;
|
|
2357
|
+
const xSignal = x;
|
|
2358
|
+
const ySignal = y;
|
|
2359
|
+
const isMovingX = isAnimatedSignal(xSignal) && xSignal.animatedState().current !== xSignal.animatedState().end;
|
|
2360
|
+
const isMovingY = isAnimatedSignal(ySignal) && ySignal.animatedState().current !== ySignal.animatedState().end;
|
|
2361
|
+
return isMovingX || isMovingY;
|
|
2362
|
+
});
|
|
2363
|
+
effect7(() => {
|
|
2364
|
+
const _isMoving = isMoving();
|
|
2365
|
+
if (!this.isMounted) return;
|
|
2366
|
+
if (_isMoving) {
|
|
2367
|
+
this.sheetCurrentAnimation = "walk" /* Walk */;
|
|
2368
|
+
} else {
|
|
2369
|
+
this.sheetCurrentAnimation = "stand" /* Stand */;
|
|
2370
|
+
}
|
|
2371
|
+
this.play(this.sheetCurrentAnimation, [this.sheetParams]);
|
|
2372
|
+
});
|
|
2373
|
+
super.onMount(params);
|
|
2374
|
+
}
|
|
2375
|
+
async onUpdate(props) {
|
|
2376
|
+
super.onUpdate(props);
|
|
2377
|
+
const sheet = props.sheet;
|
|
2378
|
+
if (sheet?.params) this.sheetParams = sheet?.params;
|
|
2379
|
+
if (sheet?.playing && this.isMounted) {
|
|
2380
|
+
this.sheetCurrentAnimation = sheet?.playing;
|
|
2381
|
+
this.play(this.sheetCurrentAnimation, [this.sheetParams]);
|
|
2382
|
+
}
|
|
2383
|
+
if (props.hitbox) this.hitbox = props.hitbox;
|
|
2384
|
+
if (props.scaleMode) this.baseTexture.scaleMode = props.scaleMode;
|
|
2385
|
+
else if (props.image && this.fullProps.rectangle === void 0) {
|
|
2386
|
+
this.texture = await Assets.load(this.fullProps.image);
|
|
2387
|
+
} else if (props.texture) {
|
|
2388
|
+
this.texture = props.texture;
|
|
2389
|
+
}
|
|
2390
|
+
if (props.rectangle !== void 0) {
|
|
2391
|
+
const { x, y, width, height } = props.rectangle?.value ?? props.rectangle;
|
|
2392
|
+
const texture = await Assets.load(this.fullProps.image);
|
|
2393
|
+
this.texture = new Texture2({
|
|
2394
|
+
source: texture.source,
|
|
2395
|
+
frame: new Rectangle2(x, y, width, height)
|
|
2396
|
+
});
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
onDestroy() {
|
|
2400
|
+
super.onDestroy();
|
|
2401
|
+
this.subscriptionSheet.forEach((sub) => sub.unsubscribe());
|
|
2402
|
+
this.subscriptionTick.unsubscribe();
|
|
2403
|
+
if (this.currentAnimationContainer && this.parent instanceof Container5) {
|
|
2404
|
+
this.parent.removeChild(this.currentAnimationContainer);
|
|
2405
|
+
}
|
|
2406
|
+
}
|
|
2407
|
+
has(name) {
|
|
2408
|
+
return this.animations.has(name);
|
|
2409
|
+
}
|
|
2410
|
+
get(name) {
|
|
2411
|
+
return this.animations.get(name);
|
|
2412
|
+
}
|
|
2413
|
+
isPlaying(name) {
|
|
2414
|
+
if (!name) return !!this.currentAnimation;
|
|
2415
|
+
if (this.currentAnimation == null) return false;
|
|
2416
|
+
return this.currentAnimation.name == name;
|
|
2417
|
+
}
|
|
2418
|
+
stop() {
|
|
2419
|
+
this.currentAnimation = null;
|
|
2420
|
+
this.destroy();
|
|
2421
|
+
}
|
|
2422
|
+
play(name, params = []) {
|
|
2423
|
+
const animParams = this.currentAnimation?.params;
|
|
2424
|
+
if (this.isPlaying(name) && arrayEquals(params, animParams || [])) return;
|
|
2425
|
+
const animation = this.get(name);
|
|
2426
|
+
if (!animation) {
|
|
2427
|
+
throw new Error(
|
|
2428
|
+
`Impossible to play the ${name} animation because it doesn't exist on the "${this.id}" spritesheet`
|
|
2429
|
+
);
|
|
2430
|
+
}
|
|
2431
|
+
const cloneParams = structuredClone(params);
|
|
2432
|
+
this.removeChildren();
|
|
2433
|
+
animation.sprites = [];
|
|
2434
|
+
this.currentAnimation = animation;
|
|
2435
|
+
this.currentAnimation.params = cloneParams;
|
|
2436
|
+
this.time = 0;
|
|
2437
|
+
this.frameIndex = 0;
|
|
2438
|
+
let animations = animation.animations;
|
|
2439
|
+
animations = isFunction(animations) ? animations(...cloneParams) : animations;
|
|
2440
|
+
this.currentAnimationContainer = new Container5();
|
|
2441
|
+
for (let container of animations) {
|
|
2442
|
+
const sprite = new PixiSprite();
|
|
2443
|
+
for (let frame of container) {
|
|
2444
|
+
this.currentAnimation.sprites.push(frame);
|
|
2445
|
+
}
|
|
2446
|
+
this.currentAnimationContainer.addChild(sprite);
|
|
2447
|
+
}
|
|
2448
|
+
const sound = this.currentAnimation.data.sound;
|
|
2449
|
+
if (sound) {
|
|
2450
|
+
}
|
|
2451
|
+
this.update({
|
|
2452
|
+
deltaRatio: 1
|
|
2453
|
+
});
|
|
2454
|
+
}
|
|
2455
|
+
update({ deltaRatio }) {
|
|
2456
|
+
if (!this.isPlaying() || !this.currentAnimation || !this.currentAnimationContainer)
|
|
2457
|
+
return;
|
|
2458
|
+
const self = this;
|
|
2459
|
+
const { frames, sprites, data } = this.currentAnimation;
|
|
2460
|
+
let frame = sprites[this.frameIndex];
|
|
2461
|
+
const nextFrame = sprites[this.frameIndex + 1];
|
|
2462
|
+
for (let _sprite of this.currentAnimationContainer.children) {
|
|
2463
|
+
let applyTransformValue = function(prop, alias) {
|
|
2464
|
+
const optionProp = alias || prop;
|
|
2465
|
+
const val = getVal(optionProp);
|
|
2466
|
+
if (val !== void 0) {
|
|
2467
|
+
self[prop] = val;
|
|
2468
|
+
}
|
|
2469
|
+
};
|
|
2470
|
+
const sprite = _sprite;
|
|
2471
|
+
if (!frame || frame.frameY == void 0 || frame.frameX == void 0) {
|
|
2472
|
+
continue;
|
|
2473
|
+
}
|
|
2474
|
+
this.texture = frames[frame.frameY][frame.frameX];
|
|
2475
|
+
const getVal = (prop) => {
|
|
2476
|
+
return frame[prop] ?? data[prop] ?? this.spritesheet[prop];
|
|
2477
|
+
};
|
|
2478
|
+
const applyTransform = (prop) => {
|
|
2479
|
+
const val = getVal(prop);
|
|
2480
|
+
if (val) {
|
|
2481
|
+
this[prop].set(...val);
|
|
2482
|
+
}
|
|
2483
|
+
};
|
|
2484
|
+
if (this.applyTransform) {
|
|
2485
|
+
frame = {
|
|
2486
|
+
...frame,
|
|
2487
|
+
...this.applyTransform(frame, data, this.spritesheet)
|
|
2488
|
+
};
|
|
2489
|
+
}
|
|
2490
|
+
const realSize = getVal("spriteRealSize");
|
|
2491
|
+
const heightOfSprite = typeof realSize == "number" ? realSize : realSize?.height;
|
|
2492
|
+
const widthOfSprite = typeof realSize == "number" ? realSize : realSize?.width;
|
|
2493
|
+
const applyAnchorBySize = () => {
|
|
2494
|
+
if (heightOfSprite && this.hitbox) {
|
|
2495
|
+
const { spriteWidth, spriteHeight } = data;
|
|
2496
|
+
const w = (spriteWidth - this.hitbox.w) / 2 / spriteWidth;
|
|
2497
|
+
const gap = (spriteHeight - heightOfSprite) / 2;
|
|
2498
|
+
const h2 = (spriteHeight - this.hitbox.h - gap) / spriteHeight;
|
|
2499
|
+
this.anchor.set(w, h2);
|
|
2500
|
+
}
|
|
2501
|
+
};
|
|
2502
|
+
if (frame.sound) {
|
|
2503
|
+
}
|
|
2504
|
+
applyAnchorBySize();
|
|
2505
|
+
applyTransform("anchor");
|
|
2506
|
+
applyTransform("scale");
|
|
2507
|
+
applyTransform("skew");
|
|
2508
|
+
applyTransform("pivot");
|
|
2509
|
+
applyTransformValue("alpha", "opacity");
|
|
2510
|
+
applyTransformValue("x");
|
|
2511
|
+
applyTransformValue("y");
|
|
2512
|
+
applyTransformValue("angle");
|
|
2513
|
+
applyTransformValue("rotation");
|
|
2514
|
+
applyTransformValue("visible");
|
|
2515
|
+
}
|
|
2516
|
+
if (!nextFrame) {
|
|
2517
|
+
this.time = 0;
|
|
2518
|
+
this.frameIndex = 0;
|
|
2519
|
+
if (this.onFinish && sprites.length > 1) this.onFinish();
|
|
2520
|
+
return;
|
|
2521
|
+
}
|
|
2522
|
+
this.time += deltaRatio ?? 1;
|
|
2523
|
+
if (this.time >= nextFrame.time) {
|
|
2524
|
+
this.frameIndex++;
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
};
|
|
2528
|
+
registerComponent("Sprite", CanvasSprite);
|
|
2529
|
+
var Sprite2 = (props) => {
|
|
2530
|
+
return createComponent("Sprite", props);
|
|
2531
|
+
};
|
|
2532
|
+
|
|
2533
|
+
// src/components/Text.ts
|
|
2534
|
+
import { Text as PixiText } from "pixi.js";
|
|
2535
|
+
|
|
2536
|
+
// src/engine/trigger.ts
|
|
2537
|
+
import { effect as effect8, signal as signal5 } from "@signe/reactive";
|
|
2538
|
+
function isTrigger(arg) {
|
|
2539
|
+
return arg?.start && arg?.listen;
|
|
2540
|
+
}
|
|
2541
|
+
function trigger(globalConfig) {
|
|
2542
|
+
const _signal = signal5({
|
|
2543
|
+
config: globalConfig,
|
|
2544
|
+
value: 0,
|
|
2545
|
+
resolve: (value) => void 0
|
|
2546
|
+
});
|
|
2547
|
+
return {
|
|
2548
|
+
start: (config) => {
|
|
2549
|
+
return new Promise((resolve) => {
|
|
2550
|
+
_signal.set({
|
|
2551
|
+
config: {
|
|
2552
|
+
...globalConfig,
|
|
2553
|
+
...config
|
|
2554
|
+
},
|
|
2555
|
+
resolve,
|
|
2556
|
+
value: Math.random()
|
|
2557
|
+
});
|
|
2558
|
+
});
|
|
2559
|
+
},
|
|
2560
|
+
listen: () => {
|
|
2561
|
+
return {
|
|
2562
|
+
config: globalConfig,
|
|
2563
|
+
seed: _signal()
|
|
2564
|
+
};
|
|
2565
|
+
}
|
|
2566
|
+
};
|
|
2567
|
+
}
|
|
2568
|
+
function on(triggerSignal, callback) {
|
|
2569
|
+
if (!isTrigger(triggerSignal)) {
|
|
2570
|
+
throw new Error("In 'on(arg)' must have a trigger signal type");
|
|
2571
|
+
}
|
|
2572
|
+
effect8(() => {
|
|
2573
|
+
const result = triggerSignal.listen();
|
|
2574
|
+
if (result?.seed.value) {
|
|
2575
|
+
const ret = callback(result?.seed.config);
|
|
2576
|
+
if (ret && typeof ret.then === "function") {
|
|
2577
|
+
ret.then(result?.seed.resolve);
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
});
|
|
2581
|
+
}
|
|
2582
|
+
|
|
2583
|
+
// src/components/Text.ts
|
|
2584
|
+
var CanvasText = class extends DisplayObject(PixiText) {
|
|
2585
|
+
constructor() {
|
|
2586
|
+
super(...arguments);
|
|
2587
|
+
this.fullText = "";
|
|
2588
|
+
this.currentIndex = 0;
|
|
2589
|
+
this.typewriterSpeed = 1;
|
|
2590
|
+
// Default speed
|
|
2591
|
+
this._wordWrapWidth = 0;
|
|
2592
|
+
this.typewriterOptions = {};
|
|
2593
|
+
}
|
|
2594
|
+
onMount(args) {
|
|
2595
|
+
super.onMount(args);
|
|
2596
|
+
const { props } = args;
|
|
2597
|
+
const tick2 = props.context.tick;
|
|
2598
|
+
if (props.text && props.typewriter) {
|
|
2599
|
+
this.fullText = props.text;
|
|
2600
|
+
this.text = "";
|
|
2601
|
+
this.currentIndex = 0;
|
|
2602
|
+
if (props.typewriter) {
|
|
2603
|
+
this.typewriterOptions = props.typewriter;
|
|
2604
|
+
if (this.typewriterOptions.skip) {
|
|
2605
|
+
on(this.typewriterOptions.skip, () => {
|
|
2606
|
+
this.skipTypewriter();
|
|
2607
|
+
});
|
|
2608
|
+
}
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
this.subscriptionTick = tick2.observable.subscribe(() => {
|
|
2612
|
+
if (props.typewriter) {
|
|
2613
|
+
this.typewriterEffect();
|
|
2614
|
+
}
|
|
2615
|
+
});
|
|
2616
|
+
}
|
|
2617
|
+
onUpdate(props) {
|
|
2618
|
+
super.onUpdate(props);
|
|
2619
|
+
if (props.typewriter) {
|
|
2620
|
+
if (props.typewriter) {
|
|
2621
|
+
this.typewriterOptions = props.typewriter;
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
2624
|
+
if (props.text) {
|
|
2625
|
+
this.text = props.text;
|
|
2626
|
+
}
|
|
2627
|
+
if (props.text !== void 0 && props.text !== this.fullText && this.fullProps.typewriter) {
|
|
2628
|
+
this.text = "";
|
|
2629
|
+
this.currentIndex = 0;
|
|
2630
|
+
this.fullText = props.text;
|
|
2631
|
+
}
|
|
2632
|
+
if (props.style) {
|
|
2633
|
+
for (const key in props.style) {
|
|
2634
|
+
this.style[key] = props.style[key];
|
|
2635
|
+
}
|
|
2636
|
+
if (props.style.wordWrapWidth) {
|
|
2637
|
+
this._wordWrapWidth = props.style.wordWrapWidth;
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
if (props.color) {
|
|
2641
|
+
this.style.fill = props.color;
|
|
2642
|
+
}
|
|
2643
|
+
if (props.size) {
|
|
2644
|
+
this.style.fontSize = props.size;
|
|
2645
|
+
}
|
|
2646
|
+
if (props.fontFamily) {
|
|
2647
|
+
this.style.fontFamily = props.fontFamily;
|
|
2648
|
+
}
|
|
2649
|
+
if (this._wordWrapWidth) {
|
|
2650
|
+
this.setWidth(this._wordWrapWidth);
|
|
2651
|
+
} else {
|
|
2652
|
+
this.setWidth(this.width);
|
|
2653
|
+
}
|
|
2654
|
+
this.setHeight(this.height);
|
|
2655
|
+
}
|
|
2656
|
+
get onCompleteCallback() {
|
|
2657
|
+
return this.typewriterOptions.onComplete;
|
|
2658
|
+
}
|
|
2659
|
+
typewriterEffect() {
|
|
2660
|
+
if (this.currentIndex < this.fullText.length) {
|
|
2661
|
+
const nextIndex = Math.min(
|
|
2662
|
+
this.currentIndex + (this.typewriterOptions.speed ?? 1),
|
|
2663
|
+
this.fullText.length
|
|
2664
|
+
);
|
|
2665
|
+
this.text = this.fullText.slice(0, nextIndex);
|
|
2666
|
+
this.currentIndex = nextIndex;
|
|
2667
|
+
if (this.currentIndex === this.fullText.length && this.onCompleteCallback) {
|
|
2668
|
+
this.onCompleteCallback();
|
|
2669
|
+
}
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
// Add a method to skip the typewriter effect
|
|
2673
|
+
skipTypewriter() {
|
|
2674
|
+
if (this.skipSignal) {
|
|
2675
|
+
this.skipSignal();
|
|
2676
|
+
}
|
|
2677
|
+
this.text = this.fullText;
|
|
2678
|
+
this.currentIndex = this.fullText.length;
|
|
2679
|
+
}
|
|
2680
|
+
onDestroy() {
|
|
2681
|
+
super.onDestroy();
|
|
2682
|
+
this.subscriptionTick.unsubscribe();
|
|
2683
|
+
}
|
|
2684
|
+
};
|
|
2685
|
+
registerComponent("Text", CanvasText);
|
|
2686
|
+
function Text(props) {
|
|
2687
|
+
return createComponent("Text", props);
|
|
2688
|
+
}
|
|
2689
|
+
|
|
2690
|
+
// src/components/TilingSprite.ts
|
|
2691
|
+
import { TilingSprite as PixiTilingSprite, Texture as Texture3 } from "pixi.js";
|
|
2692
|
+
var CanvasTilingSprite = class extends DisplayObject(PixiTilingSprite) {
|
|
2693
|
+
onUpdate(props) {
|
|
2694
|
+
super.onUpdate(props);
|
|
2695
|
+
if (props.image) {
|
|
2696
|
+
this.texture = Texture3.from(props.image);
|
|
2697
|
+
}
|
|
2698
|
+
if (props.tileScale) {
|
|
2699
|
+
this.tileScale.set(props.tileScale.x, props.tileScale.y);
|
|
2700
|
+
}
|
|
2701
|
+
if (props.tilePosition) {
|
|
2702
|
+
this.tilePosition.set(props.tilePosition.x, props.tilePosition.y);
|
|
2703
|
+
}
|
|
2704
|
+
if (props.width !== void 0) {
|
|
2705
|
+
this.width = props.width;
|
|
2706
|
+
}
|
|
2707
|
+
if (props.height !== void 0) {
|
|
2708
|
+
this.height = props.height;
|
|
2709
|
+
}
|
|
2710
|
+
}
|
|
2711
|
+
};
|
|
2712
|
+
registerComponent("TilingSprite", CanvasTilingSprite);
|
|
2713
|
+
function TilingSprite(props) {
|
|
2714
|
+
return createComponent("TilingSprite", props);
|
|
2715
|
+
}
|
|
2716
|
+
|
|
2717
|
+
// src/components/Viewport.ts
|
|
2718
|
+
import { Viewport as PixiViewport } from "pixi-viewport";
|
|
2719
|
+
import { effect as effect9 } from "@signe/reactive";
|
|
2720
|
+
var EVENTS3 = [
|
|
2721
|
+
"bounce-x-end",
|
|
2722
|
+
"bounce-x-start",
|
|
2723
|
+
"bounce-y-end",
|
|
2724
|
+
"bounce-y-start",
|
|
2725
|
+
"clicked",
|
|
2726
|
+
"drag-end",
|
|
2727
|
+
"drag-start",
|
|
2728
|
+
"frame-end",
|
|
2729
|
+
"mouse-edge-end",
|
|
2730
|
+
"mouse-edge-start",
|
|
2731
|
+
"moved",
|
|
2732
|
+
"moved-end",
|
|
2733
|
+
"pinch-end",
|
|
2734
|
+
"pinch-start",
|
|
2735
|
+
"snap-end",
|
|
2736
|
+
"snap-start",
|
|
2737
|
+
"snap-zoom-end",
|
|
2738
|
+
"snap-zoom-start",
|
|
2739
|
+
"wheel-scroll",
|
|
2740
|
+
"zoomed",
|
|
2741
|
+
"zoomed-end"
|
|
2742
|
+
];
|
|
2743
|
+
var CanvasViewport = class extends DisplayObject(PixiViewport) {
|
|
2744
|
+
constructor() {
|
|
2745
|
+
const defaultOptions = {
|
|
2746
|
+
noTicker: true,
|
|
2747
|
+
events: {
|
|
2748
|
+
domElement: {
|
|
2749
|
+
addEventListener: () => {
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
}
|
|
2753
|
+
};
|
|
2754
|
+
super(defaultOptions);
|
|
2755
|
+
this.overrideProps = ["wheel"];
|
|
2756
|
+
}
|
|
2757
|
+
onInit(props) {
|
|
2758
|
+
super.onInit(props);
|
|
2759
|
+
for (let event of EVENTS3) {
|
|
2760
|
+
const camelCaseEvent = event.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
|
|
2761
|
+
if (props[camelCaseEvent]) {
|
|
2762
|
+
this.on(event, props[camelCaseEvent]);
|
|
2763
|
+
}
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
onMount(element) {
|
|
2767
|
+
super.onMount(element);
|
|
2768
|
+
const { tick: tick2, renderer, canvasSize } = element.props.context;
|
|
2769
|
+
let isDragging = false;
|
|
2770
|
+
effect9(() => {
|
|
2771
|
+
this.screenWidth = canvasSize().width;
|
|
2772
|
+
this.screenHeight = canvasSize().height;
|
|
2773
|
+
});
|
|
2774
|
+
renderer.events.domElement.addEventListener(
|
|
2775
|
+
"wheel",
|
|
2776
|
+
this.input.wheelFunction
|
|
2777
|
+
);
|
|
2778
|
+
this.options.events = renderer.events;
|
|
2779
|
+
this.tickSubscription = tick2.observable.subscribe(({ value }) => {
|
|
2780
|
+
this.update(value.timestamp);
|
|
2781
|
+
});
|
|
2782
|
+
element.props.context.viewport = this;
|
|
2783
|
+
this.updateViewportSettings(element.props);
|
|
2784
|
+
}
|
|
2785
|
+
onUpdate(props) {
|
|
2786
|
+
super.onUpdate(props);
|
|
2787
|
+
this.updateViewportSettings(props);
|
|
2788
|
+
}
|
|
2789
|
+
updateViewportSettings(props) {
|
|
2790
|
+
if (props.screenWidth !== void 0) {
|
|
2791
|
+
this.screenWidth = props.screenWidth;
|
|
2792
|
+
}
|
|
2793
|
+
if (props.screenHeight !== void 0) {
|
|
2794
|
+
this.screenHeight = props.screenHeight;
|
|
2795
|
+
}
|
|
2796
|
+
if (props.worldWidth !== void 0) {
|
|
2797
|
+
this.worldWidth = props.worldWidth;
|
|
2798
|
+
}
|
|
2799
|
+
if (props.worldHeight !== void 0) {
|
|
2800
|
+
this.worldHeight = props.worldHeight;
|
|
2801
|
+
}
|
|
2802
|
+
if (props.clamp) {
|
|
2803
|
+
this.clamp(props.clamp);
|
|
2804
|
+
}
|
|
2805
|
+
if (props.wheel) {
|
|
2806
|
+
if (props.wheel === true) {
|
|
2807
|
+
this.wheel();
|
|
2808
|
+
} else {
|
|
2809
|
+
this.wheel(props.wheel);
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2812
|
+
if (props.decelerate) {
|
|
2813
|
+
if (props.decelerate === true) {
|
|
2814
|
+
this.decelerate();
|
|
2815
|
+
} else {
|
|
2816
|
+
this.decelerate(props.decelerate);
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2819
|
+
if (props.pinch) {
|
|
2820
|
+
if (props.pinch === true) {
|
|
2821
|
+
this.pinch();
|
|
2822
|
+
} else {
|
|
2823
|
+
this.pinch(props.pinch);
|
|
2824
|
+
}
|
|
2825
|
+
}
|
|
2826
|
+
}
|
|
2827
|
+
onDestroy() {
|
|
2828
|
+
super.onDestroy();
|
|
2829
|
+
this.tickSubscription.unsubscribe();
|
|
2830
|
+
}
|
|
2831
|
+
};
|
|
2832
|
+
registerComponent("Viewport", CanvasViewport);
|
|
2833
|
+
function Viewport(props) {
|
|
2834
|
+
return createComponent("Viewport", props);
|
|
2835
|
+
}
|
|
2836
|
+
|
|
2837
|
+
// src/components/NineSliceSprite.ts
|
|
2838
|
+
import { Assets as Assets2, NineSliceSprite as PixiNineSliceSprite } from "pixi.js";
|
|
2839
|
+
var CanvasNineSliceSprite = class extends DisplayObject(PixiNineSliceSprite) {
|
|
2840
|
+
constructor() {
|
|
2841
|
+
super({
|
|
2842
|
+
width: 0,
|
|
2843
|
+
height: 0
|
|
2844
|
+
});
|
|
2845
|
+
}
|
|
2846
|
+
async onUpdate(props) {
|
|
2847
|
+
for (const [key, value] of Object.entries(props)) {
|
|
2848
|
+
if (value !== void 0) {
|
|
2849
|
+
if (key === "image") {
|
|
2850
|
+
this.texture = await Assets2.load(value);
|
|
2851
|
+
} else if (key in this) {
|
|
2852
|
+
this[key] = value;
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
};
|
|
2858
|
+
registerComponent("NineSliceSprite", CanvasNineSliceSprite);
|
|
2859
|
+
function NineSliceSprite(props) {
|
|
2860
|
+
return createComponent("NineSliceSprite", props);
|
|
2861
|
+
}
|
|
2862
|
+
|
|
2863
|
+
// src/engine/bootstrap.ts
|
|
2864
|
+
var bootstrapCanvas = async (rootElement, canvas) => {
|
|
2865
|
+
const canvasElement = await h(canvas);
|
|
2866
|
+
if (canvasElement.tag != "Canvas") {
|
|
2867
|
+
throw new Error("Canvas is required");
|
|
2868
|
+
}
|
|
2869
|
+
canvasElement.render(rootElement);
|
|
2870
|
+
return canvasElement;
|
|
2871
|
+
};
|
|
2872
|
+
|
|
2873
|
+
// src/utils/Ease.ts
|
|
2874
|
+
import {
|
|
2875
|
+
linear,
|
|
2876
|
+
easeIn,
|
|
2877
|
+
easeInOut,
|
|
2878
|
+
easeOut,
|
|
2879
|
+
circIn,
|
|
2880
|
+
circInOut,
|
|
2881
|
+
circOut,
|
|
2882
|
+
backIn,
|
|
2883
|
+
backInOut,
|
|
2884
|
+
backOut,
|
|
2885
|
+
anticipate,
|
|
2886
|
+
bounceIn,
|
|
2887
|
+
bounceInOut,
|
|
2888
|
+
bounceOut
|
|
2889
|
+
} from "popmotion";
|
|
2890
|
+
var Easing = {
|
|
2891
|
+
linear,
|
|
2892
|
+
easeIn,
|
|
2893
|
+
easeInOut,
|
|
2894
|
+
easeOut,
|
|
2895
|
+
circIn,
|
|
2896
|
+
circInOut,
|
|
2897
|
+
circOut,
|
|
2898
|
+
backIn,
|
|
2899
|
+
backInOut,
|
|
2900
|
+
backOut,
|
|
2901
|
+
anticipate,
|
|
2902
|
+
bounceIn,
|
|
2903
|
+
bounceInOut,
|
|
2904
|
+
bounceOut
|
|
2905
|
+
};
|
|
2906
|
+
|
|
2907
|
+
// src/utils/RadialGradient.ts
|
|
2908
|
+
import { Texture as Texture5, ImageSource, DOMAdapter, Matrix } from "pixi.js";
|
|
2909
|
+
var RadialGradient = class {
|
|
2910
|
+
/**
|
|
2911
|
+
* Creates a new RadialGradient instance
|
|
2912
|
+
* @param x0 - The x-coordinate of the starting circle
|
|
2913
|
+
* @param y0 - The y-coordinate of the starting circle
|
|
2914
|
+
* @param x1 - The x-coordinate of the ending circle
|
|
2915
|
+
* @param y1 - The y-coordinate of the ending circle
|
|
2916
|
+
* @param x2 - The x-coordinate for gradient transformation
|
|
2917
|
+
* @param y2 - The y-coordinate for gradient transformation
|
|
2918
|
+
* @param focalPoint - The focal point of the gradient (0-1), defaults to 0
|
|
2919
|
+
*/
|
|
2920
|
+
constructor(x0, y0, x1, y1, x2, y2, focalPoint = 0) {
|
|
2921
|
+
this.x0 = x0;
|
|
2922
|
+
this.y0 = y0;
|
|
2923
|
+
this.x1 = x1;
|
|
2924
|
+
this.y1 = y1;
|
|
2925
|
+
this.x2 = x2;
|
|
2926
|
+
this.y2 = y2;
|
|
2927
|
+
this.focalPoint = focalPoint;
|
|
2928
|
+
this.gradient = null;
|
|
2929
|
+
this.texture = null;
|
|
2930
|
+
this.size = 600;
|
|
2931
|
+
this.size = x0;
|
|
2932
|
+
const halfSize = this.size * 0.5;
|
|
2933
|
+
this.canvas = DOMAdapter.get().createCanvas();
|
|
2934
|
+
this.canvas.width = this.size;
|
|
2935
|
+
this.canvas.height = this.size;
|
|
2936
|
+
this.ctx = this.canvas.getContext("2d");
|
|
2937
|
+
if (this.ctx) {
|
|
2938
|
+
this.gradient = this.ctx.createRadialGradient(
|
|
2939
|
+
halfSize * (1 - focalPoint),
|
|
2940
|
+
halfSize,
|
|
2941
|
+
0,
|
|
2942
|
+
halfSize,
|
|
2943
|
+
halfSize,
|
|
2944
|
+
halfSize - 0.5
|
|
2945
|
+
);
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
/**
|
|
2949
|
+
* Adds a color stop to the gradient
|
|
2950
|
+
* @param offset - The position of the color stop (0-1)
|
|
2951
|
+
* @param color - The color value (any valid CSS color string)
|
|
2952
|
+
*/
|
|
2953
|
+
addColorStop(offset, color) {
|
|
2954
|
+
if (this.gradient) {
|
|
2955
|
+
this.gradient.addColorStop(offset, color);
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
/**
|
|
2959
|
+
* Renders the gradient and returns the texture with its transformation matrix
|
|
2960
|
+
* @param options - Render options
|
|
2961
|
+
* @param options.translate - Optional translation coordinates
|
|
2962
|
+
* @returns Object containing the texture and transformation matrix
|
|
2963
|
+
*/
|
|
2964
|
+
render({ translate } = {}) {
|
|
2965
|
+
const { x0, y0, x1, y1, x2, y2, focalPoint } = this;
|
|
2966
|
+
const defaultSize = this.size;
|
|
2967
|
+
if (this.ctx && this.gradient) {
|
|
2968
|
+
this.ctx.fillStyle = this.gradient;
|
|
2969
|
+
this.ctx.fillRect(0, 0, defaultSize, defaultSize);
|
|
2970
|
+
this.texture = new Texture5({
|
|
2971
|
+
source: new ImageSource({
|
|
2972
|
+
resource: this.canvas,
|
|
2973
|
+
addressModeU: "clamp-to-edge",
|
|
2974
|
+
addressModeV: "clamp-to-edge"
|
|
2975
|
+
})
|
|
2976
|
+
});
|
|
2977
|
+
const m = new Matrix();
|
|
2978
|
+
const dx = Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
|
|
2979
|
+
const dy = Math.sqrt((x2 - x0) * (x2 - x0) + (y2 - y0) * (y2 - y0));
|
|
2980
|
+
const angle = Math.atan2(y1 - y0, x1 - x0);
|
|
2981
|
+
const scaleX = dx / defaultSize;
|
|
2982
|
+
const scaleY = dy / defaultSize;
|
|
2983
|
+
m.rotate(-angle);
|
|
2984
|
+
m.scale(scaleX, scaleY);
|
|
2985
|
+
if (translate) {
|
|
2986
|
+
m.translate(translate.x, translate.y);
|
|
2987
|
+
}
|
|
2988
|
+
this.transform = m;
|
|
2989
|
+
}
|
|
2990
|
+
return {
|
|
2991
|
+
texture: this.texture,
|
|
2992
|
+
matrix: this.transform
|
|
2993
|
+
};
|
|
2994
|
+
}
|
|
2995
|
+
};
|
|
2996
|
+
|
|
2997
|
+
// src/index.ts
|
|
2998
|
+
import { isObservable } from "rxjs";
|
|
2999
|
+
export {
|
|
3000
|
+
Canvas2 as Canvas,
|
|
3001
|
+
Circle,
|
|
3002
|
+
Container4 as Container,
|
|
3003
|
+
DisplayObject,
|
|
3004
|
+
EVENTS2 as EVENTS,
|
|
3005
|
+
Easing,
|
|
3006
|
+
Ellipse,
|
|
3007
|
+
Graphics,
|
|
3008
|
+
Howler,
|
|
3009
|
+
NineSliceSprite,
|
|
3010
|
+
ParticlesEmitter,
|
|
3011
|
+
RadialGradient,
|
|
3012
|
+
Rect,
|
|
3013
|
+
Scene,
|
|
3014
|
+
Sprite2 as Sprite,
|
|
3015
|
+
Text,
|
|
3016
|
+
TilingSprite,
|
|
3017
|
+
Triangle,
|
|
3018
|
+
utils_exports as Utils,
|
|
3019
|
+
Viewport,
|
|
3020
|
+
animatedSignal,
|
|
3021
|
+
bootstrapCanvas,
|
|
3022
|
+
cond,
|
|
3023
|
+
createComponent,
|
|
3024
|
+
currentSubscriptionsTracker,
|
|
3025
|
+
h,
|
|
3026
|
+
isAnimatedSignal,
|
|
3027
|
+
isElement,
|
|
3028
|
+
isObservable,
|
|
3029
|
+
isPrimitive,
|
|
3030
|
+
isTrigger,
|
|
3031
|
+
loop,
|
|
3032
|
+
mount,
|
|
3033
|
+
mountTracker,
|
|
3034
|
+
on,
|
|
3035
|
+
registerComponent,
|
|
3036
|
+
Svg as svg,
|
|
3037
|
+
tick,
|
|
3038
|
+
trigger,
|
|
3039
|
+
useDefineProps,
|
|
3040
|
+
useProps
|
|
3041
|
+
};
|
|
3042
|
+
//# sourceMappingURL=index.js.map
|