Loading packages/client/src/components/Settings/TemplateSettings.tsx +26 −1 Original line number Diff line number Diff line import { useTemplateContext } from "../../contexts/TemplateContext"; import { Input, Slider, Switch } from "@nextui-org/react"; import { Input, Select, SelectItem, Slider, Switch } from "@nextui-org/react"; export const TemplateSettings = () => { const { Loading @@ -15,6 +15,8 @@ export const TemplateSettings = () => { setY, opacity, setOpacity, style, setStyle, showMobileTools, setShowMobileTools, } = useTemplateContext(); Loading Loading @@ -70,6 +72,29 @@ export const TemplateSettings = () => { onChange={(v) => setOpacity(v as number)} getValue={(v) => v + "%"} /> <Select label="Template Style" size="sm" selectedKeys={[style]} onChange={(e) => setStyle(e.target.value as any)} > <SelectItem key="SOURCE">Source</SelectItem> <SelectItem key="ONE_TO_ONE">One-to-one</SelectItem> <SelectItem key="ONE_TO_ONE_INCORRECT"> One-to-one (keep incorrect) </SelectItem> <SelectItem key="DOTTED_SMALL">Dotted Small</SelectItem> <SelectItem key="DOTTED_BIG">Dotted Big</SelectItem> <SelectItem key="SYMBOLS">Symbols</SelectItem> <SelectItem key="NUMBERS">Numbers</SelectItem> </Select> {style !== "ONE_TO_ONE" && ( <div> <b>Warning:</b> Template color picking only <br /> works with one-to-one template style </div> )} <Switch className="md:hidden" isSelected={showMobileTools} Loading packages/client/src/components/Templating/Template.tsx +19 −8 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ import { Canvas } from "../../lib/canvas"; export const Template = () => { const { config } = useAppContext(); const { enable, url, width, setWidth, x, y, opacity, setX, setY } = const { enable, url, width, setWidth, x, y, opacity, setX, setY, style } = useTemplateContext(); const templateHolder = useRef<HTMLDivElement>(null); const instance = useRef<TemplateCl>(); Loading Loading @@ -87,7 +87,9 @@ export const Template = () => { useEffect(() => { if (!instance.current) { console.warn("Received template enable but no instance exists"); console.warn( "[Template] Received template enable but no instance exists" ); return; } Loading @@ -95,7 +97,7 @@ export const Template = () => { if (enable && url) { instance.current.loadImage(url).then(() => { console.log("enable: load image finished"); console.log("[Template] enable: load image finished"); }); } }, [enable]); Loading @@ -103,29 +105,29 @@ export const Template = () => { useEffect(() => { if (!instance.current) { console.warn( "recieved template url update but no template instance exists" "[Template] Recieved template url update but no template instance exists" ); return; } if (!url) { console.warn("received template url blank"); console.warn("[Template] Received template url blank"); return; } if (!enable) { console.info("Got template URL but not enabled, ignoring"); console.info("[Template] Got template URL but not enabled, ignoring"); return; } instance.current.loadImage(url).then(() => { console.log("template loader finished"); console.log("[Template] Template loader finished"); }); }, [url]); useEffect(() => { if (!instance.current) { console.warn("received template width with no instance"); console.warn("[Template] Received template width with no instance"); return; } Loading @@ -133,6 +135,15 @@ export const Template = () => { instance.current.rasterizeTemplate(); }, [width]); useEffect(() => { if (!instance.current) { console.warn("[Template] Received style update with no instance"); return; } instance.current.setOption("style", style); }, [style]); return ( <div id="template" Loading packages/client/src/contexts/TemplateContext.tsx +11 −2 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ import { } from "react"; import { IRouterData, Router } from "../lib/router"; import { KeybindManager } from "../lib/keybinds"; import { TemplateStyle } from "../lib/template"; interface ITemplate { /** Loading @@ -30,6 +31,7 @@ interface ITemplate { x: number; y: number; opacity: number; style: TemplateStyle; showMobileTools: boolean; Loading @@ -39,6 +41,7 @@ interface ITemplate { setX(v: number): void; setY(v: number): void; setOpacity(v: number): void; setStyle(style: TemplateStyle): void; setShowMobileTools(v: boolean): void; } Loading @@ -56,6 +59,9 @@ export const TemplateContext = ({ children }: PropsWithChildren) => { const [x, setX] = useState(routerData.template?.x || 0); const [y, setY] = useState(routerData.template?.y || 0); const [opacity, setOpacity] = useState(100); const [style, setStyle] = useState<TemplateStyle>( routerData.template?.style || "ONE_TO_ONE" ); const [showMobileTools, setShowMobileTools] = useState(true); const initAt = useRef<number>(); Loading @@ -70,6 +76,7 @@ export const TemplateContext = ({ children }: PropsWithChildren) => { setWidth(data.template.width); setX(data.template.x || 0); setY(data.template.y || 0); setStyle(data.template.style || "ONE_TO_ONE"); } else { setEnable(false); } Loading @@ -89,7 +96,7 @@ export const TemplateContext = ({ children }: PropsWithChildren) => { }, []); useEffect(() => { Router.setTemplate({ enabled: enable, width, x, y, url }); Router.setTemplate({ enabled: enable, width, x, y, url, style }); if (!initAt.current) { console.debug("TemplateContext updating router but no initAt"); Loading @@ -102,7 +109,7 @@ export const TemplateContext = ({ children }: PropsWithChildren) => { if (initAt.current && Date.now() - initAt.current > 2 * 1000) Router.queueUpdate(); }, [enable, width, x, y, url]); }, [enable, width, x, y, url, style]); return ( <templateContext.Provider Loading @@ -119,6 +126,8 @@ export const TemplateContext = ({ children }: PropsWithChildren) => { setY, opacity, setOpacity, style, setStyle, showMobileTools, setShowMobileTools, }} Loading packages/client/src/lib/router.ts +17 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ import { PanZoom } from "@sc07-canvas/lib/src/renderer/PanZoom"; import { Canvas } from "./canvas"; import throttle from "lodash.throttle"; import EventEmitter from "eventemitter3"; import { TemplateStyle, TemplateStyles } from "./template"; const CLIENT_PARAMS = { canvas_x: "x", Loading @@ -11,6 +12,7 @@ const CLIENT_PARAMS = { template_width: "tw", template_x: "tx", template_y: "ty", template_style: "ts", }; export interface IRouterData { Loading @@ -24,6 +26,7 @@ export interface IRouterData { width?: number; x?: number; y?: number; style?: TemplateStyle; }; } Loading @@ -41,10 +44,12 @@ class _Router extends EventEmitter<RouterEvents> { x: number; y: number; url?: string; style: TemplateStyle; } = { enabled: false, x: 0, y: 0, style: "ONE_TO_ONE", }; constructor() { Loading Loading @@ -105,6 +110,8 @@ class _Router extends EventEmitter<RouterEvents> { params.set(CLIENT_PARAMS.template_width, this.templateState.width + ""); params.set(CLIENT_PARAMS.template_x, this.templateState.x + ""); params.set(CLIENT_PARAMS.template_y, this.templateState.y + ""); if (this.templateState.style) params.set(CLIENT_PARAMS.template_style, this.templateState.style + ""); } return ( Loading Loading @@ -161,6 +168,7 @@ class _Router extends EventEmitter<RouterEvents> { width?: number; x?: number; y?: number; style?: TemplateStyle; } | undefined = undefined; Loading Loading @@ -190,6 +198,14 @@ class _Router extends EventEmitter<RouterEvents> { template.y = y; } } if (params.has(CLIENT_PARAMS.template_style)) { let style = params.get(CLIENT_PARAMS.template_style); if (style && TemplateStyles.indexOf(style) > -1) { template.style = style as any; } } } return { Loading @@ -208,6 +224,7 @@ class _Router extends EventEmitter<RouterEvents> { x: number; y: number; url?: string; style: TemplateStyle; }) { this.templateState = args; } Loading packages/client/src/lib/template.ts +67 −32 Original line number Diff line number Diff line Loading @@ -15,18 +15,30 @@ interface TemplateEvents { interface ITemplateOptions { enable: boolean; width?: number; style: TemplateStyle; } style: keyof typeof TemplateStyle; } const TemplateStyle = { SOURCE: "", ONE_TO_ONE: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGklEQVQoz2P8//8/AymAiYFEMKphVMPQ0QAAVW0DHZ8uFaIAAAAASUVORK5CYII=", ONE_TO_ONE_INCORRECT: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGklEQVQoz2P8//8/AymAiYFEMKphVMPQ0QAAVW0DHZ8uFaIAAAAASUVORK5CYII=", DOTTED_SMALL: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAQAAAD9CzEMAAAAAmJLR0QA/4ePzL8AAAAzSURBVFjD7dBBDQAACMSw828aVEAI6R4T0GShGv6DECFChAgRIkSIECFChAgRIkSIruA0nub+AuTzLZoAAAAASUVORK5CYII=", DOTTED_BIG: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAWklEQVR42u3UwQkAIAwEwcX+e9aP2INkBvK4d2CLqva9cXv5PWgAoAGgARoAGqABoAEaABqgAaABGgAaoAGgARoAGqABoAEaABqgAaABGgAaoAGgAT/vRwOmO8dS/DI1VxCbAAAAAElFTkSuQmCC", SYMBOLS: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAABwAQMAAAD8LmYIAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAuIwAALiMBeKU/dgAAAAZQTFRFAAAAAwMDFQUF7wAAAAJ0Uk5TAP9bkSK1AAAAuUlEQVR4nGNgQAUhjQvdz0uwMfx82OrVIgPkBj/xaOEQ6GRuP9vHAeQGsPjzyVj8LH5+iAXEDTziMd+uplHg+VE+GQaNjwHt5+WB3A+HO+bbMRACDoed+Xg0FIMW97dIMLAwNC45OF8ip+Dh8aN8Ngwsjc2sXfNFBAoePz8xX46B5+DhNj4WlpwCx+NH5W0Yan5+fn6+xU5DwWlxf58EAWs0DFC4NQX4uBaoXAFUvaNgFIyCUTAKaAYAzI49GM5w0hQAAAAOZVhJZk1NACoAAAAIAAAAAAAAANJTkwAAAABJRU5ErkJggg==", NUMBERS: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALAAAACwCAYAAACvt+ReAAAE10lEQVR42u3d3bKjKBQGULDy/q/MXE1VdzqRH9kqZq2bqZn5JKAmErbm5JRSSbCw0pGTlb1VdttpoAS9AUpANgW1u0q2dGxTOo7faLu92TTa7vZlozz55P2/zRyQ7RXRj97+zsyWjm1GT97aGI9kR8aWaydwxIEg7g05ms0nvcnCsq8bzrVnvVNr2RyQzReP7eeO33bBp0We/E6NnJr0nJAR7UZOpR5x/LYEC9smrCyMrETMXErpvazd4fI9c3+VnW/2teze8Ss7qwAt7ZYJ50y13deqk/fBbVYb28iY8mLZvf9ebTcnlTgeOIWAZShJyi6bfX3YOH84sfOXF7oyW3amQrXs++vMarc3m7/048w+rJT957htlU/i3HCQ93J77R7N5o4vD+/ZUvmSkRvHdiSbOvqwt/2RbA7av6cdt+0Bqw8jlMDX9M9xq5WS71xKjS5VtmxbDvZ3JJsDsvnEsU09dq+GM75MPnl72s2VQZx1JehdA23pb8/YevdDax/KhWMrM84Vy2gs7dOXuJGSZMslYLTUWbsUtbT7nm25ibqlhPqp3Z7+po7+RuyHnj707t/S8fql8/XLyHzE2qPs7bJKyTxmCgFLcimSXTa7fdiwfPn3NDGbgtq9ezYNZke++JaAbApqdzj75zrw+9rd3lrekeye1vsljmZ7+5snZL/1q2clJw3uwxnZXlGPWP3VX3PgNSh9f/HaeaeXzk+FEpzNAdl88dhSQPanjttWeafX7lZq/ZRovQPqSLanDyWo3ci70XqyvXeutbQbeVdez91onkrmmVOII3c1RV02I+8Ei2g36sc/SuOVo+WSfKS/EdOfw/2wnii7bFYpmaWZA7M8lyLZZbOvD0sUf/4z7XyJ68n++f88PfyDTw9H9WHWI0W17JFHXmqv+WnHzcymjj7Utj2yvpwC9u/yx+3uc2Al1DWddtxelfnw7DJjxI9Kt14pSuM7flY2B2TzxWO73XF7/12IM8qMtXeuEmpDCfWEsR2dSvVOu4ZuWbCMxtJaf9gkHcjNKM3WVgBqlzGl7/7+HhlfrfQ9ejdaOXqSysreKquUzNLMgVmeS5Hsstlv9wMroY5lW7+4KH1Pyr6vQiihHnsquTSMy1Pf4/v3n6w58FxK3yf7VkpWQo35M7Ol4xPzvd0SnM0B2Rw9tq1y+f7Fp4fPOHlr/SgdYysHxta7H3pOyIh2/a1kfmMK0fqJ0rrd3Uq5nh6O3Q8peP8Obywre6usUjJLMwdmeS5Fsstma6Xkb8scSqjPyC5/3Fp+nfKbI0+hRq0vp45s72MsOaC/V2eXP26z5sBKqGta/rjNWgfuyfrh7Pix/cxx2w68Iy95CvWiS5wfzt7f/rKnvi2j8egpxC2fQr355TCiXU9972xrPVF22axSMo+aQkCUsCU7lyLZM7Lhn8BKqOf39xdL31PN+kOHSqhj+yF1ju0ppe+wE9h8jKW/xK1WQj1D5GM3I9mIH5vOF49tyifwij/AfOYndk8JNqLNiDJ/CWr3tOOmlMxjphB+gPn4VErp+4Jpn3VK2TOyYXM7pWTO+h4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE/1H4IIqRgL4W2oAAAAAElFTkSuQmCC", }; enum TemplateStyle { SOURCE = "", ONE_TO_ONE = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGklEQVQoz2P8//8/AymAiYFEMKphVMPQ0QAAVW0DHZ8uFaIAAAAASUVORK5CYII=", ONE_TO_ONE_INCORRECT = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGklEQVQoz2P8//8/AymAiYFEMKphVMPQ0QAAVW0DHZ8uFaIAAAAASUVORK5CYII=", DOTTED_SMALL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAQAAAD9CzEMAAAAAmJLR0QA/4ePzL8AAAAzSURBVFjD7dBBDQAACMSw828aVEAI6R4T0GShGv6DECFChAgRIkSIECFChAgRIkSIruA0nub+AuTzLZoAAAAASUVORK5CYII=", DOTTED_BIG = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAWklEQVR42u3UwQkAIAwEwcX+e9aP2INkBvK4d2CLqva9cXv5PWgAoAGgARoAGqABoAEaABqgAaABGgAaoAGgARoAGqABoAEaABqgAaABGgAaoAGgAT/vRwOmO8dS/DI1VxCbAAAAAElFTkSuQmCC", SYMBOLS = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAABwAQMAAAD8LmYIAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAuIwAALiMBeKU/dgAAAAZQTFRFAAAAAwMDFQUF7wAAAAJ0Uk5TAP9bkSK1AAAAuUlEQVR4nGNgQAUhjQvdz0uwMfx82OrVIgPkBj/xaOEQ6GRuP9vHAeQGsPjzyVj8LH5+iAXEDTziMd+uplHg+VE+GQaNjwHt5+WB3A+HO+bbMRACDoed+Xg0FIMW97dIMLAwNC45OF8ip+Dh8aN8Ngwsjc2sXfNFBAoePz8xX46B5+DhNj4WlpwCx+NH5W0Yan5+fn6+xU5DwWlxf58EAWs0DFC4NQX4uBaoXAFUvaNgFIyCUTAKaAYAzI49GM5w0hQAAAAOZVhJZk1NACoAAAAIAAAAAAAAANJTkwAAAABJRU5ErkJggg==", NUMBERS = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALAAAACwCAYAAACvt+ReAAAE10lEQVR42u3d3bKjKBQGULDy/q/MXE1VdzqRH9kqZq2bqZn5JKAmErbm5JRSSbCw0pGTlb1VdttpoAS9AUpANgW1u0q2dGxTOo7faLu92TTa7vZlozz55P2/zRyQ7RXRj97+zsyWjm1GT97aGI9kR8aWaydwxIEg7g05ms0nvcnCsq8bzrVnvVNr2RyQzReP7eeO33bBp0We/E6NnJr0nJAR7UZOpR5x/LYEC9smrCyMrETMXErpvazd4fI9c3+VnW/2teze8Ss7qwAt7ZYJ50y13deqk/fBbVYb28iY8mLZvf9ebTcnlTgeOIWAZShJyi6bfX3YOH84sfOXF7oyW3amQrXs++vMarc3m7/048w+rJT957htlU/i3HCQ93J77R7N5o4vD+/ZUvmSkRvHdiSbOvqwt/2RbA7av6cdt+0Bqw8jlMDX9M9xq5WS71xKjS5VtmxbDvZ3JJsDsvnEsU09dq+GM75MPnl72s2VQZx1JehdA23pb8/YevdDax/KhWMrM84Vy2gs7dOXuJGSZMslYLTUWbsUtbT7nm25ibqlhPqp3Z7+po7+RuyHnj707t/S8fql8/XLyHzE2qPs7bJKyTxmCgFLcimSXTa7fdiwfPn3NDGbgtq9ezYNZke++JaAbApqdzj75zrw+9rd3lrekeye1vsljmZ7+5snZL/1q2clJw3uwxnZXlGPWP3VX3PgNSh9f/HaeaeXzk+FEpzNAdl88dhSQPanjttWeafX7lZq/ZRovQPqSLanDyWo3ci70XqyvXeutbQbeVdez91onkrmmVOII3c1RV02I+8Ei2g36sc/SuOVo+WSfKS/EdOfw/2wnii7bFYpmaWZA7M8lyLZZbOvD0sUf/4z7XyJ68n++f88PfyDTw9H9WHWI0W17JFHXmqv+WnHzcymjj7Utj2yvpwC9u/yx+3uc2Al1DWddtxelfnw7DJjxI9Kt14pSuM7flY2B2TzxWO73XF7/12IM8qMtXeuEmpDCfWEsR2dSvVOu4ZuWbCMxtJaf9gkHcjNKM3WVgBqlzGl7/7+HhlfrfQ9ejdaOXqSysreKquUzNLMgVmeS5Hsstlv9wMroY5lW7+4KH1Pyr6vQiihHnsquTSMy1Pf4/v3n6w58FxK3yf7VkpWQo35M7Ol4xPzvd0SnM0B2Rw9tq1y+f7Fp4fPOHlr/SgdYysHxta7H3pOyIh2/a1kfmMK0fqJ0rrd3Uq5nh6O3Q8peP8Obywre6usUjJLMwdmeS5Fsstma6Xkb8scSqjPyC5/3Fp+nfKbI0+hRq0vp45s72MsOaC/V2eXP26z5sBKqGta/rjNWgfuyfrh7Pix/cxx2w68Iy95CvWiS5wfzt7f/rKnvi2j8egpxC2fQr355TCiXU9972xrPVF22axSMo+aQkCUsCU7lyLZM7Lhn8BKqOf39xdL31PN+kOHSqhj+yF1ju0ppe+wE9h8jKW/xK1WQj1D5GM3I9mIH5vOF49tyifwij/AfOYndk8JNqLNiDJ/CWr3tOOmlMxjphB+gPn4VErp+4Jpn3VK2TOyYXM7pWTO+h4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE/1H4IIqRgL4W2oAAAAAElFTkSuQmCC", } export type TemplateStyle = keyof typeof TemplateStyle; export const TemplateStyles = Object.keys(TemplateStyle); const STYLES_Y = 16; const STYLES_X = 16; export class Template extends EventEmitter<TemplateEvents> { static instance: Template; Loading @@ -41,7 +53,7 @@ export class Template extends EventEmitter<TemplateEvents> { options: ITemplateOptions = { enable: false, style: TemplateStyle.ONE_TO_ONE, style: "ONE_TO_ONE", }; constructor(config: ClientConfig, templateHolder: HTMLDivElement) { Loading @@ -67,7 +79,11 @@ export class Template extends EventEmitter<TemplateEvents> { this.$style = document.createElement("img"); this.$style.setAttribute("crossorigin", ""); this.$style.setAttribute("src", this.options!.style); this.$style.setAttribute("src", TemplateStyle[this.options!.style]); this.$style.addEventListener("load", () => { console.log("[Template] Style loaded"); this.loadStyle(); }); this.$canvas = document.createElement("canvas"); Loading Loading @@ -108,6 +124,18 @@ export class Template extends EventEmitter<TemplateEvents> { case "enable": this.setElementVisible([this.$canvas], !!value); break; case "style": if ((value as keyof typeof TemplateStyle) in TemplateStyle) { const key = value as keyof typeof TemplateStyle; this.$style.setAttribute("src", TemplateStyle[key]); this.$imageLoader.style.display = key === "SOURCE" ? "block" : "none"; if (key === "SOURCE") { this.stylizeTemplate(); } } break; } this.emit("option", key, value); Loading Loading @@ -208,15 +236,27 @@ export class Template extends EventEmitter<TemplateEvents> { width: this.$imageLoader.naturalWidth, height: this.$imageLoader.naturalHeight, }; let style = { width: this.$style.naturalWidth / STYLES_X, height: this.$style.naturalHeight / STYLES_Y, }; let aspectRatio = source.height / source.width; return { source, display: { let display = { width: Math.round(this.options?.width || source.width), height: Math.round((this.options?.width || source.width) * aspectRatio), }, }; let internal = { width: display.width * style.width, height: display.height * style.height, }; return { source, style, display, internal, aspectRatio, }; } Loading @@ -240,15 +280,14 @@ export class Template extends EventEmitter<TemplateEvents> { } = { downscaling: {} } as any; updateSize() { const { display: { width, height }, } = this.getDimentions(); const { display, internal } = this.getDimentions(); this.$wrapper.style.width = width + "px"; this.$imageLoader.style.width = width + "px"; this.$wrapper.style.width = display.width + "px"; this.$imageLoader.style.width = display.width + "px"; this.$canvas.style.width = display.width + "px"; this.$canvas.width = width; this.$canvas.height = height; this.$canvas.width = internal.width; this.$canvas.height = internal.height; } /** Loading @@ -261,8 +300,6 @@ export class Template extends EventEmitter<TemplateEvents> { const palette: { value: string }[] = this.config.pallete.colors.map( (color) => ({ value: color.hex }) ); const STYLES_Y = 16; const STYLES_X = 16; const context = this.$canvas.getContext("webgl", { premultipliedAlpha: true, Loading Loading @@ -589,11 +626,9 @@ export class Template extends EventEmitter<TemplateEvents> { stylizeTemplate() { this.updateSize(); const { display: { width, height }, } = this.getDimentions(); const { internal, display } = this.getDimentions(); if (this.context == null || width === 0 || height === 0) { if (this.context == null || internal.width === 0 || internal.height === 0) { return; } Loading @@ -602,14 +637,14 @@ export class Template extends EventEmitter<TemplateEvents> { this.framebuffers.main ); this.context.clear(this.context.COLOR_BUFFER_BIT); this.context.viewport(0, 0, width, height); this.context.viewport(0, 0, internal.width, internal.height); this.context.useProgram(this.programs.stylize); this.context.uniform2f( this.context.getUniformLocation(this.programs.stylize, "u_TexelSize"), 1 / width, 1 / height 1 / display.width, 1 / display.height ); this.context.activeTexture(this.context.TEXTURE0); Loading Loading
packages/client/src/components/Settings/TemplateSettings.tsx +26 −1 Original line number Diff line number Diff line import { useTemplateContext } from "../../contexts/TemplateContext"; import { Input, Slider, Switch } from "@nextui-org/react"; import { Input, Select, SelectItem, Slider, Switch } from "@nextui-org/react"; export const TemplateSettings = () => { const { Loading @@ -15,6 +15,8 @@ export const TemplateSettings = () => { setY, opacity, setOpacity, style, setStyle, showMobileTools, setShowMobileTools, } = useTemplateContext(); Loading Loading @@ -70,6 +72,29 @@ export const TemplateSettings = () => { onChange={(v) => setOpacity(v as number)} getValue={(v) => v + "%"} /> <Select label="Template Style" size="sm" selectedKeys={[style]} onChange={(e) => setStyle(e.target.value as any)} > <SelectItem key="SOURCE">Source</SelectItem> <SelectItem key="ONE_TO_ONE">One-to-one</SelectItem> <SelectItem key="ONE_TO_ONE_INCORRECT"> One-to-one (keep incorrect) </SelectItem> <SelectItem key="DOTTED_SMALL">Dotted Small</SelectItem> <SelectItem key="DOTTED_BIG">Dotted Big</SelectItem> <SelectItem key="SYMBOLS">Symbols</SelectItem> <SelectItem key="NUMBERS">Numbers</SelectItem> </Select> {style !== "ONE_TO_ONE" && ( <div> <b>Warning:</b> Template color picking only <br /> works with one-to-one template style </div> )} <Switch className="md:hidden" isSelected={showMobileTools} Loading
packages/client/src/components/Templating/Template.tsx +19 −8 Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ import { Canvas } from "../../lib/canvas"; export const Template = () => { const { config } = useAppContext(); const { enable, url, width, setWidth, x, y, opacity, setX, setY } = const { enable, url, width, setWidth, x, y, opacity, setX, setY, style } = useTemplateContext(); const templateHolder = useRef<HTMLDivElement>(null); const instance = useRef<TemplateCl>(); Loading Loading @@ -87,7 +87,9 @@ export const Template = () => { useEffect(() => { if (!instance.current) { console.warn("Received template enable but no instance exists"); console.warn( "[Template] Received template enable but no instance exists" ); return; } Loading @@ -95,7 +97,7 @@ export const Template = () => { if (enable && url) { instance.current.loadImage(url).then(() => { console.log("enable: load image finished"); console.log("[Template] enable: load image finished"); }); } }, [enable]); Loading @@ -103,29 +105,29 @@ export const Template = () => { useEffect(() => { if (!instance.current) { console.warn( "recieved template url update but no template instance exists" "[Template] Recieved template url update but no template instance exists" ); return; } if (!url) { console.warn("received template url blank"); console.warn("[Template] Received template url blank"); return; } if (!enable) { console.info("Got template URL but not enabled, ignoring"); console.info("[Template] Got template URL but not enabled, ignoring"); return; } instance.current.loadImage(url).then(() => { console.log("template loader finished"); console.log("[Template] Template loader finished"); }); }, [url]); useEffect(() => { if (!instance.current) { console.warn("received template width with no instance"); console.warn("[Template] Received template width with no instance"); return; } Loading @@ -133,6 +135,15 @@ export const Template = () => { instance.current.rasterizeTemplate(); }, [width]); useEffect(() => { if (!instance.current) { console.warn("[Template] Received style update with no instance"); return; } instance.current.setOption("style", style); }, [style]); return ( <div id="template" Loading
packages/client/src/contexts/TemplateContext.tsx +11 −2 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ import { } from "react"; import { IRouterData, Router } from "../lib/router"; import { KeybindManager } from "../lib/keybinds"; import { TemplateStyle } from "../lib/template"; interface ITemplate { /** Loading @@ -30,6 +31,7 @@ interface ITemplate { x: number; y: number; opacity: number; style: TemplateStyle; showMobileTools: boolean; Loading @@ -39,6 +41,7 @@ interface ITemplate { setX(v: number): void; setY(v: number): void; setOpacity(v: number): void; setStyle(style: TemplateStyle): void; setShowMobileTools(v: boolean): void; } Loading @@ -56,6 +59,9 @@ export const TemplateContext = ({ children }: PropsWithChildren) => { const [x, setX] = useState(routerData.template?.x || 0); const [y, setY] = useState(routerData.template?.y || 0); const [opacity, setOpacity] = useState(100); const [style, setStyle] = useState<TemplateStyle>( routerData.template?.style || "ONE_TO_ONE" ); const [showMobileTools, setShowMobileTools] = useState(true); const initAt = useRef<number>(); Loading @@ -70,6 +76,7 @@ export const TemplateContext = ({ children }: PropsWithChildren) => { setWidth(data.template.width); setX(data.template.x || 0); setY(data.template.y || 0); setStyle(data.template.style || "ONE_TO_ONE"); } else { setEnable(false); } Loading @@ -89,7 +96,7 @@ export const TemplateContext = ({ children }: PropsWithChildren) => { }, []); useEffect(() => { Router.setTemplate({ enabled: enable, width, x, y, url }); Router.setTemplate({ enabled: enable, width, x, y, url, style }); if (!initAt.current) { console.debug("TemplateContext updating router but no initAt"); Loading @@ -102,7 +109,7 @@ export const TemplateContext = ({ children }: PropsWithChildren) => { if (initAt.current && Date.now() - initAt.current > 2 * 1000) Router.queueUpdate(); }, [enable, width, x, y, url]); }, [enable, width, x, y, url, style]); return ( <templateContext.Provider Loading @@ -119,6 +126,8 @@ export const TemplateContext = ({ children }: PropsWithChildren) => { setY, opacity, setOpacity, style, setStyle, showMobileTools, setShowMobileTools, }} Loading
packages/client/src/lib/router.ts +17 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ import { PanZoom } from "@sc07-canvas/lib/src/renderer/PanZoom"; import { Canvas } from "./canvas"; import throttle from "lodash.throttle"; import EventEmitter from "eventemitter3"; import { TemplateStyle, TemplateStyles } from "./template"; const CLIENT_PARAMS = { canvas_x: "x", Loading @@ -11,6 +12,7 @@ const CLIENT_PARAMS = { template_width: "tw", template_x: "tx", template_y: "ty", template_style: "ts", }; export interface IRouterData { Loading @@ -24,6 +26,7 @@ export interface IRouterData { width?: number; x?: number; y?: number; style?: TemplateStyle; }; } Loading @@ -41,10 +44,12 @@ class _Router extends EventEmitter<RouterEvents> { x: number; y: number; url?: string; style: TemplateStyle; } = { enabled: false, x: 0, y: 0, style: "ONE_TO_ONE", }; constructor() { Loading Loading @@ -105,6 +110,8 @@ class _Router extends EventEmitter<RouterEvents> { params.set(CLIENT_PARAMS.template_width, this.templateState.width + ""); params.set(CLIENT_PARAMS.template_x, this.templateState.x + ""); params.set(CLIENT_PARAMS.template_y, this.templateState.y + ""); if (this.templateState.style) params.set(CLIENT_PARAMS.template_style, this.templateState.style + ""); } return ( Loading Loading @@ -161,6 +168,7 @@ class _Router extends EventEmitter<RouterEvents> { width?: number; x?: number; y?: number; style?: TemplateStyle; } | undefined = undefined; Loading Loading @@ -190,6 +198,14 @@ class _Router extends EventEmitter<RouterEvents> { template.y = y; } } if (params.has(CLIENT_PARAMS.template_style)) { let style = params.get(CLIENT_PARAMS.template_style); if (style && TemplateStyles.indexOf(style) > -1) { template.style = style as any; } } } return { Loading @@ -208,6 +224,7 @@ class _Router extends EventEmitter<RouterEvents> { x: number; y: number; url?: string; style: TemplateStyle; }) { this.templateState = args; } Loading
packages/client/src/lib/template.ts +67 −32 Original line number Diff line number Diff line Loading @@ -15,18 +15,30 @@ interface TemplateEvents { interface ITemplateOptions { enable: boolean; width?: number; style: TemplateStyle; } style: keyof typeof TemplateStyle; } const TemplateStyle = { SOURCE: "", ONE_TO_ONE: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGklEQVQoz2P8//8/AymAiYFEMKphVMPQ0QAAVW0DHZ8uFaIAAAAASUVORK5CYII=", ONE_TO_ONE_INCORRECT: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGklEQVQoz2P8//8/AymAiYFEMKphVMPQ0QAAVW0DHZ8uFaIAAAAASUVORK5CYII=", DOTTED_SMALL: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAQAAAD9CzEMAAAAAmJLR0QA/4ePzL8AAAAzSURBVFjD7dBBDQAACMSw828aVEAI6R4T0GShGv6DECFChAgRIkSIECFChAgRIkSIruA0nub+AuTzLZoAAAAASUVORK5CYII=", DOTTED_BIG: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAWklEQVR42u3UwQkAIAwEwcX+e9aP2INkBvK4d2CLqva9cXv5PWgAoAGgARoAGqABoAEaABqgAaABGgAaoAGgARoAGqABoAEaABqgAaABGgAaoAGgAT/vRwOmO8dS/DI1VxCbAAAAAElFTkSuQmCC", SYMBOLS: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAABwAQMAAAD8LmYIAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAuIwAALiMBeKU/dgAAAAZQTFRFAAAAAwMDFQUF7wAAAAJ0Uk5TAP9bkSK1AAAAuUlEQVR4nGNgQAUhjQvdz0uwMfx82OrVIgPkBj/xaOEQ6GRuP9vHAeQGsPjzyVj8LH5+iAXEDTziMd+uplHg+VE+GQaNjwHt5+WB3A+HO+bbMRACDoed+Xg0FIMW97dIMLAwNC45OF8ip+Dh8aN8Ngwsjc2sXfNFBAoePz8xX46B5+DhNj4WlpwCx+NH5W0Yan5+fn6+xU5DwWlxf58EAWs0DFC4NQX4uBaoXAFUvaNgFIyCUTAKaAYAzI49GM5w0hQAAAAOZVhJZk1NACoAAAAIAAAAAAAAANJTkwAAAABJRU5ErkJggg==", NUMBERS: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALAAAACwCAYAAACvt+ReAAAE10lEQVR42u3d3bKjKBQGULDy/q/MXE1VdzqRH9kqZq2bqZn5JKAmErbm5JRSSbCw0pGTlb1VdttpoAS9AUpANgW1u0q2dGxTOo7faLu92TTa7vZlozz55P2/zRyQ7RXRj97+zsyWjm1GT97aGI9kR8aWaydwxIEg7g05ms0nvcnCsq8bzrVnvVNr2RyQzReP7eeO33bBp0We/E6NnJr0nJAR7UZOpR5x/LYEC9smrCyMrETMXErpvazd4fI9c3+VnW/2teze8Ss7qwAt7ZYJ50y13deqk/fBbVYb28iY8mLZvf9ebTcnlTgeOIWAZShJyi6bfX3YOH84sfOXF7oyW3amQrXs++vMarc3m7/048w+rJT957htlU/i3HCQ93J77R7N5o4vD+/ZUvmSkRvHdiSbOvqwt/2RbA7av6cdt+0Bqw8jlMDX9M9xq5WS71xKjS5VtmxbDvZ3JJsDsvnEsU09dq+GM75MPnl72s2VQZx1JehdA23pb8/YevdDax/KhWMrM84Vy2gs7dOXuJGSZMslYLTUWbsUtbT7nm25ibqlhPqp3Z7+po7+RuyHnj707t/S8fql8/XLyHzE2qPs7bJKyTxmCgFLcimSXTa7fdiwfPn3NDGbgtq9ezYNZke++JaAbApqdzj75zrw+9rd3lrekeye1vsljmZ7+5snZL/1q2clJw3uwxnZXlGPWP3VX3PgNSh9f/HaeaeXzk+FEpzNAdl88dhSQPanjttWeafX7lZq/ZRovQPqSLanDyWo3ci70XqyvXeutbQbeVdez91onkrmmVOII3c1RV02I+8Ei2g36sc/SuOVo+WSfKS/EdOfw/2wnii7bFYpmaWZA7M8lyLZZbOvD0sUf/4z7XyJ68n++f88PfyDTw9H9WHWI0W17JFHXmqv+WnHzcymjj7Utj2yvpwC9u/yx+3uc2Al1DWddtxelfnw7DJjxI9Kt14pSuM7flY2B2TzxWO73XF7/12IM8qMtXeuEmpDCfWEsR2dSvVOu4ZuWbCMxtJaf9gkHcjNKM3WVgBqlzGl7/7+HhlfrfQ9ejdaOXqSysreKquUzNLMgVmeS5Hsstlv9wMroY5lW7+4KH1Pyr6vQiihHnsquTSMy1Pf4/v3n6w58FxK3yf7VkpWQo35M7Ol4xPzvd0SnM0B2Rw9tq1y+f7Fp4fPOHlr/SgdYysHxta7H3pOyIh2/a1kfmMK0fqJ0rrd3Uq5nh6O3Q8peP8Obywre6usUjJLMwdmeS5Fsstma6Xkb8scSqjPyC5/3Fp+nfKbI0+hRq0vp45s72MsOaC/V2eXP26z5sBKqGta/rjNWgfuyfrh7Pix/cxx2w68Iy95CvWiS5wfzt7f/rKnvi2j8egpxC2fQr355TCiXU9972xrPVF22axSMo+aQkCUsCU7lyLZM7Lhn8BKqOf39xdL31PN+kOHSqhj+yF1ju0ppe+wE9h8jKW/xK1WQj1D5GM3I9mIH5vOF49tyifwij/AfOYndk8JNqLNiDJ/CWr3tOOmlMxjphB+gPn4VErp+4Jpn3VK2TOyYXM7pWTO+h4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE/1H4IIqRgL4W2oAAAAAElFTkSuQmCC", }; enum TemplateStyle { SOURCE = "", ONE_TO_ONE = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGklEQVQoz2P8//8/AymAiYFEMKphVMPQ0QAAVW0DHZ8uFaIAAAAASUVORK5CYII=", ONE_TO_ONE_INCORRECT = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAGklEQVQoz2P8//8/AymAiYFEMKphVMPQ0QAAVW0DHZ8uFaIAAAAASUVORK5CYII=", DOTTED_SMALL = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAQAAAD9CzEMAAAAAmJLR0QA/4ePzL8AAAAzSURBVFjD7dBBDQAACMSw828aVEAI6R4T0GShGv6DECFChAgRIkSIECFChAgRIkSIruA0nub+AuTzLZoAAAAASUVORK5CYII=", DOTTED_BIG = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAWklEQVR42u3UwQkAIAwEwcX+e9aP2INkBvK4d2CLqva9cXv5PWgAoAGgARoAGqABoAEaABqgAaABGgAaoAGgARoAGqABoAEaABqgAaABGgAaoAGgAT/vRwOmO8dS/DI1VxCbAAAAAElFTkSuQmCC", SYMBOLS = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHAAAABwAQMAAAD8LmYIAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAuIwAALiMBeKU/dgAAAAZQTFRFAAAAAwMDFQUF7wAAAAJ0Uk5TAP9bkSK1AAAAuUlEQVR4nGNgQAUhjQvdz0uwMfx82OrVIgPkBj/xaOEQ6GRuP9vHAeQGsPjzyVj8LH5+iAXEDTziMd+uplHg+VE+GQaNjwHt5+WB3A+HO+bbMRACDoed+Xg0FIMW97dIMLAwNC45OF8ip+Dh8aN8Ngwsjc2sXfNFBAoePz8xX46B5+DhNj4WlpwCx+NH5W0Yan5+fn6+xU5DwWlxf58EAWs0DFC4NQX4uBaoXAFUvaNgFIyCUTAKaAYAzI49GM5w0hQAAAAOZVhJZk1NACoAAAAIAAAAAAAAANJTkwAAAABJRU5ErkJggg==", NUMBERS = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALAAAACwCAYAAACvt+ReAAAE10lEQVR42u3d3bKjKBQGULDy/q/MXE1VdzqRH9kqZq2bqZn5JKAmErbm5JRSSbCw0pGTlb1VdttpoAS9AUpANgW1u0q2dGxTOo7faLu92TTa7vZlozz55P2/zRyQ7RXRj97+zsyWjm1GT97aGI9kR8aWaydwxIEg7g05ms0nvcnCsq8bzrVnvVNr2RyQzReP7eeO33bBp0We/E6NnJr0nJAR7UZOpR5x/LYEC9smrCyMrETMXErpvazd4fI9c3+VnW/2teze8Ss7qwAt7ZYJ50y13deqk/fBbVYb28iY8mLZvf9ebTcnlTgeOIWAZShJyi6bfX3YOH84sfOXF7oyW3amQrXs++vMarc3m7/048w+rJT957htlU/i3HCQ93J77R7N5o4vD+/ZUvmSkRvHdiSbOvqwt/2RbA7av6cdt+0Bqw8jlMDX9M9xq5WS71xKjS5VtmxbDvZ3JJsDsvnEsU09dq+GM75MPnl72s2VQZx1JehdA23pb8/YevdDax/KhWMrM84Vy2gs7dOXuJGSZMslYLTUWbsUtbT7nm25ibqlhPqp3Z7+po7+RuyHnj707t/S8fql8/XLyHzE2qPs7bJKyTxmCgFLcimSXTa7fdiwfPn3NDGbgtq9ezYNZke++JaAbApqdzj75zrw+9rd3lrekeye1vsljmZ7+5snZL/1q2clJw3uwxnZXlGPWP3VX3PgNSh9f/HaeaeXzk+FEpzNAdl88dhSQPanjttWeafX7lZq/ZRovQPqSLanDyWo3ci70XqyvXeutbQbeVdez91onkrmmVOII3c1RV02I+8Ei2g36sc/SuOVo+WSfKS/EdOfw/2wnii7bFYpmaWZA7M8lyLZZbOvD0sUf/4z7XyJ68n++f88PfyDTw9H9WHWI0W17JFHXmqv+WnHzcymjj7Utj2yvpwC9u/yx+3uc2Al1DWddtxelfnw7DJjxI9Kt14pSuM7flY2B2TzxWO73XF7/12IM8qMtXeuEmpDCfWEsR2dSvVOu4ZuWbCMxtJaf9gkHcjNKM3WVgBqlzGl7/7+HhlfrfQ9ejdaOXqSysreKquUzNLMgVmeS5Hsstlv9wMroY5lW7+4KH1Pyr6vQiihHnsquTSMy1Pf4/v3n6w58FxK3yf7VkpWQo35M7Ol4xPzvd0SnM0B2Rw9tq1y+f7Fp4fPOHlr/SgdYysHxta7H3pOyIh2/a1kfmMK0fqJ0rrd3Uq5nh6O3Q8peP8Obywre6usUjJLMwdmeS5Fsstma6Xkb8scSqjPyC5/3Fp+nfKbI0+hRq0vp45s72MsOaC/V2eXP26z5sBKqGta/rjNWgfuyfrh7Pix/cxx2w68Iy95CvWiS5wfzt7f/rKnvi2j8egpxC2fQr355TCiXU9972xrPVF22axSMo+aQkCUsCU7lyLZM7Lhn8BKqOf39xdL31PN+kOHSqhj+yF1ju0ppe+wE9h8jKW/xK1WQj1D5GM3I9mIH5vOF49tyifwij/AfOYndk8JNqLNiDJ/CWr3tOOmlMxjphB+gPn4VErp+4Jpn3VK2TOyYXM7pWTO+h4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE/1H4IIqRgL4W2oAAAAAElFTkSuQmCC", } export type TemplateStyle = keyof typeof TemplateStyle; export const TemplateStyles = Object.keys(TemplateStyle); const STYLES_Y = 16; const STYLES_X = 16; export class Template extends EventEmitter<TemplateEvents> { static instance: Template; Loading @@ -41,7 +53,7 @@ export class Template extends EventEmitter<TemplateEvents> { options: ITemplateOptions = { enable: false, style: TemplateStyle.ONE_TO_ONE, style: "ONE_TO_ONE", }; constructor(config: ClientConfig, templateHolder: HTMLDivElement) { Loading @@ -67,7 +79,11 @@ export class Template extends EventEmitter<TemplateEvents> { this.$style = document.createElement("img"); this.$style.setAttribute("crossorigin", ""); this.$style.setAttribute("src", this.options!.style); this.$style.setAttribute("src", TemplateStyle[this.options!.style]); this.$style.addEventListener("load", () => { console.log("[Template] Style loaded"); this.loadStyle(); }); this.$canvas = document.createElement("canvas"); Loading Loading @@ -108,6 +124,18 @@ export class Template extends EventEmitter<TemplateEvents> { case "enable": this.setElementVisible([this.$canvas], !!value); break; case "style": if ((value as keyof typeof TemplateStyle) in TemplateStyle) { const key = value as keyof typeof TemplateStyle; this.$style.setAttribute("src", TemplateStyle[key]); this.$imageLoader.style.display = key === "SOURCE" ? "block" : "none"; if (key === "SOURCE") { this.stylizeTemplate(); } } break; } this.emit("option", key, value); Loading Loading @@ -208,15 +236,27 @@ export class Template extends EventEmitter<TemplateEvents> { width: this.$imageLoader.naturalWidth, height: this.$imageLoader.naturalHeight, }; let style = { width: this.$style.naturalWidth / STYLES_X, height: this.$style.naturalHeight / STYLES_Y, }; let aspectRatio = source.height / source.width; return { source, display: { let display = { width: Math.round(this.options?.width || source.width), height: Math.round((this.options?.width || source.width) * aspectRatio), }, }; let internal = { width: display.width * style.width, height: display.height * style.height, }; return { source, style, display, internal, aspectRatio, }; } Loading @@ -240,15 +280,14 @@ export class Template extends EventEmitter<TemplateEvents> { } = { downscaling: {} } as any; updateSize() { const { display: { width, height }, } = this.getDimentions(); const { display, internal } = this.getDimentions(); this.$wrapper.style.width = width + "px"; this.$imageLoader.style.width = width + "px"; this.$wrapper.style.width = display.width + "px"; this.$imageLoader.style.width = display.width + "px"; this.$canvas.style.width = display.width + "px"; this.$canvas.width = width; this.$canvas.height = height; this.$canvas.width = internal.width; this.$canvas.height = internal.height; } /** Loading @@ -261,8 +300,6 @@ export class Template extends EventEmitter<TemplateEvents> { const palette: { value: string }[] = this.config.pallete.colors.map( (color) => ({ value: color.hex }) ); const STYLES_Y = 16; const STYLES_X = 16; const context = this.$canvas.getContext("webgl", { premultipliedAlpha: true, Loading Loading @@ -589,11 +626,9 @@ export class Template extends EventEmitter<TemplateEvents> { stylizeTemplate() { this.updateSize(); const { display: { width, height }, } = this.getDimentions(); const { internal, display } = this.getDimentions(); if (this.context == null || width === 0 || height === 0) { if (this.context == null || internal.width === 0 || internal.height === 0) { return; } Loading @@ -602,14 +637,14 @@ export class Template extends EventEmitter<TemplateEvents> { this.framebuffers.main ); this.context.clear(this.context.COLOR_BUFFER_BIT); this.context.viewport(0, 0, width, height); this.context.viewport(0, 0, internal.width, internal.height); this.context.useProgram(this.programs.stylize); this.context.uniform2f( this.context.getUniformLocation(this.programs.stylize, "u_TexelSize"), 1 / width, 1 / height 1 / display.width, 1 / display.height ); this.context.activeTexture(this.context.TEXTURE0); Loading