|
|
@@ -1,15 +1,10 @@
|
|
|
-import { fillRectangle } from "../base/2d"
|
|
|
-import { LayerAB, Scene } from "../base/Scene"
|
|
|
-import { createProgram, createShader } from "../base/utils"
|
|
|
+import { fillRectangle } from "../base/2d";
|
|
|
+import { LayerAB, Scene } from "../base/Scene";
|
|
|
+import { createProgram, createShader } from "../base/utils";
|
|
|
import { Center, createTexture, TexImage } from "./common";
|
|
|
import { FillerData } from "./FillerData";
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
export class NumberLayer extends LayerAB {
|
|
|
-
|
|
|
-
|
|
|
private vertexShaderCode = /*glsl*/ `
|
|
|
attribute vec2 a_position;
|
|
|
attribute vec2 a_texCoord;
|
|
|
@@ -33,36 +28,33 @@ export class NumberLayer extends LayerAB {
|
|
|
gl_FragColor = color;
|
|
|
}
|
|
|
|
|
|
- `
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- program: WebGLProgram
|
|
|
+ `;
|
|
|
|
|
|
+ program: WebGLProgram;
|
|
|
|
|
|
- aPositionLoc: number
|
|
|
- aTexcoordLoc: number
|
|
|
- uMatrixLoc: WebGLUniformLocation
|
|
|
- uScaleLoc: WebGLUniformLocation
|
|
|
- uTexSizeLoc: WebGLUniformLocation
|
|
|
+ aPositionLoc: number;
|
|
|
+ aTexcoordLoc: number;
|
|
|
+ uMatrixLoc: WebGLUniformLocation;
|
|
|
+ uScaleLoc: WebGLUniformLocation;
|
|
|
+ uTexSizeLoc: WebGLUniformLocation;
|
|
|
|
|
|
- vertexBuffer: WebGLBuffer
|
|
|
- texcoordBuffer: WebGLBuffer
|
|
|
+ vertexBuffer: WebGLBuffer;
|
|
|
+ texcoordBuffer: WebGLBuffer;
|
|
|
|
|
|
- vertexArray: Float32Array
|
|
|
- texCoordArray: Float32Array
|
|
|
+ vertexArray: Float32Array;
|
|
|
+ texCoordArray: Float32Array;
|
|
|
|
|
|
- texture: WebGLTexture
|
|
|
+ texture: WebGLTexture;
|
|
|
|
|
|
- digits: number
|
|
|
- centers: Array<Center>
|
|
|
+ digits: number;
|
|
|
+ centers: Array<Center>;
|
|
|
|
|
|
dispose() {
|
|
|
- let gl = this.scene.gl
|
|
|
- gl.deleteProgram(this.program)
|
|
|
- gl.deleteBuffer(this.vertexBuffer)
|
|
|
- gl.deleteBuffer(this.texcoordBuffer)
|
|
|
- gl.deleteTexture(this.texture)
|
|
|
+ let gl = this.scene.gl;
|
|
|
+ gl.deleteProgram(this.program);
|
|
|
+ gl.deleteBuffer(this.vertexBuffer);
|
|
|
+ gl.deleteBuffer(this.texcoordBuffer);
|
|
|
+ gl.deleteTexture(this.texture);
|
|
|
}
|
|
|
|
|
|
constructor(
|
|
|
@@ -71,185 +63,183 @@ export class NumberLayer extends LayerAB {
|
|
|
private fillerData: FillerData,
|
|
|
private bestFitScale: number,
|
|
|
) {
|
|
|
- super()
|
|
|
+ super();
|
|
|
|
|
|
const gl = scene.gl;
|
|
|
|
|
|
-
|
|
|
- this.program = createProgram(gl,
|
|
|
+ this.program = createProgram(
|
|
|
+ gl,
|
|
|
createShader(gl, gl.VERTEX_SHADER, this.vertexShaderCode)!,
|
|
|
- createShader(gl, gl.FRAGMENT_SHADER, this.fragmentShaderCode)!)!
|
|
|
+ createShader(gl, gl.FRAGMENT_SHADER, this.fragmentShaderCode)!,
|
|
|
+ )!;
|
|
|
|
|
|
- this.aPositionLoc = gl.getAttribLocation(this.program, "a_position")
|
|
|
- this.aTexcoordLoc = gl.getAttribLocation(this.program, "a_texCoord")
|
|
|
- this.uMatrixLoc = gl.getUniformLocation(this.program, "u_matrix")!
|
|
|
- this.uScaleLoc = gl.getUniformLocation(this.program, "u_scale")!
|
|
|
- this.uTexSizeLoc = gl.getUniformLocation(this.program, "u_texSize")!
|
|
|
+ this.aPositionLoc = gl.getAttribLocation(this.program, "a_position");
|
|
|
+ this.aTexcoordLoc = gl.getAttribLocation(this.program, "a_texCoord");
|
|
|
+ this.uMatrixLoc = gl.getUniformLocation(this.program, "u_matrix")!;
|
|
|
+ this.uScaleLoc = gl.getUniformLocation(this.program, "u_scale")!;
|
|
|
+ this.uTexSizeLoc = gl.getUniformLocation(this.program, "u_texSize")!;
|
|
|
|
|
|
+ this.texture = createTexture(gl, image, gl.LINEAR);
|
|
|
|
|
|
- this.texture = createTexture(gl, image, gl.LINEAR)
|
|
|
-
|
|
|
-
|
|
|
- const centers: Array<Center> = []
|
|
|
- const ratio = image.width / 10. / image.height
|
|
|
- const textHeightRatio = Array(4)
|
|
|
+ const centers: Array<Center> = [];
|
|
|
+ const ratio = image.width / 10 / image.height;
|
|
|
+ const textHeightRatio = Array(4);
|
|
|
for (var i = 0; i < 4; i++) {
|
|
|
- textHeightRatio[i] = 2. / Math.sqrt(i * i * ratio * ratio + 1)
|
|
|
+ textHeightRatio[i] = 2 / Math.sqrt(i * i * ratio * ratio + 1);
|
|
|
}
|
|
|
|
|
|
+ const magnify = 1.2;
|
|
|
+ const minify = 0.8;
|
|
|
+ var digits = 0;
|
|
|
|
|
|
- const magnify = 1.2
|
|
|
- const minify = 0.8
|
|
|
- var digits = 0
|
|
|
-
|
|
|
-
|
|
|
- const config = fillerData.config
|
|
|
+ const config = fillerData.config;
|
|
|
|
|
|
//const maxScale = fillerData.config.maxScale
|
|
|
|
|
|
- const areaGroups = fillerData.data.areaGroups
|
|
|
-
|
|
|
+ const areaGroups = fillerData.data.areaGroups;
|
|
|
|
|
|
for (var i = 0; i < areaGroups.length; i++) {
|
|
|
- var group = areaGroups[i]
|
|
|
+ var group = areaGroups[i];
|
|
|
for (var j = 0; j < group.areas.length; j++) {
|
|
|
- var area = group.areas[j]
|
|
|
+ var area = group.areas[j];
|
|
|
|
|
|
// 剪枝, 如果已经上色,直接跳过
|
|
|
- if (area.colored) continue
|
|
|
+ if (area.colored) continue;
|
|
|
|
|
|
- digits += area.center.label!.length
|
|
|
- centers.push(area.center)
|
|
|
- var fontHeight = area.center.radius * textHeightRatio[area.center.label!.length]
|
|
|
+ digits += area.center.label!.length;
|
|
|
+ centers.push(area.center);
|
|
|
+ var fontHeight =
|
|
|
+ area.center.radius * textHeightRatio[area.center.label!.length];
|
|
|
|
|
|
// 让文字大小线性放大或者缩小
|
|
|
- var k = (fontHeight * config.maxScale) / config.visibleFontSize
|
|
|
+ var k = (fontHeight * config.maxScale) / config.visibleFontSize;
|
|
|
if (k <= 1) {
|
|
|
- k *= magnify
|
|
|
+ k *= magnify;
|
|
|
} else if (k > 1 && k < 1 / minify) {
|
|
|
- k = ((1 / minify - magnify) / (1 / minify - 1)) * (k - 1) + magnify
|
|
|
+ k = ((1 / minify - magnify) / (1 / minify - 1)) * (k - 1) + magnify;
|
|
|
} else if (k >= 1 / minify) {
|
|
|
- k = minify * k + (1 / minify - 1)
|
|
|
+ k = minify * k + (1 / minify - 1);
|
|
|
}
|
|
|
- fontHeight = k * config.visibleFontSize / config.maxScale
|
|
|
+ fontHeight = (k * config.visibleFontSize) / config.maxScale;
|
|
|
|
|
|
if (fontHeight * this.bestFitScale > config.visibleFontSize * 1.2) {
|
|
|
- fontHeight = config.visibleFontSize * 1.2 / bestFitScale
|
|
|
+ fontHeight = (config.visibleFontSize * 1.2) / bestFitScale;
|
|
|
}
|
|
|
|
|
|
- area.center.fontHeight = fontHeight
|
|
|
+ area.center.fontHeight = fontHeight;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ centers.sort((a, b) => b.fontHeight - a.fontHeight);
|
|
|
|
|
|
- centers.sort((a, b) => b.fontHeight - a.fontHeight)
|
|
|
+ this.digits = digits;
|
|
|
+ this.centers = centers;
|
|
|
|
|
|
- this.digits = digits
|
|
|
- this.centers = centers
|
|
|
-
|
|
|
- this.vertexArray = new Float32Array(digits * 12)
|
|
|
- this.texCoordArray = new Float32Array(digits * 12)
|
|
|
- var offset = 0
|
|
|
+ this.vertexArray = new Float32Array(digits * 12);
|
|
|
+ this.texCoordArray = new Float32Array(digits * 12);
|
|
|
+ var offset = 0;
|
|
|
|
|
|
for (var i = 0; i < centers.length; i++) {
|
|
|
- var center = centers[i]
|
|
|
- this.fillVertexArray(this.vertexArray, this.texCoordArray, offset, center, ratio)
|
|
|
- offset += 12 * center.label.length
|
|
|
- center.offset = offset / 2
|
|
|
+ var center = centers[i];
|
|
|
+ this.fillVertexArray(
|
|
|
+ this.vertexArray,
|
|
|
+ this.texCoordArray,
|
|
|
+ offset,
|
|
|
+ center,
|
|
|
+ ratio,
|
|
|
+ );
|
|
|
+ offset += 12 * center.label.length;
|
|
|
+ center.offset = offset / 2;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
//fillRectangle(this.vertexArray, 0, 0, 0, width, height )
|
|
|
//fillRectangle(this.texCoordArray, 0, 0, 0, 1, 1)
|
|
|
|
|
|
-
|
|
|
this.vertexBuffer = gl.createBuffer()!;
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
|
|
gl.bufferData(gl.ARRAY_BUFFER, this.vertexArray, gl.STATIC_DRAW);
|
|
|
|
|
|
-
|
|
|
this.texcoordBuffer = gl.createBuffer()!;
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.texcoordBuffer);
|
|
|
gl.bufferData(gl.ARRAY_BUFFER, this.texCoordArray, gl.STATIC_DRAW);
|
|
|
-
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
+ /** replay 阶段设为 false,隐藏 hint 覆盖层 */
|
|
|
+ public enabled: boolean = true;
|
|
|
|
|
|
override draw() {
|
|
|
+ if (!this.enabled) return;
|
|
|
|
|
|
- var offset = 0
|
|
|
- const maxScale = this.fillerData.config.maxScale - 0.2
|
|
|
- const scale = this.scene.userMat[0]
|
|
|
+ var offset = 0;
|
|
|
+ const maxScale = this.fillerData.config.maxScale - 0.2;
|
|
|
+ const scale = this.scene.userMat[0];
|
|
|
|
|
|
if (scale > maxScale) {
|
|
|
- offset = this.vertexArray.length / 2
|
|
|
+ offset = this.vertexArray.length / 2;
|
|
|
} else {
|
|
|
for (var i = this.centers.length - 1; i >= 0; i--) {
|
|
|
- if (this.centers[i].fontHeight * scale > this.fillerData.config.visibleFontSize) {
|
|
|
- offset = this.centers[i].offset
|
|
|
- break
|
|
|
+ if (
|
|
|
+ this.centers[i].fontHeight * scale >
|
|
|
+ this.fillerData.config.visibleFontSize
|
|
|
+ ) {
|
|
|
+ offset = this.centers[i].offset;
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
-
|
|
|
const gl = this.scene.gl;
|
|
|
gl.useProgram(this.program);
|
|
|
|
|
|
gl.enableVertexAttribArray(this.aPositionLoc);
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer);
|
|
|
- gl.vertexAttribPointer(this.aPositionLoc, 2, gl.FLOAT, false, 0, 0)
|
|
|
+ gl.vertexAttribPointer(this.aPositionLoc, 2, gl.FLOAT, false, 0, 0);
|
|
|
|
|
|
gl.enableVertexAttribArray(this.aTexcoordLoc);
|
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.texcoordBuffer);
|
|
|
- gl.vertexAttribPointer(this.aTexcoordLoc, 2, gl.FLOAT, false, 0, 0)
|
|
|
+ gl.vertexAttribPointer(this.aTexcoordLoc, 2, gl.FLOAT, false, 0, 0);
|
|
|
|
|
|
- gl.uniformMatrix4fv(this.uMatrixLoc, false, this.scene.drawMatrix)
|
|
|
+ gl.uniformMatrix4fv(this.uMatrixLoc, false, this.scene.drawMatrix);
|
|
|
|
|
|
- gl.uniform1f(this.uScaleLoc, this.scene.userMat[0])
|
|
|
+ gl.uniform1f(this.uScaleLoc, this.scene.userMat[0]);
|
|
|
//gl.uniform2f(this.uTexSizeLoc, 1. / this.texWidth, 1. / this.texHeight)
|
|
|
|
|
|
- gl.activeTexture(gl.TEXTURE0)
|
|
|
- gl.bindTexture(gl.TEXTURE_2D, this.texture)
|
|
|
+ gl.activeTexture(gl.TEXTURE0);
|
|
|
+ gl.bindTexture(gl.TEXTURE_2D, this.texture);
|
|
|
|
|
|
gl.drawArrays(gl.TRIANGLES, 0, offset);
|
|
|
-
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- fillVertexArray(vertexArray: Float32Array, texCoordArray: Float32Array, offset: number, center: Center, ratio: number) {
|
|
|
-
|
|
|
- const text = center.label
|
|
|
- const size = text.length
|
|
|
- const cellWidth = center.fontHeight * ratio
|
|
|
- const cellHeight = center.fontHeight
|
|
|
- const width = cellWidth * size
|
|
|
- const left = center.x - width / 2
|
|
|
- const top = center.y - cellHeight / 2
|
|
|
+ fillVertexArray(
|
|
|
+ vertexArray: Float32Array,
|
|
|
+ texCoordArray: Float32Array,
|
|
|
+ offset: number,
|
|
|
+ center: Center,
|
|
|
+ ratio: number,
|
|
|
+ ) {
|
|
|
+ const text = center.label;
|
|
|
+ const size = text.length;
|
|
|
+ const cellWidth = center.fontHeight * ratio;
|
|
|
+ const cellHeight = center.fontHeight;
|
|
|
+ const width = cellWidth * size;
|
|
|
+ const left = center.x - width / 2;
|
|
|
+ const top = center.y - cellHeight / 2;
|
|
|
|
|
|
for (var i = 0; i < size; i++) {
|
|
|
- fillRectangle(vertexArray, offset + 12 * i, left + i * cellWidth, top, cellWidth, cellHeight)
|
|
|
- const index = parseInt(text.substring(i, i + 1))
|
|
|
- fillRectangle(texCoordArray, offset + 12 * i, index * 0.1, 0, 0.1, 1)
|
|
|
+ fillRectangle(
|
|
|
+ vertexArray,
|
|
|
+ offset + 12 * i,
|
|
|
+ left + i * cellWidth,
|
|
|
+ top,
|
|
|
+ cellWidth,
|
|
|
+ cellHeight,
|
|
|
+ );
|
|
|
+ const index = parseInt(text.substring(i, i + 1));
|
|
|
+ fillRectangle(texCoordArray, offset + 12 * i, index * 0.1, 0, 0.1, 1);
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
toString(): string {
|
|
|
- return `NumberLayer()`
|
|
|
+ return `NumberLayer()`;
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|