Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
Perlkonig committed Jan 9, 2025
2 parents dbc16d7 + 1846c06 commit 9a232a7
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 24 deletions.
60 changes: 42 additions & 18 deletions src/renderers/_base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,46 +437,56 @@ export abstract class RendererBase {
* @param name - The unique name of the pattern
* @param canvas - The container into which to add the pattern
*/
protected loadPattern(name: string, canvas?: Svg): void {
protected loadPattern(name: string, opts: {canvas?: Svg, fg?: string, bg?: string} = {}): void {
let canvas: Svg|undefined = this.rootSvg;
if (opts.canvas !== undefined) {
canvas = opts.canvas;
}
if (canvas === undefined) {
if (this.rootSvg === undefined) {
throw new Error("Object in an invalid state!");
}
canvas = this.rootSvg;
throw new Error("Object in an invalid state.");
}

let fg = this.options.colourContext.strokes;
if (opts.fg !== undefined) {
fg = opts.fg;
}
let bg = this.options.colourContext.background;
if (opts.bg !== undefined) {
bg = opts.bg;
}

// Keep in alphabetical order.
// If you change any `id`s, you need to change them in the constructor, too.

switch (name) {
case "chevrons":
canvas.defs().svg("<pattern id='chevrons' patternUnits='userSpaceOnUse' width='30' height='15' viewbox='0 0 60 30'><svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='60' height='30'><defs><rect id='_r' width='30' height='15' fill='#fff' stroke-width='2.5' stroke='#000'/><g id='_p'><use xlink:href='#_r'/><use y='15' xlink:href='#_r'/><use y='30' xlink:href='#_r'/><use y='45' xlink:href='#_r'/></g></defs><use xlink:href='#_p' transform='translate(0 -25) skewY(40)'/><use xlink:href='#_p' transform='translate(30 0) skewY(-40)'/></svg></pattern>");
canvas.defs().svg(`<pattern id="chevrons" patternUnits="userSpaceOnUse" width="30" height="15" viewbox="0 0 60 30"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="60" height="30"><defs><rect id="_r" width="30" height="15" fill="${bg}" stroke-width="2.5" stroke="${fg}"/><g id="_p"><use xlink:href="#_r"/><use y="15" xlink:href="#_r"/><use y="30" xlink:href="#_r"/><use y="45" xlink:href="#_r"/></g></defs><use xlink:href="#_p" transform="translate(0 -25) skewY(40)"/><use xlink:href="#_p" transform="translate(30 0) skewY(-40)"/></svg></pattern>`);
break;
case "cross":
canvas.defs().svg("<pattern id='cross' patternUnits='userSpaceOnUse' width='8' height='8'><svg xmlns='http://www.w3.org/2000/svg' width='8' height='8'><rect width='8' height='8' fill='#fff'/><path d='M0 0L8 8ZM8 0L0 8Z' stroke-width='0.5' stroke='#000'/></svg></pattern>");
canvas.defs().svg(`<pattern id="cross" patternUnits="userSpaceOnUse" width="8" height="8"><svg xmlns="http://www.w3.org/2000/svg" width="8" height="8"><rect width="8" height="8" fill="${bg}"/><path d="M0 0L8 8ZM8 0L0 8Z" stroke-width="0.5" stroke="${fg}"/></svg></pattern>`);
break;
case "dots":
canvas.defs().svg("<pattern id='dots' patternUnits='userSpaceOnUse' width='10' height='10'><svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><rect width='10' height='10' fill='#fff' /><circle cx='2.5' cy='2.5' r='2.5' fill='#000'/></svg></pattern>");
canvas.defs().svg(`<pattern id="dots" patternUnits="userSpaceOnUse" width="10" height="10"><svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"><rect width="10" height="10" fill="${bg}" /><circle cx="2.5" cy="2.5" r="2.5" fill="${fg}"/></svg></pattern>`);
break;
case "honeycomb":
canvas.defs().svg("<pattern id='honeycomb' patternUnits='userSpaceOnUse' width='22.4' height='40' viewbox='0 0 56 100'><svg xmlns='http://www.w3.org/2000/svg' width='56' height='100'><rect width='56' height='100' fill='#fff'/><path d='M28 66L0 50L0 16L28 0L56 16L56 50L28 66L28 100' fill='none' stroke='#000' stroke-width='2'/><path d='M28 0L28 34L0 50L0 84L28 100L56 84L56 50L28 34' fill='none' stroke='#000' stroke-width='2'/></svg></pattern>");
canvas.defs().svg(`<pattern id="honeycomb" patternUnits="userSpaceOnUse" width="22.4" height="40" viewbox="0 0 56 100"><svg xmlns="http://www.w3.org/2000/svg" width="56" height="100"><rect width="56" height="100" fill="${bg}"/><path d="M28 66L0 50L0 16L28 0L56 16L56 50L28 66L28 100" fill="none" stroke="${fg}" stroke-width="2"/><path d="M28 0L28 34L0 50L0 84L28 100L56 84L56 50L28 34" fill="none" stroke="${fg}" stroke-width="2"/></svg></pattern>`);
break;
case "houndstooth":
canvas.defs().svg("<pattern id='houndstooth' patternUnits='userSpaceOnUse' width='24' height='24' viewbox='0 0 24 24'><svg width='24' height='24' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'><title>houndstooth</title><g fill='#000' fill-opacity='1' fill-rule='evenodd'><path d='M0 18h6l6-6v6h6l-6 6H0M24 18v6h-6M24 0l-6 6h-6l6-6M12 0v6L0 18v-6l6-6H0V0'/></g></svg></pattern>");
canvas.defs().svg(`<pattern id="houndstooth" patternUnits="userSpaceOnUse" width="24" height="24" viewbox="0 0 24 24"><svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>houndstooth</title><g fill="${fg}" fill-opacity="1" fill-rule="evenodd"><path d="M0 18h6l6-6v6h6l-6 6H0M24 18v6h-6M24 0l-6 6h-6l6-6M12 0v6L0 18v-6l6-6H0V0"/></g></svg></pattern>`);
break;
case "microbial":
canvas.defs().svg("<pattern id='microbial' patternUnits='userSpaceOnUse' width='20' height=20><svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'><rect width='40' height='40' fill='#fff'/><circle r='9.2' stroke-width='1' stroke='#000' fill='none'/><circle cy='18.4' r='9.2' stroke-width='1px' stroke='#000' fill='none'/><circle cx='18.4' cy='18.4' r='9.2' stroke-width='1' stroke='#000' fill='none'/></svg></pattern>");
canvas.defs().svg(`<pattern id="microbial" patternUnits="userSpaceOnUse" width="20" height=20><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"><rect width="40" height="40" fill="${bg}"/><circle r="9.2" stroke-width="1" stroke="${fg}" fill="none"/><circle cy="18.4" r="9.2" stroke-width="1px" stroke="${fg}" fill="none"/><circle cx="18.4" cy="18.4" r="9.2" stroke-width="1" stroke="${fg}" fill="none"/></svg></pattern>`);
break;
case "slant":
canvas.defs().svg("<pattern id='slant' patternUnits='userSpaceOnUse' width='10' height='10'><svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><rect width='10' height='10' fill='#fff'/><path d='M-1,1 l2,-2 M0,10 l10,-10 M9,11 l2,-2' stroke='#000' stroke-width='1'/></svg></pattern>");
canvas.defs().svg(`<pattern id="slant" patternUnits="userSpaceOnUse" width="10" height="10"><svg xmlns="http://www.w3.org/2000/svg" width="10" height="10"><rect width="10" height="10" fill="${bg}"/><path d="M-1,1 l2,-2 M0,10 l10,-10 M9,11 l2,-2" stroke="${fg}" stroke-width="1"/></svg></pattern>`);
break;
case "starsWhite":
canvas.defs().svg("<pattern id='starsWhite' patternUnits='userSpaceOnUse' width='40' height='40' viewbox='0 0 80 80'><svg xmlns='http://www.w3.org/2000/svg' width='80' height='80'><rect width='80' height='80' fill='#fff'/><circle cx='40' cy='40' r='40' fill='#000'/><path d='M0 40 A40 40 45 0 0 40 0 A40 40 315 0 0 80 40 A40 40 45 0 0 40 80 A40 40 270 0 0 0 40Z' fill='#fff'/></svg></pattern>");
canvas.defs().svg(`<pattern id="starsWhite" patternUnits="userSpaceOnUse" width="40" height="40" viewbox="0 0 80 80"><svg xmlns="http://www.w3.org/2000/svg" width="80" height="80"><rect width="80" height="80" fill="${bg}"/><circle cx="40" cy="40" r="40" fill="${fg}"/><path d="M0 40 A40 40 45 0 0 40 0 A40 40 315 0 0 80 40 A40 40 45 0 0 40 80 A40 40 270 0 0 0 40Z" fill="${bg}"/></svg></pattern>`);
break;
case "triangles":
canvas.defs().svg("<pattern id='triangles' patternUnits='userSpaceOnUse' width='15' height='15'><svg xmlns='http://www.w3.org/2000/svg' width='15' height='15'><rect width='15' height='15' fill='#fff'/><path d='M0 15L7.5 0L15 15Z' fill='#000'/></svg></pattern>");
canvas.defs().svg(`<pattern id="triangles" patternUnits="userSpaceOnUse" width="15" height="15"><svg xmlns="http://www.w3.org/2000/svg" width="15" height="15"><rect width="15" height="15" fill="${bg}"/><path d="M0 15L7.5 0L15 15Z" fill="${fg}"/></svg></pattern>`);
break;
case "wavy":
canvas.defs().svg("<pattern id='wavy' patternUnits='userSpaceOnUse' width='15' height='20' viewbox='0 0 75 100'><svg xmlns='http://www.w3.org/2000/svg' width='75' height='100'><rect width='75' height='100' fill='#fff'/><circle cx='75' cy='50' r='28.3%' stroke-width='12' stroke='#000' fill='none'/><circle cx='0' r='28.3%' stroke-width='12' stroke='#000' fill='none'/><circle cy='100' r='28.3%' stroke-width='12' stroke='#000' fill='none'/></svg></pattern>");
canvas.defs().svg(`<pattern id="wavy" patternUnits="userSpaceOnUse" width="15" height="20" viewbox="0 0 75 100"><svg xmlns="http://www.w3.org/2000/svg" width="75" height="100"><rect width="75" height="100" fill="${bg}"/><circle cx="75" cy="50" r="28.3%" stroke-width="12" stroke="${fg}" fill="none"/><circle cx="0" r="28.3%" stroke-width="12" stroke="${fg}" fill="none"/><circle cy="100" r="28.3%" stroke-width="12" stroke="${fg}" fill="none"/></svg></pattern>`);
break;
default:
throw new Error(`The pattern name you requested (${name}) is not known.`);
Expand Down Expand Up @@ -6699,15 +6709,29 @@ export abstract class RendererBase {
if (typeof marker.colour === "object") {
isGradient = true;
}
colour = this.resolveColour(marker.colour );
colour = this.resolveColour(marker.colour);
}
let opacity = 0.25;
if ( ("opacity" in marker) && (marker.opacity !== undefined) ) {
opacity = marker.opacity;
}
let fill: FillData|SVGGradient;
let pattern: string | undefined;
if ( ("pattern" in marker) && (marker.pattern !== undefined) && (marker.pattern.length > 0) ) {
pattern = marker.pattern;
}
if (pattern !== undefined) {
this.loadPattern(pattern, {bg: "none", fg: typeof colour === "string" ? colour : undefined});
}
let fill: FillData|SVGGradient|SVGElement;
if (isGradient) {
fill = colour as SVGGradient;
} else if (pattern !== undefined) {
if (pattern !== undefined) {
fill = this.rootSvg.findOne(`#${pattern}`) as SVGElement;
if (fill === undefined) {
throw new Error("Could not load the requested pattern.");
}
}
} else {
fill = {color: colour as string, opacity};
}
Expand Down
20 changes: 16 additions & 4 deletions src/schemas/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,20 @@ export type BoardStyles =
| "heightmap-squares"
| "dvgc"
| "dvgc-checkered";
/**
* The patterns known by the renderer
*/
export type PatternName =
| "microbial"
| "chevrons"
| "honeycomb"
| "triangles"
| "wavy"
| "slant"
| "dots"
| "starsWhite"
| "cross"
| "houndstooth";
/**
* The required schema for the `homeworlds` renderer. It supports 4 players and colours. The `board` property describes the systems. The `pieces` property describes the pieces.
*/
Expand Down Expand Up @@ -471,10 +485,7 @@ export interface BoardBasic {
* The width of the zone expressed as a percentage of the cell size. If zero, the zone is omitted.
*/
width: number;
/**
* The name of one of the built-in patterns for fill.
*/
pattern?: string;
pattern?: PatternName;
/**
* Choose which of the four sides you want displayed. By default, it's all four.
*/
Expand Down Expand Up @@ -577,6 +588,7 @@ export interface MarkerFlood {
* The colour of the shaded area. Can be either a number (which will be interpreted as a built-in player colour) or a hexadecimal colour string.
*/
colour?: PositiveInteger | Colourfuncs | Colourstrings | Gradient;
pattern?: PatternName;
/**
* 1 is fully opaque. 0 is fully transparent.
*/
Expand Down
10 changes: 8 additions & 2 deletions src/schemas/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
"type": "string",
"pattern": "^1*2*3*$"
},
"patternName": {
"description": "The patterns known by the renderer",
"enum": ["microbial", "chevrons", "honeycomb", "triangles", "wavy", "slant", "dots", "starsWhite", "cross", "houndstooth"]
},
"colourstrings": {
"description": "Pattern for hex colour strings",
"anyOf": [
Expand Down Expand Up @@ -1200,6 +1204,9 @@
],
"default": "#000"
},
"pattern": {
"$ref": "#/$defs/patternName"
},
"opacity": {
"description": "1 is fully opaque. 0 is fully transparent.",
"type": "number",
Expand Down Expand Up @@ -1973,8 +1980,7 @@
"maximum": 0.9
},
"pattern": {
"description": "The name of one of the built-in patterns for fill.",
"type": "string"
"$ref": "#/$defs/patternName"
},
"show": {
"description": "Choose which of the four sides you want displayed. By default, it's all four.",
Expand Down

0 comments on commit 9a232a7

Please sign in to comment.