@tileflow/core 0.1.0-alpha.40 → 0.1.0-alpha.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/3d.js +280 -110
- package/dist/browser.d.ts +38 -19
- package/dist/browser.js +288 -117
- package/dist/build.d.ts +3 -3
- package/dist/build.js +52 -11
- package/dist/config-reference.json +1062 -669
- package/dist/{icon-composition-CcSHApUm.d.ts → icon-composition-B1A2udKb.d.ts} +66 -20
- package/dist/index.d.ts +26 -19
- package/dist/index.js +189 -62
- package/dist/{manifest-types-DnhSJjCM.d.ts → manifest-types-B0lQjabX.d.ts} +2 -0
- package/dist/manifest.d.ts +2 -2
- package/dist/native.d.ts +87 -1
- package/dist/native.js +193 -0
- package/dist/runtime.d.ts +1 -1
- package/dist/worker/camera-tile-worker.global.js +2 -2
- package/docs/boundary-areas-and-choropleths.md +24 -11
- package/docs/buildings-3d.md +51 -21
- package/docs/cartographic-defaults.md +4 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -897,6 +897,7 @@ var init_visual_semantics = __esm({
|
|
|
897
897
|
"lightness",
|
|
898
898
|
"fadeDuration",
|
|
899
899
|
"gapWidth",
|
|
900
|
+
"groundOcclusion",
|
|
900
901
|
"haloBlur",
|
|
901
902
|
"haloWidth",
|
|
902
903
|
"height",
|
|
@@ -3802,19 +3803,19 @@ function deriveGlyph(glyph, metrics) {
|
|
|
3802
3803
|
const bitmap = new Uint8Array(width * rows);
|
|
3803
3804
|
for (let row = 0; row < rows; row++) {
|
|
3804
3805
|
const y = y0 + row + 0.5;
|
|
3805
|
-
for (let
|
|
3806
|
-
const x = x0 +
|
|
3806
|
+
for (let column2 = 0; column2 < width; column2++) {
|
|
3807
|
+
const x = x0 + column2 + 0.5;
|
|
3807
3808
|
const distance = Math.min(x - cell.x0, cell.x1 - x, y - cell.y0, cell.y1 - y);
|
|
3808
3809
|
const background = Math.min(CELL_VALUE, Math.max(0, CELL_EDGE + CELL_SLOPE * distance));
|
|
3809
3810
|
let letter = 0;
|
|
3810
3811
|
if (hasBitmap) {
|
|
3811
|
-
const sourceColumn = x0 +
|
|
3812
|
+
const sourceColumn = x0 + column2 - sourceX;
|
|
3812
3813
|
const sourceRow = y0 + row - sourceY;
|
|
3813
3814
|
if (sourceColumn >= 0 && sourceColumn < sourceWidth && sourceRow >= 0 && sourceRow < sourceHeight) {
|
|
3814
3815
|
letter = glyph.bitmap[sourceRow * sourceWidth + sourceColumn];
|
|
3815
3816
|
}
|
|
3816
3817
|
}
|
|
3817
|
-
bitmap[row * width +
|
|
3818
|
+
bitmap[row * width + column2] = Math.round(Math.max(letter, background));
|
|
3818
3819
|
}
|
|
3819
3820
|
}
|
|
3820
3821
|
return {
|
|
@@ -9013,6 +9014,7 @@ function resolvePoi(request) {
|
|
|
9013
9014
|
density: request?.density ?? 2,
|
|
9014
9015
|
detailZoom: request?.detailZoom ?? 17,
|
|
9015
9016
|
densityByCategory: { ...request?.densityByCategory },
|
|
9017
|
+
maxRankByType: { ...request?.maxRankByType },
|
|
9016
9018
|
icons: request?.icons ?? true,
|
|
9017
9019
|
labels: request?.labels ?? true,
|
|
9018
9020
|
minZoom: request?.minZoom ?? 0,
|
|
@@ -9500,6 +9502,9 @@ function compileCategory(category, request, semantics, context, language, select
|
|
|
9500
9502
|
}
|
|
9501
9503
|
function createPoiSelection(semantics, context, language) {
|
|
9502
9504
|
const { fields: fields2 } = context.data.schema;
|
|
9505
|
+
const typeRankCaps = Object.entries(semantics.maxRankByType).sort(
|
|
9506
|
+
([a], [b]) => a.localeCompare(b)
|
|
9507
|
+
);
|
|
9503
9508
|
const shown = /* @__PURE__ */ new Map();
|
|
9504
9509
|
const iconOnlyTypes = [...new Set(semantics.placement.iconOnlyTypes)];
|
|
9505
9510
|
const iconOnly = () => iconOnlyTypes.length ? ["match", ["get", fields2.poiType], iconOnlyTypes, true, false] : ["literal", false];
|
|
@@ -9535,6 +9540,14 @@ function createPoiSelection(semantics, context, language) {
|
|
|
9535
9540
|
[">=", sizeRank, 0],
|
|
9536
9541
|
["<=", sizeRank, 16]
|
|
9537
9542
|
];
|
|
9543
|
+
if (typeRankCaps.length) {
|
|
9544
|
+
result.push([
|
|
9545
|
+
"match",
|
|
9546
|
+
["get", fields2.poiType],
|
|
9547
|
+
...typeRankCaps.flatMap(([type, rank]) => [type, ["<=", filterRank, rank]]),
|
|
9548
|
+
true
|
|
9549
|
+
]);
|
|
9550
|
+
}
|
|
9538
9551
|
if (!semantics.icons || !semantics.labels) return result;
|
|
9539
9552
|
const textless = categories.filter((category) => !shown.get(category)?.text);
|
|
9540
9553
|
const iconless = categories.filter((category) => !shown.get(category)?.icon);
|
|
@@ -13573,6 +13586,12 @@ var tileflowModelParts = Object.freeze({
|
|
|
13573
13586
|
accent: 3,
|
|
13574
13587
|
roof: 4
|
|
13575
13588
|
});
|
|
13589
|
+
var tileflowModelArchitecturalPartNames = Object.freeze(
|
|
13590
|
+
Object.keys(tileflowModelParts)
|
|
13591
|
+
);
|
|
13592
|
+
function isTileflowModelPartName(value) {
|
|
13593
|
+
return typeof value === "string" && value.length <= 32 && /^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$/u.test(value);
|
|
13594
|
+
}
|
|
13576
13595
|
var tileflowModelLightingRoles = Object.freeze({
|
|
13577
13596
|
unclassified: 0,
|
|
13578
13597
|
wall: 1,
|
|
@@ -13582,7 +13601,16 @@ var tileflowModelLightingRoles = Object.freeze({
|
|
|
13582
13601
|
lamp: 5,
|
|
13583
13602
|
logo: 6
|
|
13584
13603
|
});
|
|
13585
|
-
var
|
|
13604
|
+
var architecturalRoles = {
|
|
13605
|
+
surface: 1,
|
|
13606
|
+
secondary: 1,
|
|
13607
|
+
glass: 4,
|
|
13608
|
+
accent: 1,
|
|
13609
|
+
roof: 3
|
|
13610
|
+
};
|
|
13611
|
+
function tileflowModelDefaultLightingRole(part) {
|
|
13612
|
+
return Object.hasOwn(architecturalRoles, part) ? architecturalRoles[part] : tileflowModelLightingRoles.unclassified;
|
|
13613
|
+
}
|
|
13586
13614
|
var tileflowModelLimits = Object.freeze({
|
|
13587
13615
|
/** Levels of detail, nearest first. */
|
|
13588
13616
|
levels: 3,
|
|
@@ -13599,7 +13627,9 @@ var tileflowModelLimits = Object.freeze({
|
|
|
13599
13627
|
/** Models in one prepared file, as a landmark tile holds them. */
|
|
13600
13628
|
models: 512,
|
|
13601
13629
|
/** Bytes of one prepared file. */
|
|
13602
|
-
bytes: 16 * 1024 * 1024
|
|
13630
|
+
bytes: 16 * 1024 * 1024,
|
|
13631
|
+
/** Differently named parts of one level. */
|
|
13632
|
+
parts: 16
|
|
13603
13633
|
});
|
|
13604
13634
|
var tileflowModelVertexBytes = 16;
|
|
13605
13635
|
function tileflowInsideRings(rings, px, py) {
|
|
@@ -13719,6 +13749,9 @@ function readModelRoleLighting(value) {
|
|
|
13719
13749
|
...entry.colorMix === void 0 ? {} : { colorMix: bounded(entry.colorMix, 0, 1, 1) },
|
|
13720
13750
|
...entry.metallic === void 0 ? {} : { metallic: bounded(entry.metallic, 0, 1, 0) },
|
|
13721
13751
|
...entry.roughness === void 0 ? {} : { roughness: bounded(entry.roughness, 0, 1, 1) },
|
|
13752
|
+
...entry.shading === "map" || entry.shading === "physical" ? { shading: entry.shading } : {},
|
|
13753
|
+
...entry.ambientOcclusion === void 0 ? {} : { ambientOcclusion: bounded(entry.ambientOcclusion, 0, 1, 1) },
|
|
13754
|
+
...entry.partColorMix === void 0 ? {} : { partColorMix: bounded(entry.partColorMix, 0, 1, 1) },
|
|
13722
13755
|
...readRoleColorVariation(entry.colorVariation),
|
|
13723
13756
|
emissiveHeight: Array.isArray(gradient) && gradient.length === 5 && gradient.every(
|
|
13724
13757
|
(v, i) => typeof v === "number" && Number.isFinite(v) && v <= 1 && v >= (i === 4 ? -1 : 0)
|
|
@@ -13802,6 +13835,7 @@ var tileflowDefaultBuildings3DDesign = Object.freeze({
|
|
|
13802
13835
|
windows: false,
|
|
13803
13836
|
shadows: true,
|
|
13804
13837
|
occlusion: true,
|
|
13838
|
+
groundOcclusion: 0.16,
|
|
13805
13839
|
modelOcclusion: 0.75
|
|
13806
13840
|
});
|
|
13807
13841
|
function tileflowBuildingsMetadata(design) {
|
|
@@ -13828,7 +13862,7 @@ function readTileflowBuildings3D(metadata) {
|
|
|
13828
13862
|
},
|
|
13829
13863
|
color: color3,
|
|
13830
13864
|
edges: within(value.edges, 1, 0),
|
|
13831
|
-
edgeRadius: within(value.edgeRadius, 1, defaults4.edgeRadius),
|
|
13865
|
+
edgeRadius: within(value.edgeRadius, 1.5, defaults4.edgeRadius),
|
|
13832
13866
|
lighting: value.lighting === "style" ? "style" : defaults4.lighting,
|
|
13833
13867
|
colorVariation: within(value.colorVariation, 1, 0),
|
|
13834
13868
|
verticalGradient: value.verticalGradient !== false,
|
|
@@ -13841,6 +13875,7 @@ function readTileflowBuildings3D(metadata) {
|
|
|
13841
13875
|
...readTileflowBuildingsEntrance(value.entrance),
|
|
13842
13876
|
shadows: typeof value.shadows === "boolean" ? value.shadows : defaults4.shadows,
|
|
13843
13877
|
occlusion: typeof value.occlusion === "boolean" ? value.occlusion : defaults4.occlusion,
|
|
13878
|
+
groundOcclusion: within(value.groundOcclusion, 1, defaults4.groundOcclusion),
|
|
13844
13879
|
modelOcclusion: within(value.modelOcclusion, 1, defaults4.modelOcclusion),
|
|
13845
13880
|
...modelsOf(value.models),
|
|
13846
13881
|
...modelColorsOf(value.modelColors),
|
|
@@ -13887,8 +13922,8 @@ function modelsOf(value) {
|
|
|
13887
13922
|
function modelColorsOf(value) {
|
|
13888
13923
|
if (!isRecord7(value)) return {};
|
|
13889
13924
|
const colors = {};
|
|
13890
|
-
for (const part of Object.
|
|
13891
|
-
if (typeof
|
|
13925
|
+
for (const [part, color3] of Object.entries(value))
|
|
13926
|
+
if (isTileflowModelPartName(part) && typeof color3 === "string") colors[part] = color3;
|
|
13892
13927
|
return Object.keys(colors).length > 0 ? { modelColors: colors } : {};
|
|
13893
13928
|
}
|
|
13894
13929
|
function landmarksOf(value) {
|
|
@@ -14317,7 +14352,7 @@ function limitError(message) {
|
|
|
14317
14352
|
return new Error(site ? `${message} Called at ${site}.` : message);
|
|
14318
14353
|
}
|
|
14319
14354
|
function authoringCallSite(stack) {
|
|
14320
|
-
const locations = (stack ?? "").split("\n").slice(1).map((line) => /\(?([^()\s]+?):(\d+):(\d+)\)?$/.exec(line.trim())).filter((match3) => match3 !== null).map(([, file, line,
|
|
14355
|
+
const locations = (stack ?? "").split("\n").slice(1).map((line) => /\(?([^()\s]+?):(\d+):(\d+)\)?$/.exec(line.trim())).filter((match3) => match3 !== null).map(([, file, line, column2]) => ({ file: file.replace(/^file:\/\//, ""), line, column: column2 }));
|
|
14321
14356
|
const own = locations[0]?.file;
|
|
14322
14357
|
const site = locations.find(({ file }) => file !== own && !file.startsWith("node:"));
|
|
14323
14358
|
return site ? `${site.file}:${site.line}:${site.column}` : void 0;
|
|
@@ -17307,6 +17342,9 @@ var modelRoleLightingSchema = z7.object({
|
|
|
17307
17342
|
colorMix: boundedThemeNumberSchema(0, 1).optional(),
|
|
17308
17343
|
metallic: boundedThemeNumberSchema(0, 1).optional(),
|
|
17309
17344
|
roughness: boundedThemeNumberSchema(0, 1).optional(),
|
|
17345
|
+
shading: z7.enum(["physical", "map"]).optional(),
|
|
17346
|
+
ambientOcclusion: boundedThemeNumberSchema(0, 1).optional(),
|
|
17347
|
+
partColorMix: boundedThemeNumberSchema(0, 1).optional(),
|
|
17310
17348
|
colorVariation: z7.object({
|
|
17311
17349
|
hue: z7.tuple([boundedThemeNumberSchema(0, 360), boundedThemeNumberSchema(0, 360)]),
|
|
17312
17350
|
saturation: z7.tuple([boundedThemeNumberSchema(0, 100), boundedThemeNumberSchema(0, 100)]),
|
|
@@ -17333,7 +17371,7 @@ var buildingsModuleSchema = z7.object({
|
|
|
17333
17371
|
lighting: z7.enum(["style", "sun"]).optional(),
|
|
17334
17372
|
colorVariation: boundedThemeNumberSchema(0, 1).optional(),
|
|
17335
17373
|
edges: boundedThemeNumberSchema(0, 1).optional(),
|
|
17336
|
-
edgeRadius: z7.number().min(0).max(1).optional(),
|
|
17374
|
+
edgeRadius: z7.number().min(0).max(1.5).optional(),
|
|
17337
17375
|
edgeColor: themeColorValueSchema.optional(),
|
|
17338
17376
|
nightLight: boundedThemeNumberSchema(0, 2).optional(),
|
|
17339
17377
|
floodLight: z7.object({
|
|
@@ -17356,6 +17394,7 @@ var buildingsModuleSchema = z7.object({
|
|
|
17356
17394
|
}).strict().optional(),
|
|
17357
17395
|
entrance: z7.object({ buildings: entranceBandSchema.optional(), models: entranceBandSchema.optional() }).strict().optional(),
|
|
17358
17396
|
occlusion: z7.boolean().optional(),
|
|
17397
|
+
groundOcclusion: boundedThemeNumberSchema(0, 1).optional(),
|
|
17359
17398
|
modelOcclusion: boundedThemeNumberSchema(0, 1).optional(),
|
|
17360
17399
|
shadows: z7.boolean().optional(),
|
|
17361
17400
|
windows: z7.boolean().optional(),
|
|
@@ -17392,13 +17431,14 @@ var buildingsModuleSchema = z7.object({
|
|
|
17392
17431
|
}).optional()
|
|
17393
17432
|
}).strict()
|
|
17394
17433
|
).max(256).optional(),
|
|
17395
|
-
modelColors: z7.
|
|
17396
|
-
|
|
17397
|
-
|
|
17398
|
-
|
|
17399
|
-
|
|
17400
|
-
|
|
17401
|
-
|
|
17434
|
+
modelColors: z7.record(
|
|
17435
|
+
z7.string().refine(isTileflowModelPartName, {
|
|
17436
|
+
message: "A model part is named in lower-case words joined by hyphens or underscores, at most 32 characters."
|
|
17437
|
+
}),
|
|
17438
|
+
themeColorValueSchema
|
|
17439
|
+
).refine((colors) => Object.keys(colors).length <= 64, {
|
|
17440
|
+
message: "A map colours at most 64 model parts."
|
|
17441
|
+
}).optional(),
|
|
17402
17442
|
landmarks: z7.union([
|
|
17403
17443
|
z7.boolean(),
|
|
17404
17444
|
z7.object({
|
|
@@ -17603,6 +17643,17 @@ var poiModuleSchema = z7.object({
|
|
|
17603
17643
|
type: z7.literal("poi"),
|
|
17604
17644
|
detailZoom: z7.number().finite().gt(16).max(24).optional(),
|
|
17605
17645
|
categories: z7.array(z7.enum(tileflowPoiCategories)).optional(),
|
|
17646
|
+
maxRankByType: z7.record(
|
|
17647
|
+
z7.string().regex(/^[a-z0-9]+(?:_[a-z0-9]+)*$/u, "Expected a World POI type"),
|
|
17648
|
+
z7.union([
|
|
17649
|
+
z7.literal(0),
|
|
17650
|
+
z7.literal(1),
|
|
17651
|
+
z7.literal(2),
|
|
17652
|
+
z7.literal(3),
|
|
17653
|
+
z7.literal(4),
|
|
17654
|
+
z7.literal(5)
|
|
17655
|
+
])
|
|
17656
|
+
).describe("Fixed maximum World filter rank per POI type, independent of zoom detail.").optional(),
|
|
17606
17657
|
color: z7.enum(["uniform", "category"]).optional(),
|
|
17607
17658
|
density: z7.union([z7.literal(1), z7.literal(2), z7.literal(3), z7.literal(4), z7.literal(5)]).describe(
|
|
17608
17659
|
"POI density from 1 to 5. Defaults to 2; native collisions determine which eligible names fit."
|
|
@@ -20599,6 +20650,7 @@ function tileflowBuildings3DDesignOf(module, context, layers2, buildingModels, t
|
|
|
20599
20650
|
...readTileflowBuildingsEntrance(style.entrance),
|
|
20600
20651
|
shadows: typeof style.shadows === "boolean" ? style.shadows : defaults4.shadows,
|
|
20601
20652
|
occlusion: typeof style.occlusion === "boolean" ? style.occlusion : defaults4.occlusion,
|
|
20653
|
+
groundOcclusion: number(style.groundOcclusion, defaults4.groundOcclusion),
|
|
20602
20654
|
modelOcclusion: number(style.modelOcclusion, defaults4.modelOcclusion),
|
|
20603
20655
|
...placedModels(style.models, buildingModels),
|
|
20604
20656
|
...modelColours(style.modelColors),
|
|
@@ -20622,7 +20674,7 @@ function placedModels(value, served) {
|
|
|
20622
20674
|
throw new Error(
|
|
20623
20675
|
`The buildings module places missing 3D models: ${missing.join(", ")}. Add ${missing.map((id2) => `${id2}.glb`).join(
|
|
20624
20676
|
", "
|
|
20625
|
-
)} to a map.models directory, with
|
|
20677
|
+
)} to a map.models directory, with each material named after its part, such as surface, glass, roof or water, and run the Node build so the directories are prepared.`
|
|
20626
20678
|
);
|
|
20627
20679
|
return {
|
|
20628
20680
|
models: placements.map((entry) => ({
|
|
@@ -22949,17 +23001,17 @@ function parseBoundaryLookupCsv(text) {
|
|
|
22949
23001
|
);
|
|
22950
23002
|
}
|
|
22951
23003
|
const row = {};
|
|
22952
|
-
header.forEach((
|
|
23004
|
+
header.forEach((column2, position) => {
|
|
22953
23005
|
const cell = record4[position];
|
|
22954
|
-
if (cell === "" || !lookupColumns.has(
|
|
22955
|
-
if (numericLookupColumns.has(
|
|
23006
|
+
if (cell === "" || !lookupColumns.has(column2)) return;
|
|
23007
|
+
if (numericLookupColumns.has(column2)) {
|
|
22956
23008
|
const number = Number(cell);
|
|
22957
23009
|
if (!Number.isSafeInteger(number)) {
|
|
22958
|
-
throw new Error(`Boundaries lookup CSV row ${index + 2} has a non-integer ${
|
|
23010
|
+
throw new Error(`Boundaries lookup CSV row ${index + 2} has a non-integer ${column2}.`);
|
|
22959
23011
|
}
|
|
22960
|
-
row[
|
|
23012
|
+
row[column2] = number;
|
|
22961
23013
|
} else {
|
|
22962
|
-
row[
|
|
23014
|
+
row[column2] = cell;
|
|
22963
23015
|
}
|
|
22964
23016
|
});
|
|
22965
23017
|
if (row.class_tier !== void 0 && !isClassTier(row.class_tier)) {
|
|
@@ -25196,6 +25248,7 @@ function checkTileflowModelSurface(surface, vertices, indices) {
|
|
|
25196
25248
|
const value = attributes[i];
|
|
25197
25249
|
if (!Number.isFinite(value) || Math.abs(value) > 65536) fail("unbounded vertex attributes");
|
|
25198
25250
|
if (i % 8 >= 4 && (value < 0 || value > 1)) fail("vertex RGBA must be zero to one");
|
|
25251
|
+
if ((i % 8 === 2 || i % 8 === 3) && (value < 0 || value > 1)) fail("UV1 must be zero to one");
|
|
25199
25252
|
}
|
|
25200
25253
|
if (!Array.isArray(materials) || materials.length < 1 || materials.length > tileflowModelSurfaceLimits.materials)
|
|
25201
25254
|
fail("material count exceeds the limit");
|
|
@@ -25277,7 +25330,7 @@ function checkTileflowModelSurface(surface, vertices, indices) {
|
|
|
25277
25330
|
fail("emitter count exceeds the limit");
|
|
25278
25331
|
for (const emitter of emitters) {
|
|
25279
25332
|
if (!emitter || typeof emitter !== "object") fail("invalid area emitter");
|
|
25280
|
-
if (!tuple(emitter.start, 3, -2e3, 2e3) || !tuple(emitter.end, 3, -2e3, 2e3) || !number(emitter.height, 0.01, 1e3) || emitter.depth !== void 0 && !number(emitter.depth, 0, 100) || !Object.hasOwn(tileflowModelLightingRoles, emitter.role) || !
|
|
25333
|
+
if (!tuple(emitter.start, 3, -2e3, 2e3) || !tuple(emitter.end, 3, -2e3, 2e3) || !number(emitter.height, 0.01, 1e3) || emitter.depth !== void 0 && !number(emitter.depth, 0, 100) || !Object.hasOwn(tileflowModelLightingRoles, emitter.role) || !isTileflowModelPartName(emitter.part))
|
|
25281
25334
|
fail("invalid area emitter");
|
|
25282
25335
|
if (Math.hypot(emitter.end[0] - emitter.start[0], emitter.end[1] - emitter.start[1]) < 1e-3 || Math.abs(emitter.end[2] - emitter.start[2]) > 0.01)
|
|
25283
25336
|
fail("an area emitter needs a horizontal lower edge");
|
|
@@ -25320,7 +25373,6 @@ var levelNames = ["near", "mid", "far"];
|
|
|
25320
25373
|
var meshopt = "EXT_meshopt_compression";
|
|
25321
25374
|
var quantisation = "KHR_mesh_quantization";
|
|
25322
25375
|
var steps = 32767;
|
|
25323
|
-
var partCount2 = Object.keys(tileflowModelParts).length;
|
|
25324
25376
|
var roleCount = Object.keys(tileflowModelLightingRoles).length;
|
|
25325
25377
|
var modelId2 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
|
|
25326
25378
|
var [glbMagic, jsonChunk, binChunk] = [1179937895, 1313821514, 5130562];
|
|
@@ -25378,7 +25430,13 @@ function encodeTileflowModels(models, compressor) {
|
|
|
25378
25430
|
return bufferViews.length - 1;
|
|
25379
25431
|
}
|
|
25380
25432
|
const mode = vertices ? "ATTRIBUTES" : "TRIANGLES";
|
|
25381
|
-
const packed = compressor.encodeGltfBuffer(
|
|
25433
|
+
const packed = compressor.encodeGltfBuffer(
|
|
25434
|
+
bytes,
|
|
25435
|
+
count,
|
|
25436
|
+
stride,
|
|
25437
|
+
mode,
|
|
25438
|
+
vertices ? 1 : void 0
|
|
25439
|
+
);
|
|
25382
25440
|
const byteOffset = addBlob(packed);
|
|
25383
25441
|
const fallbackOffset = fallbackLength;
|
|
25384
25442
|
fallbackLength += bytes.byteLength + (4 - bytes.byteLength % 4) % 4;
|
|
@@ -25459,20 +25517,33 @@ function encodeTileflowModels(models, compressor) {
|
|
|
25459
25517
|
let surface;
|
|
25460
25518
|
if (mesh.surface && level.attributes) {
|
|
25461
25519
|
const attributes = level.attributes;
|
|
25462
|
-
const data = new Uint8Array(
|
|
25463
|
-
attributes.buffer,
|
|
25464
|
-
attributes.byteOffset,
|
|
25465
|
-
attributes.byteLength
|
|
25466
|
-
);
|
|
25467
|
-
const view = addView(data, level.count, 32, true);
|
|
25468
25520
|
const uv = accessors.length;
|
|
25521
|
+
const rest = new Float32Array(level.count * 6);
|
|
25522
|
+
const second = new Uint16Array(level.count * 2);
|
|
25523
|
+
for (let vertex = 0; vertex < level.count; vertex++) {
|
|
25524
|
+
const at = vertex * 8;
|
|
25525
|
+
rest.set([attributes[at], attributes[at + 1]], vertex * 6);
|
|
25526
|
+
rest.set(attributes.subarray(at + 4, at + 8), vertex * 6 + 2);
|
|
25527
|
+
second[vertex * 2] = Math.round(attributes[at + 2] * 65535);
|
|
25528
|
+
second[vertex * 2 + 1] = Math.round(attributes[at + 3] * 65535);
|
|
25529
|
+
}
|
|
25530
|
+
const view = addView(new Uint8Array(rest.buffer), level.count, 24, true);
|
|
25531
|
+
const lightmap = addView(new Uint8Array(second.buffer), level.count, 4, true);
|
|
25469
25532
|
accessors.push(
|
|
25470
|
-
{ bufferView: view, byteOffset: 0, componentType: 5126, count: level.count, type: "
|
|
25471
|
-
{
|
|
25533
|
+
{ bufferView: view, byteOffset: 0, componentType: 5126, count: level.count, type: "VEC2" },
|
|
25534
|
+
{
|
|
25535
|
+
bufferView: lightmap,
|
|
25536
|
+
byteOffset: 0,
|
|
25537
|
+
componentType: 5123,
|
|
25538
|
+
normalized: true,
|
|
25539
|
+
count: level.count,
|
|
25540
|
+
type: "VEC2"
|
|
25541
|
+
},
|
|
25542
|
+
{ bufferView: view, byteOffset: 8, componentType: 5126, count: level.count, type: "VEC4" }
|
|
25472
25543
|
);
|
|
25473
25544
|
surface = {
|
|
25474
|
-
version:
|
|
25475
|
-
attributes: [uv, uv + 1],
|
|
25545
|
+
version: 2,
|
|
25546
|
+
attributes: [uv, uv + 1, uv + 2],
|
|
25476
25547
|
materials: mesh.surface.materials,
|
|
25477
25548
|
textures: mesh.surface.textures.map(({ bytes, ...texture }) => ({
|
|
25478
25549
|
...texture,
|
|
@@ -25489,7 +25560,7 @@ function encodeTileflowModels(models, compressor) {
|
|
|
25489
25560
|
mesh: meshes.length - 1,
|
|
25490
25561
|
translation: [...level.centre],
|
|
25491
25562
|
scale: [level.step, level.step, level.step],
|
|
25492
|
-
|
|
25563
|
+
extras: { tileflow: { parts: [...partNamesOf(mesh)], ...surface ? { surface } : {} } }
|
|
25493
25564
|
});
|
|
25494
25565
|
}
|
|
25495
25566
|
roots.push(nodes.length);
|
|
@@ -25559,7 +25630,7 @@ async function decodeTileflowModels(buffer, decompressor) {
|
|
|
25559
25630
|
if (source !== 0 || byteStride !== stride || count * byteStride !== length)
|
|
25560
25631
|
throw new Error();
|
|
25561
25632
|
if (filter !== void 0 && filter !== "NONE") throw new Error();
|
|
25562
|
-
if (mode !== (
|
|
25633
|
+
if (mode !== (view.target === 34963 ? "TRIANGLES" : "ATTRIBUTES")) throw new Error();
|
|
25563
25634
|
out = new Uint8Array(length);
|
|
25564
25635
|
decoder.decodeGltfBuffer(out, count, byteStride, slice(bin, byteOffset, byteLength), mode);
|
|
25565
25636
|
} else {
|
|
@@ -25598,6 +25669,7 @@ async function decodeTileflowModels(buffer, decompressor) {
|
|
|
25598
25669
|
}
|
|
25599
25670
|
levels.push({
|
|
25600
25671
|
vertices: level.vertices,
|
|
25672
|
+
partNames: level.partNames,
|
|
25601
25673
|
indices: level.indices,
|
|
25602
25674
|
centre: level.centre,
|
|
25603
25675
|
step: level.step,
|
|
@@ -25752,6 +25824,7 @@ function quantise(mesh, compressor) {
|
|
|
25752
25824
|
...low.map((value, axis) => Math.max(centre[axis] - value, high[axis] - centre[axis]))
|
|
25753
25825
|
);
|
|
25754
25826
|
const step2 = Math.max(reach, 1e-3) / steps;
|
|
25827
|
+
const names = partNamesOf(mesh);
|
|
25755
25828
|
const raw = new Uint8Array(count * tileflowModelVertexBytes);
|
|
25756
25829
|
const view = new DataView(raw.buffer);
|
|
25757
25830
|
for (let vertex = 0; vertex < count; vertex += 1) {
|
|
@@ -25773,12 +25846,12 @@ function quantise(mesh, compressor) {
|
|
|
25773
25846
|
for (let axis = 0; axis < 3; axis += 1)
|
|
25774
25847
|
view.setInt8(at + 8 + axis, clamp3(Math.round(normal[axis] * 127), -127, 127));
|
|
25775
25848
|
const part = mesh.parts[vertex];
|
|
25776
|
-
if (!Number.isInteger(part) || part < 0 || part >=
|
|
25849
|
+
if (!Number.isInteger(part) || part < 0 || part >= names.length)
|
|
25777
25850
|
throw new RangeError(`Vertex ${vertex} has no part.`);
|
|
25778
25851
|
raw[at + 12] = part;
|
|
25779
25852
|
raw[at + 13] = Math.round((clamp3(mesh.shades[vertex], -1, 1) + 1) / 2 * 255);
|
|
25780
25853
|
raw[at + 14] = Math.round(clamp3(mesh.occlusion[vertex], 0, 1) * 255);
|
|
25781
|
-
const role = mesh.lightingRoles?.[vertex] ??
|
|
25854
|
+
const role = mesh.lightingRoles?.[vertex] ?? tileflowModelDefaultLightingRole(names[part]);
|
|
25782
25855
|
if (!Number.isInteger(role) || role < 0 || role >= roleCount)
|
|
25783
25856
|
throw new RangeError(`Vertex ${vertex} has no lighting role.`);
|
|
25784
25857
|
raw[at + 15] = role;
|
|
@@ -25811,6 +25884,24 @@ function quantise(mesh, compressor) {
|
|
|
25811
25884
|
order = new Array(unique);
|
|
25812
25885
|
for (const [index, vertex] of kept.entries())
|
|
25813
25886
|
if (remap[index] !== 4294967295) order[remap[index]] = vertex;
|
|
25887
|
+
} else if (compressor) {
|
|
25888
|
+
for (const { from, count: length } of mesh.surface.ranges) {
|
|
25889
|
+
const range2 = indices.slice(from, from + length);
|
|
25890
|
+
const [remap, unique] = compressor.reorderMesh(range2, true, false);
|
|
25891
|
+
const global = new Uint32Array(unique);
|
|
25892
|
+
for (const [vertex, local] of remap.entries())
|
|
25893
|
+
if (local !== 4294967295) global[local] = vertex;
|
|
25894
|
+
for (const [at, local] of range2.entries()) indices[from + at] = global[local];
|
|
25895
|
+
}
|
|
25896
|
+
const renumber = new Uint32Array(kept.length).fill(4294967295);
|
|
25897
|
+
order = [];
|
|
25898
|
+
for (const [at, vertex] of indices.entries()) {
|
|
25899
|
+
if (renumber[vertex] === 4294967295) {
|
|
25900
|
+
renumber[vertex] = order.length;
|
|
25901
|
+
order.push(kept[vertex]);
|
|
25902
|
+
}
|
|
25903
|
+
indices[at] = renumber[vertex];
|
|
25904
|
+
}
|
|
25814
25905
|
}
|
|
25815
25906
|
const vertices = new Uint8Array(order.length * tileflowModelVertexBytes);
|
|
25816
25907
|
const attributes = mesh.surface ? new Float32Array(order.length * 8) : void 0;
|
|
@@ -25861,6 +25952,10 @@ function checkModel(model) {
|
|
|
25861
25952
|
throw new RangeError(`Every vertex of level ${at} needs a part, a shade and a light.`);
|
|
25862
25953
|
if (level.lightingRoles && level.lightingRoles.length !== count)
|
|
25863
25954
|
throw new RangeError(`Every vertex of level ${at} needs a lighting role.`);
|
|
25955
|
+
if (!isPartNames(partNamesOf(level)))
|
|
25956
|
+
throw new RangeError(
|
|
25957
|
+
`Level ${at} names 1 to ${tileflowModelLimits.parts} different parts, each in lower-case words joined by hyphens or underscores.`
|
|
25958
|
+
);
|
|
25864
25959
|
if (level.surface) checkTileflowModelSurface(level.surface, count, level.indices.length);
|
|
25865
25960
|
for (let index = 0; index < count; index += 1)
|
|
25866
25961
|
for (let axis = 0; axis < 3; axis += 1) {
|
|
@@ -25949,6 +26044,9 @@ function readLevelNode(json, node2, name, viewBytes, hasLightingRoles) {
|
|
|
25949
26044
|
const indexCount = index?.count;
|
|
25950
26045
|
if (!width || index.type !== "SCALAR" || (index.byteOffset ?? 0) !== 0 || !Number.isInteger(indexCount) || indexCount < 3 || indexCount % 3 !== 0 || indexCount / 3 > tileflowModelLimits.triangles)
|
|
25951
26046
|
throw new Error();
|
|
26047
|
+
const own = node2.extras?.tileflow?.parts;
|
|
26048
|
+
const partNames = own === void 0 ? tileflowModelArchitecturalPartNames : own;
|
|
26049
|
+
if (!isPartNames(partNames)) throw new Error();
|
|
25952
26050
|
const vertices = viewBytes(
|
|
25953
26051
|
position.bufferView,
|
|
25954
26052
|
tileflowModelVertexBytes,
|
|
@@ -25957,8 +26055,8 @@ function readLevelNode(json, node2, name, viewBytes, hasLightingRoles) {
|
|
|
25957
26055
|
for (let vertex = 0; vertex < count; vertex += 1) {
|
|
25958
26056
|
const at = vertex * tileflowModelVertexBytes;
|
|
25959
26057
|
const part = vertices[at + 12];
|
|
25960
|
-
if (part >=
|
|
25961
|
-
if (!hasLightingRoles) vertices[at + 15] =
|
|
26058
|
+
if (part >= partNames.length) throw new Error();
|
|
26059
|
+
if (!hasLightingRoles) vertices[at + 15] = tileflowModelDefaultLightingRole(partNames[part]);
|
|
25962
26060
|
else if (vertices[at + 15] >= roleCount) throw new Error();
|
|
25963
26061
|
}
|
|
25964
26062
|
const indexBytes = viewBytes(index.bufferView, width, indexCount * width);
|
|
@@ -25967,18 +26065,30 @@ function readLevelNode(json, node2, name, viewBytes, hasLightingRoles) {
|
|
|
25967
26065
|
const physical = node2.extras?.tileflow?.surface;
|
|
25968
26066
|
let surface;
|
|
25969
26067
|
if (physical !== void 0) {
|
|
25970
|
-
if (physical?.version !==
|
|
26068
|
+
if (physical?.version !== 2 || !Array.isArray(physical.attributes) || physical.attributes.length !== 3)
|
|
25971
26069
|
throw new Error();
|
|
25972
|
-
const uv =
|
|
25973
|
-
|
|
25974
|
-
if (!uv || !colour || (uv.byteOffset ?? 0) !== 0 || colour.byteOffset !== 16 || uv.bufferView !== colour.bufferView || [uv, colour].some(
|
|
25975
|
-
(value) => value.componentType !== 5126 || value.type !== "VEC4" || value.count !== count || value.normalized === true
|
|
25976
|
-
))
|
|
26070
|
+
const [uv, lightmap, colour] = physical.attributes.map(accessor);
|
|
26071
|
+
if (!uv || !lightmap || !colour || (uv.byteOffset ?? 0) !== 0 || colour.byteOffset !== 8 || (lightmap.byteOffset ?? 0) !== 0 || uv.bufferView !== colour.bufferView || uv.bufferView === lightmap.bufferView || uv.componentType !== 5126 || uv.type !== "VEC2" || colour.componentType !== 5126 || colour.type !== "VEC4" || lightmap.componentType !== 5123 || lightmap.type !== "VEC2" || lightmap.normalized !== true || [uv, lightmap, colour].some((value) => value.count !== count))
|
|
25977
26072
|
throw new Error();
|
|
25978
|
-
const
|
|
26073
|
+
const restBytes = viewBytes(uv.bufferView, 24, count * 24);
|
|
26074
|
+
const lightmapBytes = viewBytes(lightmap.bufferView, 4, count * 4);
|
|
26075
|
+
const rest = new Float32Array(
|
|
26076
|
+
restBytes.buffer.slice(restBytes.byteOffset, restBytes.byteOffset + count * 24)
|
|
26077
|
+
);
|
|
26078
|
+
const second = new Uint16Array(
|
|
26079
|
+
lightmapBytes.buffer.slice(lightmapBytes.byteOffset, lightmapBytes.byteOffset + count * 4)
|
|
26080
|
+
);
|
|
26081
|
+
const attributes = new Float32Array(count * 8);
|
|
26082
|
+
for (let vertex = 0; vertex < count; vertex++) {
|
|
26083
|
+
const at = vertex * 8;
|
|
26084
|
+
attributes[at] = rest[vertex * 6];
|
|
26085
|
+
attributes[at + 1] = rest[vertex * 6 + 1];
|
|
26086
|
+
attributes[at + 2] = second[vertex * 2] / 65535;
|
|
26087
|
+
attributes[at + 3] = second[vertex * 2 + 1] / 65535;
|
|
26088
|
+
attributes.set(rest.subarray(vertex * 6 + 2, vertex * 6 + 6), at + 4);
|
|
26089
|
+
}
|
|
25979
26090
|
if (!Array.isArray(physical.textures) || physical.textures.length > 32) throw new Error();
|
|
25980
|
-
|
|
25981
|
-
attributes: new Float32Array(attributeBytes.buffer, attributeBytes.byteOffset, count * 8),
|
|
26091
|
+
const read = {
|
|
25982
26092
|
materials: physical.materials,
|
|
25983
26093
|
ranges: physical.ranges,
|
|
25984
26094
|
textures: physical.textures.map((texture) => {
|
|
@@ -25989,10 +26099,12 @@ function readLevelNode(json, node2, name, viewBytes, hasLightingRoles) {
|
|
|
25989
26099
|
}),
|
|
25990
26100
|
...physical.emitters === void 0 ? {} : { emitters: physical.emitters }
|
|
25991
26101
|
};
|
|
25992
|
-
checkTileflowModelSurface(
|
|
26102
|
+
checkTileflowModelSurface({ ...read, attributes }, count, indexCount);
|
|
26103
|
+
surface = { ...read, uv: column(attributes, 0), rgba: column(attributes, 4) };
|
|
25993
26104
|
}
|
|
25994
26105
|
return {
|
|
25995
26106
|
vertices,
|
|
26107
|
+
partNames: [...partNames],
|
|
25996
26108
|
indices,
|
|
25997
26109
|
centre: [centre[0], centre[1], centre[2]],
|
|
25998
26110
|
step: scale[0],
|
|
@@ -26001,6 +26113,24 @@ function readLevelNode(json, node2, name, viewBytes, hasLightingRoles) {
|
|
|
26001
26113
|
surface
|
|
26002
26114
|
};
|
|
26003
26115
|
}
|
|
26116
|
+
function column(attributes, first) {
|
|
26117
|
+
const out = attributes.slice(first, first + 4);
|
|
26118
|
+
for (let at = 8 + first; at < attributes.length; at += 8)
|
|
26119
|
+
for (let component = 0; component < 4; component += 1)
|
|
26120
|
+
if (attributes[at + component] !== out[component]) {
|
|
26121
|
+
const all2 = new Float32Array(attributes.length / 2);
|
|
26122
|
+
for (let vertex = 0; vertex < all2.length / 4; vertex += 1)
|
|
26123
|
+
all2.set(attributes.subarray(vertex * 8 + first, vertex * 8 + first + 4), vertex * 4);
|
|
26124
|
+
return all2;
|
|
26125
|
+
}
|
|
26126
|
+
return out;
|
|
26127
|
+
}
|
|
26128
|
+
function partNamesOf(mesh) {
|
|
26129
|
+
return mesh.partNames ?? tileflowModelArchitecturalPartNames;
|
|
26130
|
+
}
|
|
26131
|
+
function isPartNames(names) {
|
|
26132
|
+
return Array.isArray(names) && names.length >= 1 && names.length <= tileflowModelLimits.parts && names.every(isTileflowModelPartName) && new Set(names).size === names.length;
|
|
26133
|
+
}
|
|
26004
26134
|
function readGlb(bytes) {
|
|
26005
26135
|
if (bytes.byteLength < 20 || bytes.byteLength > tileflowModelLimits.bytes) throw new Error();
|
|
26006
26136
|
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
@@ -26150,8 +26280,7 @@ function validFootprint(footprint) {
|
|
|
26150
26280
|
}
|
|
26151
26281
|
function readTileflowLandmarkRegion(json) {
|
|
26152
26282
|
if (!isRecord18(json)) return void 0;
|
|
26153
|
-
|
|
26154
|
-
if (!named && json.format !== "tileflow-landmark-region-v1") return void 0;
|
|
26283
|
+
if (json.format !== "tileflow-landmark-region-v2") return void 0;
|
|
26155
26284
|
const region = json.region;
|
|
26156
26285
|
if (json.zoom !== tileflowLandmarkTileZoom || !Array.isArray(region) || region.length !== 3 || region[0] !== tileflowLandmarkRegionZoom || !Array.isArray(json.tiles))
|
|
26157
26286
|
return void 0;
|
|
@@ -26159,17 +26288,13 @@ function readTileflowLandmarkRegion(json) {
|
|
|
26159
26288
|
if (!Number.isInteger(x) || !Number.isInteger(y)) return void 0;
|
|
26160
26289
|
const tiles = [];
|
|
26161
26290
|
for (const tile of json.tiles) {
|
|
26162
|
-
if (!Array.isArray(tile) || tile.length !==
|
|
26291
|
+
if (!Array.isArray(tile) || tile.length !== 4) return void 0;
|
|
26163
26292
|
const [tx, ty, hash, listed] = tile;
|
|
26164
26293
|
if (!Number.isInteger(tx) || !Number.isInteger(ty) || typeof hash !== "string")
|
|
26165
26294
|
return void 0;
|
|
26166
26295
|
if (!sha256.test(hash)) return void 0;
|
|
26167
26296
|
const [rx, ry] = tileflowLandmarkRegionOf([tx, ty]);
|
|
26168
26297
|
if (rx !== x || ry !== y) return void 0;
|
|
26169
|
-
if (!named) {
|
|
26170
|
-
tiles.push([tx, ty, hash]);
|
|
26171
|
-
continue;
|
|
26172
|
-
}
|
|
26173
26298
|
const landmarks = readLandmarks(listed, tx, ty);
|
|
26174
26299
|
if (!landmarks) return void 0;
|
|
26175
26300
|
tiles.push([tx, ty, hash, landmarks]);
|
|
@@ -26298,6 +26423,7 @@ export {
|
|
|
26298
26423
|
isTileflowCompilationPhase,
|
|
26299
26424
|
isTileflowIconSetSource,
|
|
26300
26425
|
isTileflowLocalDirectory,
|
|
26426
|
+
isTileflowModelPartName,
|
|
26301
26427
|
isTileflowPortableId,
|
|
26302
26428
|
isTileflowThemeName,
|
|
26303
26429
|
isTileflowTimeOfDay,
|
|
@@ -26473,8 +26599,9 @@ export {
|
|
|
26473
26599
|
tileflowMapDefaultMaxDepth,
|
|
26474
26600
|
tileflowMapIdSchema,
|
|
26475
26601
|
tileflowMaxPitch,
|
|
26602
|
+
tileflowModelArchitecturalPartNames,
|
|
26476
26603
|
tileflowModelContentType,
|
|
26477
|
-
|
|
26604
|
+
tileflowModelDefaultLightingRole,
|
|
26478
26605
|
tileflowModelFileName,
|
|
26479
26606
|
tileflowModelImageSize,
|
|
26480
26607
|
tileflowModelLightingRoles,
|
|
@@ -586,6 +586,8 @@ type TileflowPoiModuleConfig = {
|
|
|
586
586
|
density?: TileflowPoiDensity;
|
|
587
587
|
/** Category overrides of density, with the same zoom-dependent detail allowance. */
|
|
588
588
|
densityByCategory?: Partial<Record<TileflowPoiCategory, TileflowPoiDensity>>;
|
|
589
|
+
/** Fixed maximum World filter rank per POI type (0–5), independent of zoom detail. */
|
|
590
|
+
maxRankByType?: Readonly<Record<string, 0 | 1 | 2 | 3 | 4 | 5>>;
|
|
589
591
|
/** Zoom for the second extra rank of POI detail. Must exceed 16; defaults to 17. */
|
|
590
592
|
detailZoom?: number;
|
|
591
593
|
icons?: boolean;
|
package/dist/manifest.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { T as TileflowRuntimeManifest } from './manifest-types-
|
|
2
|
-
export { a as TileflowRuntimeColorScheme, b as TileflowRuntimeManifestMapEntry, c as TileflowRuntimeManifestTheme, d as TileflowRuntimeSystemThemes, e as TileflowTimeOfDay, f as TileflowTimeOfDayVariants, t as tileflowRuntimeManifestLimits, g as tileflowRuntimeManifestVersion, h as tileflowTimeOfDayManifestVersion } from './manifest-types-
|
|
1
|
+
import { T as TileflowRuntimeManifest } from './manifest-types-B0lQjabX.js';
|
|
2
|
+
export { a as TileflowRuntimeColorScheme, b as TileflowRuntimeManifestMapEntry, c as TileflowRuntimeManifestTheme, d as TileflowRuntimeSystemThemes, e as TileflowTimeOfDay, f as TileflowTimeOfDayVariants, t as tileflowRuntimeManifestLimits, g as tileflowRuntimeManifestVersion, h as tileflowTimeOfDayManifestVersion } from './manifest-types-B0lQjabX.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
5
5
|
declare const tileflowRuntimeManifestSchema: z.ZodType<TileflowRuntimeManifest>;
|