Initial commit

Co-Authored-By: Eric Tuvesson <eric.tuvesson@gmail.com>
Co-Authored-By: mikaeltellhed <2311083+mikaeltellhed@users.noreply.github.com>
Co-Authored-By: kotte <14197736+mrtamagotchi@users.noreply.github.com>
Co-Authored-By: Anders Larsson <64838990+anders-topp@users.noreply.github.com>
Co-Authored-By: Johan  <4934465+joolsus@users.noreply.github.com>
Co-Authored-By: Tore Knudsen <18231882+torekndsn@users.noreply.github.com>
Co-Authored-By: victoratndl <99176179+victoratndl@users.noreply.github.com>
This commit is contained in:
Michael Cartner
2024-01-26 11:52:55 +01:00
commit b9c60b07dc
2789 changed files with 868795 additions and 0 deletions

View File

@@ -0,0 +1,157 @@
import type { NodeRegister, GraphModel, TSFixme } from '../typings/global';
import FontLoader from './fontloader';
function getInputsWithType(nodeScope, inputType) {
const result = [];
const nodes = nodeScope.getAllNodesRecursive();
nodes.forEach((node) => {
const inputs = [];
for (const inputName in node._inputs) {
const input = node._inputs[inputName];
if (input.type === inputType) {
inputs.push(inputName);
}
}
if (inputs.length) {
result.push({ node, inputs });
}
});
return result;
}
type TextStyleData = {
letterSpacing: string;
lineHeight: { value: string; unit: string };
textTransform: string;
fontSize: { value: string; unit: string };
fontFamily: string;
color: string;
};
type StylesData = {
text?: Record<string, TextStyleData>;
colors?: Record<string, string>;
};
export default class Styles {
getNodeScope: () => TSFixme;
graphModel: GraphModel;
nodeRegister: NodeRegister;
styles: StylesData;
constructor({ graphModel, nodeRegister, getNodeScope }) {
this.getNodeScope = getNodeScope;
this.graphModel = graphModel;
this.nodeRegister = nodeRegister;
this.setStyles(graphModel.getMetaData('styles') || {});
graphModel.on('metadataChanged.styles', (styles) => this.setStyles(styles));
}
setStyles(styles: StylesData) {
// Brute force update all styles, no delta check
this.styles = styles;
// Process text styles
const textStyles = styles.text || {};
// Format font family
Object.values(textStyles)
.filter((style) => style.fontFamily)
.forEach((textStyle) => {
let family = textStyle.fontFamily;
// Load files and create font css
if (family.split('.').length > 1) {
FontLoader.instance.loadFont(family);
family = family.replace(/\.[^/.]+$/, '');
family = family.split('/').pop();
// Update the style to the font css instead of the file name
textStyle.fontFamily = family;
}
});
// Format values with units (to css strings)
for (const name in textStyles) {
const style = textStyles[name];
for (const prop in style) {
const value = style[prop];
if (typeof value === 'object') {
style[prop] = value.value + value.unit;
}
}
}
// Remove colors with empty strings
for (const name in textStyles) {
const style = textStyles[name];
if (style.hasOwnProperty('color') && !style.color) {
delete style.color;
}
}
const nodeScope = this.getNodeScope && this.getNodeScope();
if (!nodeScope) return;
const variants = this.graphModel.getVariants();
for (const variant of variants) {
if (this._variantHasInputsWithTypes(variant, ['color', 'textStyle'])) {
const nodes = nodeScope.getAllNodesWithVariantRecursive(variant);
nodes.forEach((node) => node.setVariant(variant));
}
}
//set all inputs with types using styles
//just re-apply the previous value to trigger a new style resolve
['color', 'textStyle'].forEach((inputType) => {
getInputsWithType(nodeScope, inputType).forEach(({ node, inputs }) => {
inputs.forEach((inputName) => {
if (node.getInputValue(inputName)) {
node.setInputValue(inputName, node.getInputValue(inputName));
}
});
});
});
}
resolveColor(color: string) {
if (!this.styles.colors) return color;
const resolvedColor = this.styles.colors[color];
return resolvedColor ? resolvedColor : color;
}
getTextStyle(styleName: string) {
if (!this.styles.text) return {};
return this.styles.text[styleName] || {};
}
//checks if a variant includes inputs with the specified types
_variantHasInputsWithTypes(variant, types) {
if (!this.nodeRegister.hasNode(variant.typename)) return;
//get the metadata for the node this variant is used by
const metadata = this.nodeRegister.getNodeMetadata(variant.typename);
//get all the inputs this variant affects...
const parameterNames = new Set(Object.keys(variant.parameters));
for (const state in variant.stateParameters) {
Object.keys(variant.stateParameters[state]).forEach((param) => parameterNames.add(param));
}
//...and check if the inputs are of the supplied types
for (const param of Array.from(parameterNames)) {
const inputType = metadata.inputs[param] && metadata.inputs[param].type;
if (types.includes(inputType)) {
return true;
}
}
return false;
}
}