Commit b06f9f22 authored by Ategon's avatar Ategon Committed by Grant
Browse files

Fix color picking from template

parent 3f9dc430
Loading
Loading
Loading
Loading
Loading
+10 −23
Original line number Diff line number Diff line
@@ -273,11 +273,7 @@ const CanvasInner = () => {
  const { config, blankOverlay, setCanvasPosition, setCursorPos } =
    useAppContext();
  const Panel = usePanel();
  const {
    x: templateX,
    y: templateY,
    enable: templateEnable,
  } = useTemplateContext();
  const { enable: templateEnable } = useTemplateContext();
  const PanZoom = useContext(RendererContext);
  const { captureCanvas, captureView, captureRegion, captureTemplateArea } =
    useCaptureContext();
@@ -475,17 +471,12 @@ const CanvasInner = () => {
    [canvas.current],
  );

  const getTemplatePixel = useCallback(
    (x: number, y: number) => {
  const getTemplatePixelColor = useCallback(
    (clientX: number, clientY: number) => {
      if (!templateEnable) return;
      if (x < templateX || y < templateY) return;

      x -= templateX;
      y -= templateY;

      return TemplateCl.instance.getPixel(x, y);
      return TemplateCl.instance?.getPaletteColorAt(clientX, clientY);
    },
    [templateX, templateY],
    [templateEnable],
  );

  const handlePickPixel = useCallback(
@@ -498,19 +489,15 @@ const CanvasInner = () => {
      }

      const [x, y] = canvas.current.screenToPos(clientX, clientY);
      if (!isCoordInCanvas(x, y)) {
      const templateColor = getTemplatePixelColor(clientX, clientY);

      if (templateColor === undefined && !isCoordInCanvas(x, y)) {
        PaletteLib.setSelectedColor(undefined);
        showColorDeselectFeedback(clientX, clientY);
        return;
      }

      let pixelColor = -1;

      const templatePixel = getTemplatePixel(x, y);
      if (templatePixel) {
        pixelColor =
          PaletteLib.getColorFromHex(templatePixel.slice(1))?.id ?? -1;
      }
      let pixelColor = templateColor ?? -1;

      if (pixelColor === -1) {
        pixelColor = canvas.current.getPixel(x, y)?.color ?? -1;
@@ -529,7 +516,7 @@ const CanvasInner = () => {
        PaletteLib.getColor(pixelColor)?.hex,
      );
    },
    [canvas.current],
    [getTemplatePixelColor, isCoordInCanvas],
  );

  useEffect(() => {
+0 −7
Original line number Diff line number Diff line
@@ -121,13 +121,6 @@ export const TemplateSettings = () => {
            <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}
+6 −16
Original line number Diff line number Diff line
@@ -337,24 +337,14 @@ export const Palette = () => {
    x < config.canvas.size[0] &&
    y < config.canvas.size[1];

  const getTemplatePixelColor = (x: number, y: number) => {
  const getTemplatePixelColor = (clientX: number, clientY: number) => {
    const renderer = TemplateRenderer.instance;

    if (
      !template.enable ||
      !renderer ||
      template.x === undefined ||
      template.y === undefined ||
      x < template.x ||
      y < template.y
    ) {
    if (!template.enable || !renderer) {
      return -1;
    }

    const templatePixel = renderer.getPixel(x - template.x, y - template.y);
    if (!templatePixel) return -1;

    return PaletteLib.getColorFromHex(templatePixel.slice(1))?.id ?? -1;
    return renderer.getPaletteColorAt(clientX, clientY) ?? -1;
  };

  const getPickedColor = (clientX: number, clientY: number) => {
@@ -378,11 +368,11 @@ export const Palette = () => {
      return;
    }

    if (!isCoordInCanvas(x, y)) return null;

    const templateColor = getTemplatePixelColor(x, y);
    const templateColor = getTemplatePixelColor(clientX, clientY);
    if (templateColor !== -1) return templateColor;

    if (!isCoordInCanvas(x, y)) return null;

    const canvasColor = canvas.getPixel(x, y)?.color;
    if (canvasColor !== undefined && canvasColor >= 0) return canvasColor;

+19 −49
Original line number Diff line number Diff line
import { type ClientConfig } from "@sc07-canvas/lib/net";
import EventEmitter from "eventemitter3";

import { rgbToHex } from "./utils";
import { WebGLUtils } from "./webgl";

export interface ITemplateState {
@@ -196,65 +195,36 @@ export class Template extends EventEmitter<TemplateEvents> {
    }
  }

  getPixel(x: number, y: number): string | undefined {
    if (!this.context) {
      console.warn("[Template#getPixel] No context is available");
      return undefined;
    }

    const {
      display: { width, height },
    } = this.getDimentions();
  getPaletteColorAt(clientX: number, clientY: number): number | undefined {
    if (!this.palettePixels) this.updatePaletteColorCounts();
    const templatePixels = this.palettePixels;
    if (!templatePixels) return undefined;

    const rect = this.$wrapper.getBoundingClientRect();
    const width = rect.width;
    const height = width * (templatePixels.height / templatePixels.width);
    if (
      !Number.isFinite(width) ||
      !Number.isFinite(height) ||
      width <= 0 ||
      height <= 0 ||
      x < 0 ||
      y < 0 ||
      x >= width ||
      y >= height
      clientX < rect.left ||
      clientX >= rect.left + width ||
      clientY < rect.top ||
      clientY >= rect.top + height
    ) {
      return undefined;
    }

    const arr = new Uint8Array(4 * width * height);
    this.context.bindFramebuffer(
      this.context.FRAMEBUFFER,
      this.framebuffers.intermediate,
    const pixelX = Math.floor(
      ((clientX - rect.left) / width) * templatePixels.width,
    );

    this.context.readPixels(
      0,
      0,
      width,
      height,
      this.context.RGBA,
      this.context.UNSIGNED_BYTE,
      arr,
    const pixelY = Math.floor(
      ((clientY - rect.top) / height) * templatePixels.height,
    );
    this.context.bindFramebuffer(
      this.context.FRAMEBUFFER,
      this.framebuffers.main,
    );

    const pixels = new Uint8Array(4 * width * height);
    const length = width * height * 4;
    const row = width * 4;
    const end = (height - 1) * row;
    for (let i = 0; i < length; i += row) {
      pixels.set(arr.subarray(i, i + row), end - i);
    }

    const [r, g, b, a] = pixels.slice(
      4 * (y * width + x),
      4 * (y * width + x) + 4,
    );

    if (a === 254) return undefined;
    const paletteIndex =
      templatePixels.indexes[pixelY * templatePixels.width + pixelX];
    if (paletteIndex === 254 || paletteIndex === 255) return undefined;

    return rgbToHex(r, g, b);
    return this.config.pallete.colors[paletteIndex]?.id;
  }

  getPaletteColorCounts() {
+0 −14
Original line number Diff line number Diff line
@@ -21,20 +21,6 @@ export const getRenderer = (): Renderer => {

Debug._getRenderer = getRenderer;

export const rgbToHex = (r: number, g: number, b: number) => {
  function componentToHex(c: number) {
    const hex = c.toString(16);
    return hex.length === 1 ? "0" + hex : hex;
  }

  return (
    "#" +
    componentToHex(r) +
    componentToHex(g) +
    componentToHex(b)
  ).toUpperCase();
};

export const oapi = createClient<RestAPI.paths>({
  baseUrl: new URL("/api", window.location.origin).toString(),
});