2021-03-18 23:32:05 +00:00
|
|
|
|
import { AttachmentPointType, isAttachmentPointType } from "./specs";
|
|
|
|
|
|
2021-02-27 02:30:38 +00:00
|
|
|
|
type SvgSymbolMetadataBooleans = {
|
|
|
|
|
/**
|
|
|
|
|
* If true, this indicates that the symbol should always have
|
|
|
|
|
* a symbol nested within its nesting area(s).
|
|
|
|
|
*/
|
|
|
|
|
always_nest?: boolean;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* If true, this indicates that the symbol should always
|
|
|
|
|
* be nested inside another symbol's nesting area.
|
|
|
|
|
*/
|
|
|
|
|
always_be_nested?: boolean;
|
2021-03-01 00:10:53 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* If true, this indicates that the symbol should never
|
|
|
|
|
* be nested inside another symbol's nesting area.
|
|
|
|
|
*/
|
|
|
|
|
never_be_nested?: boolean;
|
2021-03-06 00:38:25 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* If true, this indicates that any symbols nested on this
|
|
|
|
|
* symbol’s nesting area should have their colors inverted.
|
|
|
|
|
*/
|
|
|
|
|
invert_nested?: boolean;
|
2021-04-23 00:53:18 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* In the mandala, the normal rotation direction for animation is counterclockwise.
|
|
|
|
|
* This changes the rotation direction to clockwise.
|
|
|
|
|
*/
|
|
|
|
|
rotate_clockwise?: boolean;
|
2021-07-05 23:35:39 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* If true, this indicates that we should never horizontally flip the
|
|
|
|
|
* orientation of a symbol when attaching it. Otherwise, we will flip
|
|
|
|
|
* the symbol horizontally if it's facing left, and flip it horizontally
|
|
|
|
|
* again if it's facing down.
|
|
|
|
|
*/
|
|
|
|
|
never_flip_attachments?: boolean;
|
2021-02-27 02:30:38 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const METADATA_BOOLEANS: Set<keyof SvgSymbolMetadataBooleans> = new Set([
|
|
|
|
|
"always_nest",
|
|
|
|
|
"always_be_nested",
|
2021-03-01 00:10:53 +00:00
|
|
|
|
"never_be_nested",
|
2021-03-06 00:38:25 +00:00
|
|
|
|
"invert_nested",
|
2021-04-23 00:53:18 +00:00
|
|
|
|
"rotate_clockwise",
|
2021-07-05 23:35:39 +00:00
|
|
|
|
"never_flip_attachments",
|
2021-02-27 02:30:38 +00:00
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
function isSvgSymbolMetadataBoolean(
|
|
|
|
|
key: string
|
|
|
|
|
): key is keyof SvgSymbolMetadataBooleans {
|
|
|
|
|
return METADATA_BOOLEANS.has(key as any);
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-18 23:32:05 +00:00
|
|
|
|
export type SvgSymbolMetadata = SvgSymbolMetadataBooleans & {
|
|
|
|
|
/**
|
|
|
|
|
* If defined, this indicates the kinds of attachment points
|
|
|
|
|
* that this symbol can attach to. If not defined, it will
|
|
|
|
|
* be able to attach to any symbol.
|
|
|
|
|
*/
|
|
|
|
|
attach_to?: AttachmentPointType[];
|
2021-07-17 18:39:19 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Setting this to a positive integer (whole number) will multiply the
|
|
|
|
|
* likelihood that this symbol will be chosen from a random selection of symbols
|
|
|
|
|
* by the given amount when this symbol is used in a creature. For example,
|
|
|
|
|
* setting it to 2 will make it twice as likely to be chosen, setting it to 5
|
|
|
|
|
* will make it five times more likely, and so on.
|
|
|
|
|
*/
|
|
|
|
|
creature_frequency_multiplier?: number;
|
2021-03-18 23:32:05 +00:00
|
|
|
|
};
|
2021-02-27 02:30:38 +00:00
|
|
|
|
|
2021-07-03 13:34:30 +00:00
|
|
|
|
export function validateSvgSymbolMetadata(obj: any): {
|
2021-06-08 16:40:41 +00:00
|
|
|
|
metadata: SvgSymbolMetadata;
|
|
|
|
|
unknownProperties: string[];
|
|
|
|
|
} {
|
2021-02-28 23:57:51 +00:00
|
|
|
|
const metadata: SvgSymbolMetadata = {};
|
|
|
|
|
const unknownProperties: string[] = [];
|
2021-02-27 02:30:38 +00:00
|
|
|
|
for (let key in obj) {
|
|
|
|
|
const value: unknown = obj[key];
|
|
|
|
|
if (isSvgSymbolMetadataBoolean(key)) {
|
|
|
|
|
if (typeof value !== "boolean") {
|
|
|
|
|
throw new Error(
|
|
|
|
|
`Expected "${key}" to be a boolean, but it is a ${typeof value}!`
|
|
|
|
|
);
|
|
|
|
|
}
|
2021-02-28 23:57:51 +00:00
|
|
|
|
metadata[key] = value;
|
2021-03-18 23:32:05 +00:00
|
|
|
|
} else if (key === "attach_to") {
|
|
|
|
|
metadata.attach_to = validateAttachTo(obj[key]);
|
2021-07-17 18:39:19 +00:00
|
|
|
|
} else if (key === "creature_frequency_multiplier") {
|
|
|
|
|
metadata.creature_frequency_multiplier = validateFrequencyMultiplier(
|
|
|
|
|
obj[key]
|
|
|
|
|
);
|
2021-02-27 02:30:38 +00:00
|
|
|
|
} else {
|
2021-02-28 23:57:51 +00:00
|
|
|
|
unknownProperties.push(key);
|
2021-02-27 02:30:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2021-02-28 23:57:51 +00:00
|
|
|
|
return { metadata, unknownProperties };
|
2021-02-27 02:30:38 +00:00
|
|
|
|
}
|
2021-03-18 23:32:05 +00:00
|
|
|
|
|
2021-07-17 18:39:19 +00:00
|
|
|
|
const MIN_FREQUENCY_MULTIPLIER = 1;
|
|
|
|
|
|
|
|
|
|
export function validateFrequencyMultiplier(
|
|
|
|
|
value: unknown
|
|
|
|
|
): number | undefined {
|
|
|
|
|
if (typeof value === "number") {
|
|
|
|
|
if (value < MIN_FREQUENCY_MULTIPLIER) {
|
|
|
|
|
console.log(
|
|
|
|
|
`Frequency multiplier is less than minimum of ${MIN_FREQUENCY_MULTIPLIER}.`
|
|
|
|
|
);
|
|
|
|
|
return MIN_FREQUENCY_MULTIPLIER;
|
|
|
|
|
}
|
|
|
|
|
return Math.floor(value);
|
|
|
|
|
}
|
|
|
|
|
console.log(`Frequency multiplier "${value}" is not a number.`);
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
|
2021-03-18 23:32:05 +00:00
|
|
|
|
export function validateAttachTo(value: unknown): AttachmentPointType[] {
|
|
|
|
|
if (!Array.isArray(value)) {
|
|
|
|
|
throw new Error(
|
|
|
|
|
`Expected "attach_to" to be an array, but it is a ${typeof value}!`
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const result: AttachmentPointType[] = [];
|
|
|
|
|
|
|
|
|
|
for (let item of value) {
|
|
|
|
|
if (isAttachmentPointType(item)) {
|
|
|
|
|
result.push(item);
|
|
|
|
|
} else {
|
|
|
|
|
console.log(
|
|
|
|
|
`Item '${item}' in "attach_to" is not a valid attachment point.`
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|