Commit 001d239e authored by Grant's avatar Grant
Browse files

disable templating if webgl is not available

parent eb20db1e
Loading
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
import { useTemplateContext } from "../../contexts/TemplateContext";
import { Input, Select, SelectItem, Slider } from "@heroui/react";
import { Alert, Input, Select, SelectItem, Slider } from "@heroui/react";
import { Switch } from "../core/Switch";
import { Button } from "../core/Button";
import { toast } from "react-toastify";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faLink } from "@fortawesome/free-solid-svg-icons";
import { WebGLUtils } from "@/lib/webgl";

export const TemplateSettings = () => {
  const {
@@ -29,6 +30,13 @@ export const TemplateSettings = () => {
  return (
    <div className="flex flex-col p-2">
      <header className="flex flex-col gap-2">
        {!WebGLUtils.detectWebGL() && (
          <Alert color="warning">
            <strong>WebGL is not available</strong>
            <br />
            <span>Templating uses WebGL</span>
          </Alert>
        )}
        <div className="flex items-center gap-2">
          <Switch
            isSelected={enable || false}
+11 −6
Original line number Diff line number Diff line
@@ -3,8 +3,12 @@ import { Template as TemplateCl } from "../../lib/template";
import { useAppContext } from "../../contexts/AppContext";
import { useTemplateContext } from "../../contexts/TemplateContext";
import { CanvasCore } from "../../lib/canvas";
import { WebGLUtils } from "@/lib/webgl";

export const Template = () => {
export const Template = () =>
  WebGLUtils.detectWebGL() ? $Template : undefined;

const $Template = () => {
  const { config } = useAppContext();
  const { enable, url, width, setWidth, x, y, opacity, setX, setY, style } =
    useTemplateContext();
@@ -40,7 +44,7 @@ export const Template = () => {
      if (!startLocation) return;
      if (!CanvasCore.instance) {
        console.warn(
          "[Template#handleMouseMove] Canvas.instance is not defined"
          "[Template#handleMouseMove] Canvas.instance is not defined",
        );
        return;
      }
@@ -62,10 +66,11 @@ export const Template = () => {

      const x = parseInt(
        templateHolderRef.style.getPropertyValue("left").replace("px", "") ||
          "0"
          "0",
      );
      const y = parseInt(
        templateHolderRef.style.getPropertyValue("top").replace("px", "") || "0"
        templateHolderRef.style.getPropertyValue("top").replace("px", "") ||
          "0",
      );

      setX(x);
@@ -88,7 +93,7 @@ export const Template = () => {
  useEffect(() => {
    if (!instance.current) {
      console.warn(
        "[Template] Received template enable but no instance exists"
        "[Template] Received template enable but no instance exists",
      );
      return;
    }
@@ -105,7 +110,7 @@ export const Template = () => {
  useEffect(() => {
    if (!instance.current) {
      console.warn(
        "[Template] Recieved template url update but no template instance exists"
        "[Template] Recieved template url update but no template instance exists",
      );
      return;
    }
+5 −4
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ import {
import { type IRouterData, Router } from "../lib/router";
import { KeybindManager } from "../lib/keybinds";
import { type TemplateStyle } from "../lib/template";
import { WebGLUtils } from "@/lib/webgl";

interface ITemplate {
  /**
@@ -54,13 +55,13 @@ export const TemplateContext = ({ children }: PropsWithChildren) => {
  const [enable, setEnable] = useState(!!routerData.template?.url);
  const [url, setURL] = useState<string | undefined>(routerData.template?.url);
  const [width, setWidth] = useState<number | undefined>(
    routerData.template?.width
    routerData.template?.width,
  );
  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"
    routerData.template?.style || "ONE_TO_ONE",
  );
  const [showMobileTools, setShowMobileTools] = useState(true);

@@ -103,7 +104,7 @@ export const TemplateContext = ({ children }: PropsWithChildren) => {
    } else if (Date.now() - initAt.current < 2 * 1000) {
      console.debug(
        "TemplateContext updating router too soon after init",
        Date.now() - initAt.current
        Date.now() - initAt.current,
      );
    }

@@ -114,7 +115,7 @@ export const TemplateContext = ({ children }: PropsWithChildren) => {
  return (
    <templateContext.Provider
      value={{
        enable,
        enable: WebGLUtils.detectWebGL() && enable,
        setEnable,
        url,
        setURL,
+21 −8
Original line number Diff line number Diff line
let hasWebGL: boolean | null = null;

/**
 * Utilities for WebGL contexts
 */
@@ -8,6 +10,17 @@ export class WebGLUtils {
    this.context = context;
  }

  static detectWebGL() {
    if (typeof hasWebGL !== "boolean") {
      const canvas = document.createElement("canvas");
      const gl = canvas.getContext("webgl");

      hasWebGL = gl instanceof WebGLRenderingContext;
    }

    return hasWebGL;
  }

  /**
   * Create WebGL texture
   *
@@ -21,22 +34,22 @@ export class WebGLUtils {
    this.context.texParameteri(
      this.context.TEXTURE_2D,
      this.context.TEXTURE_WRAP_S,
      this.context.CLAMP_TO_EDGE
      this.context.CLAMP_TO_EDGE,
    );
    this.context.texParameteri(
      this.context.TEXTURE_2D,
      this.context.TEXTURE_WRAP_T,
      this.context.CLAMP_TO_EDGE
      this.context.CLAMP_TO_EDGE,
    );
    this.context.texParameteri(
      this.context.TEXTURE_2D,
      this.context.TEXTURE_MIN_FILTER,
      this.context.NEAREST
      this.context.NEAREST,
    );
    this.context.texParameteri(
      this.context.TEXTURE_2D,
      this.context.TEXTURE_MAG_FILTER,
      this.context.NEAREST
      this.context.NEAREST,
    );
    return texture;
  }
@@ -56,16 +69,16 @@ export class WebGLUtils {
    const program = this.context.createProgram()!;
    this.context.attachShader(
      program,
      this.createShader(this.context.VERTEX_SHADER, vertexSource)
      this.createShader(this.context.VERTEX_SHADER, vertexSource),
    );
    this.context.attachShader(
      program,
      this.createShader(this.context.FRAGMENT_SHADER, fragmentSource)
      this.createShader(this.context.FRAGMENT_SHADER, fragmentSource),
    );
    this.context.linkProgram(program);
    if (!this.context.getProgramParameter(program, this.context.LINK_STATUS)) {
      throw new Error(
        `Failed to link WebGL template program:\n\n${this.context.getProgramInfoLog(program)}`
        `Failed to link WebGL template program:\n\n${this.context.getProgramInfoLog(program)}`,
      );
    }
    return program;
@@ -90,7 +103,7 @@ export class WebGLUtils {

    if (!this.context.getShaderParameter(shader, this.context.COMPILE_STATUS)) {
      throw new Error(
        `Failed to compile WebGL template shader:\n\n${this.context.getShaderInfoLog(shader)}`
        `Failed to compile WebGL template shader:\n\n${this.context.getShaderInfoLog(shader)}`,
      );
    }