Pixel pick on template (fixes #70)
This commit is contained in:
parent
924815e629
commit
46214c56cf
|
@ -7,10 +7,12 @@ import { ViewportMoveEvent } from "@sc07-canvas/lib/src/renderer/PanZoom";
|
|||
import throttle from "lodash.throttle";
|
||||
import { IPosition } from "@sc07-canvas/lib/src/net";
|
||||
import { Template } from "./Templating/Template";
|
||||
import { Template as TemplateCl } from "../lib/template";
|
||||
import { IRouterData, Router } from "../lib/router";
|
||||
import { KeybindManager } from "../lib/keybinds";
|
||||
import { BlankOverlay } from "./Overlay/BlankOverlay";
|
||||
import { HeatmapOverlay } from "./Overlay/HeatmapOverlay";
|
||||
import { useTemplateContext } from "../contexts/TemplateContext";
|
||||
|
||||
export const CanvasWrapper = () => {
|
||||
const { config } = useAppContext();
|
||||
|
@ -65,6 +67,11 @@ const CanvasInner = () => {
|
|||
const canvas = useRef<Canvas>();
|
||||
const { config, setCanvasPosition, setCursor, setPixelWhois } =
|
||||
useAppContext();
|
||||
const {
|
||||
x: templateX,
|
||||
y: templateY,
|
||||
enable: templateEnable,
|
||||
} = useTemplateContext();
|
||||
const PanZoom = useContext(RendererContext);
|
||||
|
||||
/**
|
||||
|
@ -129,6 +136,19 @@ const CanvasInner = () => {
|
|||
[canvas.current]
|
||||
);
|
||||
|
||||
const getTemplatePixel = useCallback(
|
||||
(x: number, y: number) => {
|
||||
if (!templateEnable) return;
|
||||
if (x < templateX || y < templateY) return;
|
||||
|
||||
x -= templateX;
|
||||
y -= templateY;
|
||||
|
||||
return TemplateCl.instance.getPixel(x, y);
|
||||
},
|
||||
[templateX, templateY]
|
||||
);
|
||||
|
||||
const handlePickPixel = useCallback(
|
||||
({ clientX, clientY }: { clientX: number; clientY: number }) => {
|
||||
if (!canvas.current) {
|
||||
|
@ -141,13 +161,27 @@ const CanvasInner = () => {
|
|||
const [x, y] = canvas.current.screenToPos(clientX, clientY);
|
||||
if (!isCoordInCanvas(x, y)) return; // out of bounds
|
||||
|
||||
const pixel = canvas.current.getPixel(x, y);
|
||||
if (!pixel) return;
|
||||
let pixelColor = -1;
|
||||
|
||||
const templatePixel = getTemplatePixel(x, y);
|
||||
if (templatePixel) {
|
||||
pixelColor =
|
||||
canvas.current.Pallete.getColorFromHex(templatePixel.slice(1))?.id ||
|
||||
-1;
|
||||
}
|
||||
|
||||
if (pixelColor === -1) {
|
||||
pixelColor = canvas.current.getPixel(x, y)?.color || -1;
|
||||
}
|
||||
|
||||
if (pixelColor === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// no need to use canvas#setCursor as Palette.tsx already does that
|
||||
setCursor((v) => ({
|
||||
...v,
|
||||
color: pixel.color,
|
||||
color: pixelColor,
|
||||
}));
|
||||
},
|
||||
[canvas.current]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import EventEmitter from "eventemitter3";
|
||||
import { WebGLUtils } from "./webgl";
|
||||
import { ClientConfig } from "@sc07-canvas/lib/src/net";
|
||||
import { rgbToHex } from "./utils";
|
||||
|
||||
interface TemplateEvents {
|
||||
updateImageURL(url: string | undefined): void;
|
||||
|
@ -28,6 +29,8 @@ enum TemplateStyle {
|
|||
}
|
||||
|
||||
export class Template extends EventEmitter<TemplateEvents> {
|
||||
static instance: Template;
|
||||
|
||||
config: ClientConfig;
|
||||
|
||||
$wrapper: HTMLDivElement;
|
||||
|
@ -43,9 +46,10 @@ export class Template extends EventEmitter<TemplateEvents> {
|
|||
|
||||
constructor(config: ClientConfig, templateHolder: HTMLDivElement) {
|
||||
super();
|
||||
Template.instance = this;
|
||||
this.config = config;
|
||||
|
||||
console.log("template init", config, templateHolder);
|
||||
console.log("[Template] Initialize", config, templateHolder);
|
||||
|
||||
this.$wrapper = templateHolder;
|
||||
|
||||
|
@ -53,7 +57,7 @@ export class Template extends EventEmitter<TemplateEvents> {
|
|||
this.$imageLoader.style.setProperty("display", "none");
|
||||
this.$imageLoader.setAttribute("crossorigin", "");
|
||||
this.$imageLoader.addEventListener("load", () => {
|
||||
console.log("imageLoader loaded image");
|
||||
console.log("[Template] Image loaded");
|
||||
if (!this.options.width) {
|
||||
this.setOption("width", this.$imageLoader.naturalWidth);
|
||||
this.emit("autoDetectWidth", this.$imageLoader.naturalWidth);
|
||||
|
@ -115,6 +119,57 @@ 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 width = this.context.drawingBufferWidth;
|
||||
const height = this.context.drawingBufferHeight;
|
||||
|
||||
const arr = new Uint8Array(4 * width * height);
|
||||
this.context.bindFramebuffer(
|
||||
this.context.FRAMEBUFFER,
|
||||
this.framebuffers.intermediate
|
||||
);
|
||||
|
||||
if (x < 0 || y < 0 || x > width || y > height) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
this.context.readPixels(
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
height,
|
||||
this.context.RGBA,
|
||||
this.context.UNSIGNED_BYTE,
|
||||
arr
|
||||
);
|
||||
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 * this.context.drawingBufferWidth + x),
|
||||
4 * (y * this.context.drawingBufferWidth + x) + 4
|
||||
);
|
||||
|
||||
if (a === 254) return undefined;
|
||||
|
||||
return rgbToHex(r, g, b);
|
||||
}
|
||||
|
||||
rasterizeTemplate() {
|
||||
this.downscaleTemplate();
|
||||
this.stylizeTemplate();
|
||||
|
|
|
@ -17,6 +17,20 @@ export const getRenderer = (): Renderer => {
|
|||
|
||||
Debug._getRenderer = getRenderer;
|
||||
|
||||
export const rgbToHex = (r: number, g: number, b: number) => {
|
||||
function componentToHex(c: number) {
|
||||
var hex = c.toString(16);
|
||||
return hex.length == 1 ? "0" + hex : hex;
|
||||
}
|
||||
|
||||
return (
|
||||
"#" +
|
||||
componentToHex(r) +
|
||||
componentToHex(g) +
|
||||
componentToHex(b)
|
||||
).toUpperCase();
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const api = async <T = unknown, Error = string>(
|
||||
endpoint: string,
|
||||
|
|
Loading…
Reference in New Issue