232 lines
6.8 KiB
TypeScript
232 lines
6.8 KiB
TypeScript
/**
|
|
* @fileoverview
|
|
* 调试 MG 渲染器的测试脚本
|
|
*
|
|
* @author SteveXMH
|
|
*/
|
|
import GUI from "lil-gui";
|
|
import Stats from "stats.js";
|
|
import { MeshGradientRenderer } from "./bg-render";
|
|
|
|
const debugValues = {
|
|
controlPointSize: 4,
|
|
subdivideDepth: 15,
|
|
wireFrame: false,
|
|
};
|
|
|
|
const canvas = document.getElementById("bg")! as HTMLCanvasElement;
|
|
const mgRenderer = new MeshGradientRenderer(canvas);
|
|
// mgRenderer.setAlbum("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAADUExURf///6fEG8gAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAKSURBVBjTY2AAAAACAAGYY2zXAAAAAElFTkSuQmCC");
|
|
mgRenderer.setManualControl(true);
|
|
mgRenderer.setFPS(Number.POSITIVE_INFINITY);
|
|
|
|
function updateControlPointDraggers() {
|
|
for (const el of document.querySelectorAll(".dragger")) {
|
|
const x = Number.parseInt(el.getAttribute("x") ?? "");
|
|
const y = Number.parseInt(el.getAttribute("y") ?? "");
|
|
const point = mgRenderer.getControlPoint(x, y);
|
|
if (point === undefined) return;
|
|
(el as HTMLElement).style.left = `${(point.location.x + 1) * 50}%`;
|
|
(el as HTMLElement).style.top = `${(1 - point.location.y) * 50}%`;
|
|
}
|
|
}
|
|
|
|
let draggerGui: GUI | undefined;
|
|
function setActiveDragger(x: number, y: number) {
|
|
if (draggerGui) {
|
|
draggerGui.destroy();
|
|
draggerGui = undefined;
|
|
}
|
|
const point = mgRenderer.getControlPoint(x, y);
|
|
if (point) {
|
|
draggerGui = gui.addFolder(`控制点 (${x}, ${y})`);
|
|
const obj = {
|
|
uAngle: point.uRot,
|
|
vAngle: point.vRot,
|
|
uScale: point.uScale,
|
|
vScale: point.vScale,
|
|
};
|
|
draggerGui
|
|
.add(obj, "uAngle", -180, 180)
|
|
.name("横向扭曲角度")
|
|
.onChange((v: number) => {
|
|
point.uRot = (v * Math.PI) / 180;
|
|
updateResult();
|
|
});
|
|
draggerGui
|
|
.add(obj, "vAngle", -180, 180)
|
|
.name("纵向扭曲角度")
|
|
.onChange((v: number) => {
|
|
point.vRot = (v * Math.PI) / 180;
|
|
updateResult();
|
|
});
|
|
draggerGui
|
|
.add(obj, "uScale", 0.1, 10)
|
|
.name("横向缩放")
|
|
.onChange((v: number) => {
|
|
point.uScale = v;
|
|
updateResult();
|
|
});
|
|
draggerGui
|
|
.add(obj, "vScale", 0.1, 10)
|
|
.name("纵向缩放")
|
|
.onChange((v: number) => {
|
|
point.vScale = v;
|
|
updateResult();
|
|
});
|
|
}
|
|
}
|
|
|
|
window.addEventListener("resize", updateControlPointDraggers);
|
|
|
|
const resultTextArea = document.getElementById(
|
|
"result",
|
|
)! as HTMLTextAreaElement;
|
|
resultTextArea.value = "// 控制点的设置代码将会在这里显示";
|
|
function updateResult() {
|
|
const result = [
|
|
`preset(${debugValues.controlPointSize}, ${debugValues.controlPointSize}, [`,
|
|
];
|
|
for (let y = 0; y < debugValues.controlPointSize; y++) {
|
|
for (let x = 0; x < debugValues.controlPointSize; x++) {
|
|
const point = mgRenderer.getControlPoint(x, y);
|
|
if (point === undefined) continue;
|
|
result.push(
|
|
` p(${x}, ${y}, ${point.location.x}, ${point.location.y}, ${point.uRot}, ${point.vRot}, ${point.uScale}, ${point.vScale}),`,
|
|
);
|
|
}
|
|
}
|
|
result.push("]),");
|
|
resultTextArea.value = result.join("\n");
|
|
}
|
|
|
|
function resizeControlPoint() {
|
|
document
|
|
.querySelectorAll(".dragger")
|
|
.forEach((el) => el.parentElement?.removeChild(el));
|
|
mgRenderer.resizeControlPoints(
|
|
debugValues.controlPointSize,
|
|
debugValues.controlPointSize,
|
|
);
|
|
mgRenderer.resetSubdivition(debugValues.subdivideDepth);
|
|
|
|
for (let y = 0; y < debugValues.controlPointSize; y++) {
|
|
for (let x = 0; x < debugValues.controlPointSize; x++) {
|
|
const point = mgRenderer.getControlPoint(x, y);
|
|
if (point === undefined) continue;
|
|
const dragger = document.createElement("div");
|
|
const draggerInput = document.createElement("input");
|
|
draggerInput.type = "color";
|
|
draggerInput.style.position = "absolute";
|
|
draggerInput.style.visibility = "hidden";
|
|
dragger.appendChild(draggerInput);
|
|
dragger.setAttribute("x", `${x}`);
|
|
dragger.setAttribute("y", `${y}`);
|
|
dragger.className = "dragger";
|
|
dragger.style.left = `${(x * 100) / (debugValues.controlPointSize - 1)}%`;
|
|
dragger.style.top = `${
|
|
((debugValues.controlPointSize - y - 1) * 100) /
|
|
(debugValues.controlPointSize - 1)
|
|
}%`;
|
|
draggerInput.addEventListener("input", () => {
|
|
// mgRenderer.getControlPoint(x, y).color = dragger.value;
|
|
const c = draggerInput.value;
|
|
console.log(c);
|
|
dragger.style.backgroundColor = c;
|
|
const color = c.match(/#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/i);
|
|
if (color) {
|
|
point.color.r = Number.parseInt(color[1], 16) / 255;
|
|
point.color.g = Number.parseInt(color[2], 16) / 255;
|
|
point.color.b = Number.parseInt(color[3], 16) / 255;
|
|
dragger.setAttribute("r", `${point.color.r}`);
|
|
dragger.setAttribute("g", `${point.color.g}`);
|
|
dragger.setAttribute("b", `${point.color.b}`);
|
|
updateResult();
|
|
}
|
|
});
|
|
let dragging = false;
|
|
dragger.addEventListener("mousedown", (evt) => {
|
|
evt.stopPropagation();
|
|
function onMouseMove(evt: MouseEvent) {
|
|
dragger.style.left = `${Math.min(
|
|
window.innerWidth,
|
|
Math.max(0, evt.clientX),
|
|
)}px`;
|
|
dragger.style.top = `${Math.min(
|
|
window.innerHeight,
|
|
Math.max(0, evt.clientY),
|
|
)}px`;
|
|
if (point) {
|
|
point.location.x = Math.max(
|
|
-1,
|
|
Math.min(1, (evt.clientX / window.innerWidth) * 2 - 1),
|
|
);
|
|
point.location.y = Math.max(
|
|
-1,
|
|
Math.min(1, -((evt.clientY / window.innerHeight) * 2 - 1)),
|
|
);
|
|
}
|
|
dragging = true;
|
|
updateResult();
|
|
evt.stopPropagation();
|
|
}
|
|
function onMouseUp(evt: MouseEvent) {
|
|
if (dragging) {
|
|
dragging = false;
|
|
} else if (dragger.classList.contains("active")) {
|
|
draggerInput.click();
|
|
} else {
|
|
for (const el of document.querySelectorAll(".dragger.active")) {
|
|
el.classList.remove("active");
|
|
}
|
|
dragger.classList.add("active");
|
|
setActiveDragger(x, y);
|
|
}
|
|
window.removeEventListener("mousemove", onMouseMove);
|
|
window.removeEventListener("mouseup", onMouseUp);
|
|
evt.stopPropagation();
|
|
}
|
|
window.addEventListener("mousemove", onMouseMove);
|
|
window.addEventListener("mouseup", onMouseUp);
|
|
});
|
|
document.body.appendChild(dragger);
|
|
}
|
|
}
|
|
}
|
|
|
|
function subdivide() {
|
|
mgRenderer.resetSubdivition(debugValues.subdivideDepth);
|
|
}
|
|
|
|
mgRenderer.setAlbum("bigsur.png").then(() => {
|
|
resizeControlPoint();
|
|
subdivide();
|
|
});
|
|
|
|
const gui = new GUI();
|
|
gui.close();
|
|
gui.title("MG Renderer 调试页面");
|
|
gui
|
|
.add(debugValues, "controlPointSize", 3, 10, 1)
|
|
.name("控制点矩阵大小")
|
|
.onFinishChange(resizeControlPoint);
|
|
gui
|
|
.add(debugValues, "subdivideDepth", 2, 50, 1)
|
|
.name("细分深度")
|
|
.onChange(subdivide);
|
|
gui
|
|
.add(debugValues, "wireFrame")
|
|
.name("线框模式")
|
|
.onChange((v: boolean) => mgRenderer.setWireFrame(v));
|
|
|
|
const stats = new Stats();
|
|
stats.showPanel(0);
|
|
stats.dom.style.left = "50px";
|
|
document.body.appendChild(stats.dom);
|
|
const frame = () => {
|
|
stats.end();
|
|
stats.begin();
|
|
requestAnimationFrame(frame);
|
|
};
|
|
requestAnimationFrame(frame);
|