@makefully/platypus 4.1.8 → 4.1.10
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/CHANGELOG.md +32 -0
- package/lib/platypus.js +1 -1
- package/package.json +1 -1
- package/src/AssetManager.js +44 -2
- package/src/VOPlayer.js +1 -1
- package/src/components/LevelBuilder.js +37 -19
- package/src/components/Render.js +11 -1
- package/src/components/RenderTiles.js +163 -132
- package/src/components/TiledLoader.js +8 -4
- package/src/utils/clone.js +11 -0
package/package.json
CHANGED
package/src/AssetManager.js
CHANGED
|
@@ -26,6 +26,9 @@ const
|
|
|
26
26
|
'src', path,
|
|
27
27
|
'data', asset.data ?? null
|
|
28
28
|
);
|
|
29
|
+
},
|
|
30
|
+
isRegisteredWithPixi = function (alias, src) {
|
|
31
|
+
return Assets.resolver.hasKey(alias) || (src && src !== alias && Assets.resolver.hasKey(src));
|
|
29
32
|
};
|
|
30
33
|
|
|
31
34
|
export default class AssetManager {
|
|
@@ -71,7 +74,18 @@ export default class AssetManager {
|
|
|
71
74
|
* @return {Object} Returns the asset if defined.
|
|
72
75
|
*/
|
|
73
76
|
get (alias) {
|
|
74
|
-
|
|
77
|
+
if (this.assets.has(alias)) {
|
|
78
|
+
return this.assets.get(alias);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const
|
|
82
|
+
fileId = this.getFileId(alias);
|
|
83
|
+
|
|
84
|
+
if (fileId !== alias && this.assets.has(fileId)) {
|
|
85
|
+
return this.assets.get(fileId);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return undefined;
|
|
75
89
|
}
|
|
76
90
|
|
|
77
91
|
/**
|
|
@@ -131,6 +145,7 @@ export default class AssetManager {
|
|
|
131
145
|
const
|
|
132
146
|
counts = this.counts,
|
|
133
147
|
needsLoading = arrayCache.setUp(),
|
|
148
|
+
needsRelink = arrayCache.setUp(),
|
|
134
149
|
adds = Data.setUp();
|
|
135
150
|
|
|
136
151
|
if (platypus.game?.options?.images ?? platypus.game?.options?.audio) {
|
|
@@ -154,13 +169,39 @@ export default class AssetManager {
|
|
|
154
169
|
adds[alias] += 1;
|
|
155
170
|
} else {
|
|
156
171
|
adds[alias] = 1;
|
|
172
|
+
if (isRegisteredWithPixi(alias, item.src)) {
|
|
173
|
+
needsRelink.push(item);
|
|
174
|
+
} else {
|
|
175
|
+
needsLoading.push(item);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
for (let i = needsRelink.length - 1; i >= 0; i--) {
|
|
181
|
+
const
|
|
182
|
+
item = needsRelink[i],
|
|
183
|
+
alias = item.alias[0],
|
|
184
|
+
asset = Assets.get(alias) ?? Assets.get(item.src);
|
|
185
|
+
|
|
186
|
+
if (asset) {
|
|
187
|
+
this.set(alias, asset, adds[alias]);
|
|
188
|
+
needsRelink.splice(i, 1);
|
|
189
|
+
} else {
|
|
157
190
|
needsLoading.push(item);
|
|
191
|
+
needsRelink.splice(i, 1);
|
|
158
192
|
}
|
|
159
193
|
}
|
|
160
194
|
|
|
161
195
|
if (needsLoading.length) {
|
|
162
196
|
// Do this first to pass `data` property if needed
|
|
163
|
-
needsLoading.forEach((asset) =>
|
|
197
|
+
needsLoading.forEach((asset) => {
|
|
198
|
+
const
|
|
199
|
+
alias = asset.alias[0];
|
|
200
|
+
|
|
201
|
+
if (!isRegisteredWithPixi(alias, asset.src)) {
|
|
202
|
+
Assets.add(asset);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
164
205
|
|
|
165
206
|
const
|
|
166
207
|
aliases = needsLoading.map((asset) => asset.alias[0]),
|
|
@@ -188,6 +229,7 @@ export default class AssetManager {
|
|
|
188
229
|
}
|
|
189
230
|
|
|
190
231
|
arrayCache.recycle(needsLoading);
|
|
232
|
+
arrayCache.recycle(needsRelink);
|
|
191
233
|
}
|
|
192
234
|
|
|
193
235
|
/**
|
package/src/VOPlayer.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* global atob, platypus */
|
|
2
2
|
import {arrayCache, greenSlice, greenSplice, union} from '../utils/array.js';
|
|
3
|
+
import {cloneDefinition} from '../utils/clone.js';
|
|
3
4
|
import createComponentClass from '../factory.js';
|
|
4
5
|
import {inflate} from 'pako';
|
|
5
6
|
import TiledLoader from './TiledLoader.js';
|
|
@@ -31,6 +32,21 @@ const
|
|
|
31
32
|
}
|
|
32
33
|
return layer;
|
|
33
34
|
},
|
|
35
|
+
cloneLevelDefinition = cloneDefinition,
|
|
36
|
+
copySegmentProperty = function (target, source, key) {
|
|
37
|
+
if (target[key]) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const
|
|
42
|
+
value = source[key];
|
|
43
|
+
|
|
44
|
+
if (value != null && typeof value === 'object') {
|
|
45
|
+
target[key] = cloneDefinition(value);
|
|
46
|
+
} else {
|
|
47
|
+
target[key] = value;
|
|
48
|
+
}
|
|
49
|
+
},
|
|
34
50
|
mergeData = function (levelData, levelMergeAxisLength, segmentData, segmentMergeAxisLength, nonMergeAxisLength, mergeAxis) {
|
|
35
51
|
const
|
|
36
52
|
combined = greenSlice(levelData);
|
|
@@ -54,9 +70,7 @@ const
|
|
|
54
70
|
|
|
55
71
|
for (let i = 0; i < obj2s.length; i++) {
|
|
56
72
|
const
|
|
57
|
-
obj =
|
|
58
|
-
...obj2s[i]
|
|
59
|
-
};
|
|
73
|
+
obj = cloneLevelDefinition(obj2s[i]);
|
|
60
74
|
|
|
61
75
|
if (mergeAxis === 'horizontal') {
|
|
62
76
|
obj.x += mergeAxisLength;
|
|
@@ -68,6 +82,8 @@ const
|
|
|
68
82
|
return list;
|
|
69
83
|
},
|
|
70
84
|
mergeSegment = function (level, segment, mergeAxis) {
|
|
85
|
+
segment = cloneLevelDefinition(segment);
|
|
86
|
+
|
|
71
87
|
if (!level.tilewidth && !level.tileheight) {
|
|
72
88
|
//set level tile size data if it's not already set.
|
|
73
89
|
level.tilewidth = segment.tilewidth;
|
|
@@ -96,9 +112,7 @@ const
|
|
|
96
112
|
decodeLayer(segment.layers[i]);
|
|
97
113
|
|
|
98
114
|
const
|
|
99
|
-
layer = level.layers[i] =
|
|
100
|
-
...segment.layers[i]
|
|
101
|
-
};
|
|
115
|
+
layer = level.layers[i] = cloneLevelDefinition(segment.layers[i]);
|
|
102
116
|
|
|
103
117
|
// If we're adding objects, make sure that they're offset correctly.
|
|
104
118
|
if (layer.objects) {
|
|
@@ -149,9 +163,7 @@ const
|
|
|
149
163
|
const
|
|
150
164
|
key = keys[i];
|
|
151
165
|
|
|
152
|
-
|
|
153
|
-
level[key] = segment[key];
|
|
154
|
-
}
|
|
166
|
+
copySegmentProperty(level, segment, key);
|
|
155
167
|
}
|
|
156
168
|
}
|
|
157
169
|
},
|
|
@@ -200,6 +212,8 @@ const
|
|
|
200
212
|
return level;
|
|
201
213
|
},
|
|
202
214
|
mirrorSegment = function (segment) {
|
|
215
|
+
segment = cloneLevelDefinition(segment);
|
|
216
|
+
|
|
203
217
|
const
|
|
204
218
|
newSegment = {
|
|
205
219
|
layers: []
|
|
@@ -211,9 +225,7 @@ const
|
|
|
211
225
|
|
|
212
226
|
const
|
|
213
227
|
fromLayer = segment.layers[i],
|
|
214
|
-
toLayer = newSegment.layers[i] =
|
|
215
|
-
...fromLayer
|
|
216
|
-
};
|
|
228
|
+
toLayer = newSegment.layers[i] = cloneLevelDefinition(fromLayer);
|
|
217
229
|
|
|
218
230
|
if (fromLayer.data) {
|
|
219
231
|
const
|
|
@@ -237,9 +249,7 @@ const
|
|
|
237
249
|
for (let j = 0; j < fromObjects.length; j++) {
|
|
238
250
|
const
|
|
239
251
|
fromObject = fromObjects[j],
|
|
240
|
-
toObject = toObjects[j] =
|
|
241
|
-
...fromObject
|
|
242
|
-
};
|
|
252
|
+
toObject = toObjects[j] = cloneLevelDefinition(fromObject);
|
|
243
253
|
|
|
244
254
|
toObject.x = width - fromObject.x - (fromObject.width || 0); // subtract object width since its top-left corner is the origin.
|
|
245
255
|
if (fromObject.rotation) {
|
|
@@ -265,9 +275,7 @@ const
|
|
|
265
275
|
const
|
|
266
276
|
key = keys[i];
|
|
267
277
|
|
|
268
|
-
|
|
269
|
-
newSegment[key] = segment[key];
|
|
270
|
-
}
|
|
278
|
+
copySegmentProperty(newSegment, segment, key);
|
|
271
279
|
}
|
|
272
280
|
}
|
|
273
281
|
|
|
@@ -351,6 +359,10 @@ export default createComponentClass(/** @lends platypus.components.LevelBuilder.
|
|
|
351
359
|
|
|
352
360
|
events: {
|
|
353
361
|
"layer-loaded": function (data) {
|
|
362
|
+
if (data?.level && typeof data.level === 'object') {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
354
366
|
const
|
|
355
367
|
piecesToCopy = data?.levelPieces ?? this.levelPieces;
|
|
356
368
|
|
|
@@ -417,7 +429,10 @@ export default createComponentClass(/** @lends platypus.components.LevelBuilder.
|
|
|
417
429
|
* @param data.persistentData.levelPieces {Object} An object of key/value pairs listing the pieces that map to an id in the level template.
|
|
418
430
|
* @param data.persistentData.useUniques {Boolean} If true, no single map piece is used twice in the creation of the combined map.
|
|
419
431
|
*/
|
|
420
|
-
this.owner.triggerEvent('created-level',
|
|
432
|
+
this.owner.triggerEvent('created-level', {
|
|
433
|
+
level: cloneLevelDefinition(this.levelMessage.level),
|
|
434
|
+
persistentData: this.levelMessage.persistentData
|
|
435
|
+
});
|
|
421
436
|
|
|
422
437
|
/**
|
|
423
438
|
* Dispatched when the scene has loaded and the level has been composited so TileLoader can begin loading the level.
|
|
@@ -462,6 +477,9 @@ export default createComponentClass(/** @lends platypus.components.LevelBuilder.
|
|
|
462
477
|
throw new Error(`Level Builder: There are no level pieces of type: ${type}`);
|
|
463
478
|
}
|
|
464
479
|
},
|
|
480
|
+
cloneLevel: function (level) {
|
|
481
|
+
return cloneLevelDefinition(level);
|
|
482
|
+
},
|
|
465
483
|
destroy: function () {
|
|
466
484
|
this.levelMessage.level = null;
|
|
467
485
|
this.levelMessage.persistentData = null;
|
package/src/components/Render.js
CHANGED
|
@@ -98,8 +98,18 @@ export default createComponentClass(/** @lends platypus.components.RenderSprite.
|
|
|
98
98
|
initialize () {
|
|
99
99
|
const
|
|
100
100
|
{image, images, localRotation, localScaleX, localScaleY, offsetX, offsetY, offsetZ, options, owner, spriteType} = this,
|
|
101
|
+
resolveTexture = (path) => {
|
|
102
|
+
const
|
|
103
|
+
texture = platypus.assetCache.get(path);
|
|
104
|
+
|
|
105
|
+
if (!texture) {
|
|
106
|
+
platypus.debug.warn(`Render: Image is not a loaded asset: ${path}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return texture;
|
|
110
|
+
},
|
|
101
111
|
sprite = this.sprite = new spriteTypes[spriteType === 'Sprite' && images && !images ? 'AnimatedSprite' : spriteType]({
|
|
102
|
-
...(image ? {texture:
|
|
112
|
+
...(image ? {texture: resolveTexture(image)} : {textures: images.map((path) => resolveTexture(path))}),
|
|
103
113
|
...options ?? {}
|
|
104
114
|
}),
|
|
105
115
|
matchEntity = this.matchEntity ? {
|
|
@@ -437,14 +437,7 @@ export default createComponentClass(/** @lends platypus.components.RenderTiles.p
|
|
|
437
437
|
|
|
438
438
|
if (map) {
|
|
439
439
|
this.updateTile(tile, map[z || 0], x, y);
|
|
440
|
-
|
|
441
|
-
// cached region. Changes outside the cache will be drawn correctly
|
|
442
|
-
// the next time the camera pans to include them.
|
|
443
|
-
if (!this.cache.empty &&
|
|
444
|
-
x >= this.cache.left && x <= this.cache.right &&
|
|
445
|
-
y >= this.cache.top && y <= this.cache.bottom) {
|
|
446
|
-
this.updateCache = true;
|
|
447
|
-
}
|
|
440
|
+
this.updateCache = true;
|
|
448
441
|
}
|
|
449
442
|
},
|
|
450
443
|
|
|
@@ -458,70 +451,13 @@ export default createComponentClass(/** @lends platypus.components.RenderTiles.p
|
|
|
458
451
|
},
|
|
459
452
|
|
|
460
453
|
/**
|
|
461
|
-
* Forces an immediate full re-render
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
* For the panning cache, we invalidate cachePixels and re-run the full
|
|
466
|
-
* camera-update recache logic using the last known camera, which correctly
|
|
467
|
-
* handles texture swapping, tile population, and sprite positioning.
|
|
454
|
+
* Forces an immediate full re-render of all cached tile textures.
|
|
455
|
+
* Call this after bulk tile changes to ensure the display is up to date
|
|
456
|
+
* without requiring a camera pan.
|
|
468
457
|
*/
|
|
469
458
|
"force-render": function () {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
this.populateTiles(this.cache, null);
|
|
473
|
-
this.renderCache(this.cache, this.cacheTexture, this.mapContainer, this.mapContainerWrapper);
|
|
474
|
-
} else if (this.cacheTexture) {
|
|
475
|
-
// Panning cache — invalidate cachePixels so the recache branch
|
|
476
|
-
// runs, then execute the full camera-update recache inline.
|
|
477
|
-
const
|
|
478
|
-
{viewport: vp} = this.owner.parent.worldCamera,
|
|
479
|
-
{cache, cachePixels} = this,
|
|
480
|
-
tempC = tempCache,
|
|
481
|
-
ctw = this.cacheTilesWidth - 1,
|
|
482
|
-
cth = this.cacheTilesHeight - 1,
|
|
483
|
-
ctw2 = ctw / 2,
|
|
484
|
-
cth2 = cth / 2;
|
|
485
|
-
|
|
486
|
-
this.convertCamera(vp);
|
|
487
|
-
|
|
488
|
-
// Force the recache branch to run regardless of camera position.
|
|
489
|
-
cachePixels.empty = true;
|
|
490
|
-
|
|
491
|
-
tempC.setAll(
|
|
492
|
-
Math.round((this.laxCam.x - this.left) / this.tileWidth - ctw2) + ctw2,
|
|
493
|
-
Math.round((this.laxCam.y - this.top) / this.tileHeight - cth2) + cth2,
|
|
494
|
-
ctw, cth
|
|
495
|
-
);
|
|
496
|
-
if (tempC.left < 0) {
|
|
497
|
-
tempC.moveX(tempC.halfWidth);
|
|
498
|
-
} else if (tempC.right > this.tilesWidth - 1) {
|
|
499
|
-
tempC.moveX(this.tilesWidth - 1 - tempC.halfWidth);
|
|
500
|
-
}
|
|
501
|
-
if (tempC.top < 0) {
|
|
502
|
-
tempC.moveY(tempC.halfHeight);
|
|
503
|
-
} else if (tempC.bottom > this.tilesHeight - 1) {
|
|
504
|
-
tempC.moveY(this.tilesHeight - 1 - tempC.halfHeight);
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
this.tilesSpriteCache.texture = this.cacheTexture;
|
|
508
|
-
this.cacheTexture = this.cacheTexture.alternate;
|
|
509
|
-
this.tilesSprite.texture = this.cacheTexture;
|
|
510
|
-
|
|
511
|
-
this.populateTiles(tempC, cache);
|
|
512
|
-
this.renderCache(tempC, this.cacheTexture, this.mapContainer, this.mapContainerWrapper, this.tilesSpriteCache);
|
|
513
|
-
cache.set(tempC);
|
|
514
|
-
|
|
515
|
-
cachePixels.setAll(
|
|
516
|
-
(cache.x + 0.5) * this.tileWidth + this.left,
|
|
517
|
-
(cache.y + 0.5) * this.tileHeight + this.top,
|
|
518
|
-
(cache.width + 1) * this.tileWidth,
|
|
519
|
-
(cache.height + 1) * this.tileHeight
|
|
520
|
-
);
|
|
521
|
-
|
|
522
|
-
this.tilesSprite.x = vp.left - this.laxCam.left + cache.left * this.tileWidth + this.left;
|
|
523
|
-
this.tilesSprite.y = vp.top - this.laxCam.top + cache.top * this.tileHeight + this.top;
|
|
524
|
-
}
|
|
459
|
+
this.refreshAllCaches();
|
|
460
|
+
this.updateCache = false;
|
|
525
461
|
}
|
|
526
462
|
},
|
|
527
463
|
|
|
@@ -571,8 +507,7 @@ export default createComponentClass(/** @lends platypus.components.RenderTiles.p
|
|
|
571
507
|
'handle-render': function () {
|
|
572
508
|
if (this.updateCache) {
|
|
573
509
|
this.updateCache = false;
|
|
574
|
-
this.
|
|
575
|
-
this.renderCache(this.cache, this.cacheTexture, this.mapContainer, this.mapContainerWrapper);
|
|
510
|
+
this.refreshAllCaches();
|
|
576
511
|
}
|
|
577
512
|
}
|
|
578
513
|
});
|
|
@@ -632,21 +567,8 @@ export default createComponentClass(/** @lends platypus.components.RenderTiles.p
|
|
|
632
567
|
},
|
|
633
568
|
'handle-render': function () {
|
|
634
569
|
if (this.updateCache) {
|
|
635
|
-
const
|
|
636
|
-
{cache, cacheGrid, cacheTilesHeight, cacheTilesWidth, tilesHeight, tilesWidth} = this,
|
|
637
|
-
tsh = tilesHeight - 1,
|
|
638
|
-
tsw = tilesWidth - 1;
|
|
639
|
-
|
|
640
570
|
this.updateCache = false;
|
|
641
|
-
|
|
642
|
-
for (let x = 0; x < cacheGrid.length; x++) {
|
|
643
|
-
for (let y = 0; y < cacheGrid[x].length; y++) {
|
|
644
|
-
cache.setBounds(x * cacheTilesWidth, y * cacheTilesHeight, Math.min((x + 1) * cacheTilesWidth, tsw), Math.min((y + 1) * cacheTilesHeight, tsh));
|
|
645
|
-
|
|
646
|
-
this.populateTiles(cache, null);
|
|
647
|
-
this.renderCacheWithExtrusion(cache, cacheGrid[x][y].texture, this.mapContainer, this.mapContainerWrapper);
|
|
648
|
-
}
|
|
649
|
-
}
|
|
571
|
+
this.refreshAllCaches();
|
|
650
572
|
}
|
|
651
573
|
}
|
|
652
574
|
});
|
|
@@ -699,24 +621,7 @@ export default createComponentClass(/** @lends platypus.components.RenderTiles.p
|
|
|
699
621
|
this.updateBufferRegion(laxCam);
|
|
700
622
|
}
|
|
701
623
|
|
|
702
|
-
|
|
703
|
-
ctw = this.cacheTilesWidth - 1,
|
|
704
|
-
cth = this.cacheTilesHeight - 1,
|
|
705
|
-
ctw2 = ctw / 2,
|
|
706
|
-
cth2 = cth / 2;
|
|
707
|
-
|
|
708
|
-
//only attempt to draw children that are relevant
|
|
709
|
-
tempC.setAll(Math.round((laxCam.x - this.left) / this.tileWidth - ctw2) + ctw2, Math.round((laxCam.y - this.top) / this.tileHeight - cth2) + cth2, ctw, cth);
|
|
710
|
-
if (tempC.left < 0) {
|
|
711
|
-
tempC.moveX(tempC.halfWidth);
|
|
712
|
-
} else if (tempC.right > this.tilesWidth - 1) {
|
|
713
|
-
tempC.moveX(this.tilesWidth - 1 - tempC.halfWidth);
|
|
714
|
-
}
|
|
715
|
-
if (tempC.top < 0) {
|
|
716
|
-
tempC.moveY(tempC.halfHeight);
|
|
717
|
-
} else if (tempC.bottom > this.tilesHeight - 1) {
|
|
718
|
-
tempC.moveY(this.tilesHeight - 1 - tempC.halfHeight);
|
|
719
|
-
}
|
|
624
|
+
this.alignCacheToCamera(tempC, vp);
|
|
720
625
|
|
|
721
626
|
this.tilesSpriteCache.texture = this.cacheTexture;
|
|
722
627
|
this.cacheTexture = this.cacheTexture.alternate;
|
|
@@ -734,17 +639,9 @@ export default createComponentClass(/** @lends platypus.components.RenderTiles.p
|
|
|
734
639
|
this.tilesSprite.y = vp.top - laxCam.top + cache.top * this.tileHeight + this.top;
|
|
735
640
|
},
|
|
736
641
|
'handle-render': function () {
|
|
737
|
-
if (this.updateCache
|
|
642
|
+
if (this.updateCache) {
|
|
738
643
|
this.updateCache = false;
|
|
739
|
-
this.
|
|
740
|
-
this.renderCacheClear(this.cache, this.cacheTexture, this.mapContainer, this.mapContainerWrapper);
|
|
741
|
-
this.tilesSpriteCache.texture = this.cacheTexture;
|
|
742
|
-
this.cachePixels.setAll(
|
|
743
|
-
(this.cache.x + 0.5) * this.tileWidth + this.left,
|
|
744
|
-
(this.cache.y + 0.5) * this.tileHeight + this.top,
|
|
745
|
-
(this.cache.width + 1) * this.tileWidth,
|
|
746
|
-
(this.cache.height + 1) * this.tileHeight
|
|
747
|
-
);
|
|
644
|
+
this.refreshAllCaches();
|
|
748
645
|
}
|
|
749
646
|
}
|
|
750
647
|
});
|
|
@@ -782,24 +679,7 @@ export default createComponentClass(/** @lends platypus.components.RenderTiles.p
|
|
|
782
679
|
this.updateBufferRegion(laxCam);
|
|
783
680
|
}
|
|
784
681
|
|
|
785
|
-
|
|
786
|
-
ctw = this.cacheTilesWidth - 1,
|
|
787
|
-
cth = this.cacheTilesHeight - 1,
|
|
788
|
-
ctw2 = ctw / 2,
|
|
789
|
-
cth2 = cth / 2;
|
|
790
|
-
|
|
791
|
-
//only attempt to draw children that are relevant
|
|
792
|
-
tempC.setAll(Math.round((laxCam.x - this.left) / this.tileWidth - ctw2) + ctw2, Math.round((laxCam.y - this.top) / this.tileHeight - cth2) + cth2, ctw, cth);
|
|
793
|
-
if (tempC.left < 0) {
|
|
794
|
-
tempC.moveX(tempC.halfWidth);
|
|
795
|
-
} else if (tempC.right > this.tilesWidth - 1) {
|
|
796
|
-
tempC.moveX(this.tilesWidth - 1 - tempC.halfWidth);
|
|
797
|
-
}
|
|
798
|
-
if (tempC.top < 0) {
|
|
799
|
-
tempC.moveY(tempC.halfHeight);
|
|
800
|
-
} else if (tempC.bottom > this.tilesHeight - 1) {
|
|
801
|
-
tempC.moveY(this.tilesHeight - 1 - tempC.halfHeight);
|
|
802
|
-
}
|
|
682
|
+
this.alignCacheToCamera(tempC, vp);
|
|
803
683
|
|
|
804
684
|
this.populateTiles(tempC, null);
|
|
805
685
|
cache.set(tempC);
|
|
@@ -1079,7 +959,151 @@ export default createComponentClass(/** @lends platypus.components.RenderTiles.p
|
|
|
1079
959
|
this.mapContainer.mask = new Graphics().rect(0, 0, this.cacheClipWidth, this.cacheClipHeight).fill(0x000000);
|
|
1080
960
|
},
|
|
1081
961
|
|
|
962
|
+
/**
|
|
963
|
+
* Computes tile bounds for the panning cache centered on the current camera.
|
|
964
|
+
*
|
|
965
|
+
* @param {platypus.AABB} bounds - Receives the computed tile bounds.
|
|
966
|
+
* @param {platypus.AABB} viewport - The camera viewport.
|
|
967
|
+
*/
|
|
968
|
+
alignCacheToCamera: function (bounds, viewport) {
|
|
969
|
+
const
|
|
970
|
+
ctw = this.cacheTilesWidth - 1,
|
|
971
|
+
cth = this.cacheTilesHeight - 1,
|
|
972
|
+
ctw2 = ctw / 2,
|
|
973
|
+
cth2 = cth / 2;
|
|
974
|
+
|
|
975
|
+
this.convertCamera(viewport);
|
|
976
|
+
|
|
977
|
+
bounds.setAll(
|
|
978
|
+
Math.round((this.laxCam.x - this.left) / this.tileWidth - ctw2) + ctw2,
|
|
979
|
+
Math.round((this.laxCam.y - this.top) / this.tileHeight - cth2) + cth2,
|
|
980
|
+
ctw, cth
|
|
981
|
+
);
|
|
982
|
+
|
|
983
|
+
if (bounds.left < 0) {
|
|
984
|
+
bounds.moveX(bounds.halfWidth);
|
|
985
|
+
} else if (bounds.right > this.tilesWidth - 1) {
|
|
986
|
+
bounds.moveX(this.tilesWidth - 1 - bounds.halfWidth);
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
if (bounds.top < 0) {
|
|
990
|
+
bounds.moveY(bounds.halfHeight);
|
|
991
|
+
} else if (bounds.bottom > this.tilesHeight - 1) {
|
|
992
|
+
bounds.moveY(this.tilesHeight - 1 - bounds.halfHeight);
|
|
993
|
+
}
|
|
994
|
+
},
|
|
995
|
+
|
|
996
|
+
/**
|
|
997
|
+
* Re-renders every texture in a multi-texture full-map cache grid.
|
|
998
|
+
*/
|
|
999
|
+
refreshAllCacheGrid: function () {
|
|
1000
|
+
const
|
|
1001
|
+
{cache, cacheGrid, cacheTilesHeight, cacheTilesWidth, tilesHeight, tilesWidth} = this,
|
|
1002
|
+
tsh = tilesHeight - 1,
|
|
1003
|
+
tsw = tilesWidth - 1;
|
|
1004
|
+
|
|
1005
|
+
for (let x = 0; x < cacheGrid.length; x++) {
|
|
1006
|
+
for (let y = 0; y < cacheGrid[x].length; y++) {
|
|
1007
|
+
cache.setBounds(
|
|
1008
|
+
x * cacheTilesWidth,
|
|
1009
|
+
y * cacheTilesHeight,
|
|
1010
|
+
Math.min((x + 1) * cacheTilesWidth, tsw),
|
|
1011
|
+
Math.min((y + 1) * cacheTilesHeight, tsh)
|
|
1012
|
+
);
|
|
1013
|
+
|
|
1014
|
+
this.populate(cache, null);
|
|
1015
|
+
this.renderCacheWithExtrusion(cache, cacheGrid[x][y].texture, this.mapContainer, this.mapContainerWrapper);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
},
|
|
1019
|
+
|
|
1020
|
+
/**
|
|
1021
|
+
* Re-renders the current panning-cache window in place.
|
|
1022
|
+
* Uses the alternate render texture while drawing so we never render
|
|
1023
|
+
* into the texture that is currently displayed on screen.
|
|
1024
|
+
*
|
|
1025
|
+
* @param {platypus.AABB} [viewport] - Optional camera viewport.
|
|
1026
|
+
*/
|
|
1027
|
+
refreshPanningCache: function (viewport) {
|
|
1028
|
+
const
|
|
1029
|
+
{cache, cachePixels, laxCam, left, top, tilesSprite} = this,
|
|
1030
|
+
vp = viewport ?? this.owner.parent.worldCamera?.viewport;
|
|
1031
|
+
|
|
1032
|
+
if (!vp) {
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
if (cache.empty) {
|
|
1037
|
+
this.alignCacheToCamera(cache, vp);
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
if (cache.empty) {
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
this.detachCacheCopy();
|
|
1045
|
+
|
|
1046
|
+
this.tilesSpriteCache.texture = this.cacheTexture;
|
|
1047
|
+
this.cacheTexture = this.cacheTexture.alternate;
|
|
1048
|
+
tilesSprite.texture = this.cacheTexture;
|
|
1049
|
+
|
|
1050
|
+
this.populate(cache, null);
|
|
1051
|
+
this.renderCacheClear(cache, this.cacheTexture, this.mapContainer, this.mapContainerWrapper);
|
|
1052
|
+
|
|
1053
|
+
this.tilesSpriteCache.texture = this.cacheTexture;
|
|
1054
|
+
cachePixels.setAll(
|
|
1055
|
+
(cache.x + 0.5) * this.tileWidth + left,
|
|
1056
|
+
(cache.y + 0.5) * this.tileHeight + top,
|
|
1057
|
+
(cache.width + 1) * this.tileWidth,
|
|
1058
|
+
(cache.height + 1) * this.tileHeight
|
|
1059
|
+
);
|
|
1060
|
+
|
|
1061
|
+
this.convertCamera(vp);
|
|
1062
|
+
tilesSprite.x = vp.left - laxCam.left + cache.left * this.tileWidth + left;
|
|
1063
|
+
tilesSprite.y = vp.top - laxCam.top + cache.top * this.tileHeight + top;
|
|
1064
|
+
},
|
|
1065
|
+
|
|
1066
|
+
detachCacheCopy: function () {
|
|
1067
|
+
const
|
|
1068
|
+
{mapContainer, tilesSpriteCache} = this;
|
|
1069
|
+
|
|
1070
|
+
if (tilesSpriteCache?.parent === mapContainer) {
|
|
1071
|
+
mapContainer.removeChild(tilesSpriteCache);
|
|
1072
|
+
}
|
|
1073
|
+
},
|
|
1074
|
+
|
|
1075
|
+
/**
|
|
1076
|
+
* Re-renders all cached tile textures for the active caching strategy.
|
|
1077
|
+
*
|
|
1078
|
+
* @param {platypus.AABB} [viewport] - Optional camera viewport for panning caches.
|
|
1079
|
+
*/
|
|
1080
|
+
refreshAllCaches: function (viewport) {
|
|
1081
|
+
if (!this.tileCache) {
|
|
1082
|
+
this.cachePixels.empty = true;
|
|
1083
|
+
return;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
if (this.cacheGrid) {
|
|
1087
|
+
this.refreshAllCacheGrid();
|
|
1088
|
+
return;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
if (this.cacheAll && this.cacheTexture) {
|
|
1092
|
+
this.populate(this.cache, null);
|
|
1093
|
+
this.render(this.cache, this.cacheTexture, this.mapContainer, this.mapContainerWrapper);
|
|
1094
|
+
return;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
if (this.cacheTexture) {
|
|
1098
|
+
this.refreshPanningCache(viewport);
|
|
1099
|
+
}
|
|
1100
|
+
},
|
|
1101
|
+
|
|
1082
1102
|
populateTiles: function (bounds, oldBounds) {
|
|
1103
|
+
// When oldBounds is provided, only tiles outside the previous window are
|
|
1104
|
+
// drawn. That is correct for camera scrolling (reuse pixels from the old
|
|
1105
|
+
// cache texture) but must not be used for in-place tile edits — pass null
|
|
1106
|
+
// to redraw the entire bounds.
|
|
1083
1107
|
const
|
|
1084
1108
|
tiles = arrayCache.setUp();
|
|
1085
1109
|
|
|
@@ -1194,6 +1218,11 @@ export default createComponentClass(/** @lends platypus.components.RenderTiles.p
|
|
|
1194
1218
|
container: wrapper,
|
|
1195
1219
|
target: renderTexture
|
|
1196
1220
|
});
|
|
1221
|
+
|
|
1222
|
+
if (oldCache?.parent === src) {
|
|
1223
|
+
src.removeChild(oldCache);
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1197
1226
|
renderTexture.requiresUpdate = true;
|
|
1198
1227
|
},
|
|
1199
1228
|
|
|
@@ -1201,6 +1230,8 @@ export default createComponentClass(/** @lends platypus.components.RenderTiles.p
|
|
|
1201
1230
|
const
|
|
1202
1231
|
{renderer} = this;
|
|
1203
1232
|
|
|
1233
|
+
this.detachCacheCopy();
|
|
1234
|
+
|
|
1204
1235
|
src.x = -bounds.left * this.tileWidth;
|
|
1205
1236
|
src.y = -bounds.top * this.tileHeight;
|
|
1206
1237
|
renderer.render({
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* global atob, platypus */
|
|
2
2
|
import {arrayCache, greenSlice, union} from '../utils/array.js';
|
|
3
|
+
import {cloneDefinition} from '../utils/clone.js';
|
|
3
4
|
import AABB from '../AABB.js';
|
|
4
5
|
import Data from '../Data.js';
|
|
5
6
|
import DataMap from '../DataMap.js';
|
|
@@ -336,6 +337,7 @@ const
|
|
|
336
337
|
},
|
|
337
338
|
checkLevel = function (levelOrLevelId, ss) {
|
|
338
339
|
const
|
|
340
|
+
cacheAssetsOnLevel = typeof levelOrLevelId === 'string',
|
|
339
341
|
addObjectGroupAssets = (assets, objectGroup, tilesets) => {
|
|
340
342
|
const objects = objectGroup.objects;
|
|
341
343
|
|
|
@@ -356,7 +358,7 @@ const
|
|
|
356
358
|
level.tilesets = importTilesetData(level.tilesets);
|
|
357
359
|
}
|
|
358
360
|
|
|
359
|
-
if (level.assets) { // Property added by a previous parse (so that this algorithm isn't run on the same level multiple times)
|
|
361
|
+
if (cacheAssetsOnLevel && level.assets) { // Property added by a previous parse (so that this algorithm isn't run on the same level multiple times)
|
|
360
362
|
union(assets, level.assets);
|
|
361
363
|
} else if (level.layers) {
|
|
362
364
|
for (let i = 0; i < level.layers.length; i++) {
|
|
@@ -405,7 +407,7 @@ const
|
|
|
405
407
|
tile = tiles[l];
|
|
406
408
|
|
|
407
409
|
if (((tile.id + firstgid) === id) && tile.objectgroup) {
|
|
408
|
-
addObjectGroupAssets(assets, tile.objectgroup);
|
|
410
|
+
addObjectGroupAssets(assets, tile.objectgroup, level.tilesets);
|
|
409
411
|
}
|
|
410
412
|
}
|
|
411
413
|
}
|
|
@@ -452,7 +454,9 @@ const
|
|
|
452
454
|
union(assets, tilesets);
|
|
453
455
|
arrayCache.recycle(tilesets);
|
|
454
456
|
}
|
|
455
|
-
|
|
457
|
+
if (cacheAssetsOnLevel) {
|
|
458
|
+
level.assets = greenSlice(assets); // Save for later in case this level is checked again.
|
|
459
|
+
}
|
|
456
460
|
}
|
|
457
461
|
}
|
|
458
462
|
|
|
@@ -746,7 +750,7 @@ export default createComponentClass(/** @lends platypus.components.TiledLoader.p
|
|
|
746
750
|
} = layerProperties ? checkParallax(layer) : layer,
|
|
747
751
|
mapOffsetX = offsetX + layerOffsetX,
|
|
748
752
|
mapOffsetY = offsetY + layerOffsetY,
|
|
749
|
-
layerDefinition =
|
|
753
|
+
layerDefinition = cloneDefinition(platypus.game.settings.entities[entityKind] ?? standardEntityLayers[entityKind]),
|
|
750
754
|
layerDefinitionProperties = layerDefinition.properties = layerDefinition.properties ?? {},
|
|
751
755
|
{components} = layerDefinition,
|
|
752
756
|
importAnimation = {},
|