Skip to content

Commit

Permalink
Merge pull request #1086 from ZeLonewolf/clay-shields-assign-icon-by-…
Browse files Browse the repository at this point in the history
…length

Assign shield icons based on ref length
  • Loading branch information
claysmalley authored Jun 1, 2024
2 parents 66fdc4c + f5f2955 commit 7b75a99
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 17 deletions.
9 changes: 5 additions & 4 deletions shieldlib/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ You should create one definition entry for each network. The entry key must matc
"top": 3,
"bottom": 3
},
"spriteBlank": "name_of_image_1",
"spriteBlank": ["name_of_image_2", "name_of_image_3", "name_of_image_4"],
"noref": {
"spriteBlank": "name_of_image_2"
"spriteBlank": "name_of_image_noref"
}
"shapeBlank": {
"drawFunc": "pentagon",
Expand Down Expand Up @@ -168,7 +168,8 @@ You should create one definition entry for each network. The entry key must matc
- **`textColor`**: determines what color to draw the `ref` on the shield.
- **`textHaloColor`**: color to draw a knockout halo around the `ref` text.
- **`padding`**: padding around the `ref`, which allows you to squeeze the text into a smaller space within the shield.
- **`spriteBlank`**: specify the name of an image in the sprite sheet to use as the shield background. This can either be a single string or an array of strings if there are multiple options for different width. If it's an array of strings, they must be ordered from narrowest to widest, and the engine will choose the narrowest shield graphic that fits the text at a reasonable size.
- **`spriteBlank`**: specify the name of an image in the sprite sheet to use as the shield background. This can either be a single string or an array of strings if there are multiple options for different width.
- If `spriteBlank` is an array of strings, they must be ordered from narrowest to widest, and the filenames must be suffixed with a consecutive range of integers, representing the optimal number of characters to display in each icon.
- **`noref`**: specify alternate attributes to apply in the event that no `ref` is supplied. This allows you to use one graphic for numbered routes and a separate unitary graphic for non-numbered routes within the same network. Supports **`spriteBlank`**, **`colorLighten`**, and **`colorDarken`**.
- **`shapeBlank`**: specify that a shield should be drawn as a common shape (rectangle, ellipse, pentagon, etc), with colors and dimensions as specified. See the [drawn shield shapes](#defining-drawn-shield-shapes) section for available drawing options.
- **`banners`**: specify that one or more short text strings (up to 4 characters) should be drawn above the shield. This is specified as an array, and text will be drawn in order from top to bottom. Below is an example of bannered shields with up to three banners:
Expand Down Expand Up @@ -234,7 +235,7 @@ This effect can be achieved by overriding the text and sprite color in the route

```json
"US:GA": {
"spriteBlank": ["shield_us_ga_narrow", "shield_us_ga_wide"],
"spriteBlank": ["shield_us_ga_2", "shield_us_ga_3"],
"textColor": "black",
"overrideByRef": {
"520": {
Expand Down
30 changes: 17 additions & 13 deletions shieldlib/src/shield.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
import { TextPlacement } from "./shield_text";
import { StyleImage } from "maplibre-gl";

const narrowCharacters = /[1IJijl .-]/g;

function compoundShieldSize(
r: ShieldRenderingContext,
dimension: Dimension,
Expand Down Expand Up @@ -51,20 +53,22 @@ function getRasterShieldBlank(
let bounds: Dimension;

if (Array.isArray(shieldDef.spriteBlank)) {
for (var i = 0; i < shieldDef.spriteBlank.length; i++) {
shieldArtwork = r.spriteRepo.getSprite(shieldDef.spriteBlank[i]);
// Certain narrow characters count as two-thirds of a character
let narrowCharacterCount = (routeDef.ref.match(narrowCharacters) ?? [])
.length;
let refLength = Math.ceil(routeDef.ref.length - narrowCharacterCount / 3);

// Choose icon based on optimal character length at end of filename
let finalIndex = shieldDef.spriteBlank.length - 1;
let optimalCharacters = shieldDef.spriteBlank.map((blank) =>
parseInt(blank.split("_").reverse()[0])
);
let spriteIndex =
refLength > optimalCharacters[finalIndex]
? finalIndex
: Math.max(0, optimalCharacters.indexOf(refLength));

bounds = compoundShieldSize(r, shieldArtwork.data, bannerCount);
textPlacement = ShieldText.layoutShieldTextFromDef(
r,
routeDef.ref,
shieldDef,
bounds
);
if (textPlacement.fontPx > r.px(Gfx.fontSizeThreshold)) {
break;
}
}
shieldArtwork = r.spriteRepo.getSprite(shieldDef.spriteBlank[spriteIndex]);
} else {
shieldArtwork = r.spriteRepo.getSprite(shieldDef.spriteBlank);
}
Expand Down

0 comments on commit 7b75a99

Please sign in to comment.