1/* 2 * Copyright (c) 2022-2023 Shenzhen Kaihong Digital Industry Development Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { XMat4 } from './XMat4.js'; 17import { XShader } from './XShader.js'; 18import { Scr } from '../XDefine.js'; 19import { XTexture } from './XTexture.js'; 20import { gl } from '../GLFrame.js'; 21import { fAngle, iDistance } from '../XTools.js'; 22const { NapiLog } = require('./../../hcs/NapiLog'); 23const COLOR = 0xffffffff; 24const DRAWTEXT_SIZE = 14; 25 26export class X2DFast { 27 static gi() { 28 if (X2DFast.px2f === null) { 29 X2DFast.px2f = new X2DFast(); 30 } 31 return X2DFast.px2f; 32 } 33 34 constructor() { 35 this.localBuffer = gl.createBuffer(); 36 this.texSampleIdx = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; 37 38 this.vertexArray = new ArrayBuffer(1024 * 1024 * 4 * 2); 39 this.vertexFloat32 = new Float32Array(this.vertexArray); 40 this.vertexUint32 = new Uint32Array(this.vertexArray); 41 this.whiteImg = XTexture.gi().loadTextureFromImage('CUSTOM_TEXTURE_1'); 42 this.whiteCut = XTexture.gi().makeCut(this.whiteImg, 0, 0, 1, 1); 43 XShader.gi(); 44 45 this.resetMat(); 46 } 47 resetMat() { 48 X2DFast.transform2D.unit(); 49 X2DFast.transform2D.orthoMat(0, 0, Scr.logicw, Scr.logich); 50 let tm = X2DFast.transform2D.mat; 51 this.t2dExt = [ 52 tm[0][0], 53 tm[1][0], 54 tm[2][0], 55 tm[3][0], 56 tm[0][1], 57 tm[1][1], 58 tm[2][1], 59 tm[3][1], 60 tm[0][2], 61 tm[1][2], 62 tm[2][2], 63 tm[3][2], 64 tm[0][3], 65 tm[1][3], 66 tm[2][3], 67 tm[3][3], 68 ]; 69 } 70 71 swapMode2D() { 72 gl.disable(gl.DEPTH_TEST); 73 74 gl.enable(gl.BLEND); 75 gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); 76 } 77 78 DrawCircle(ox, oy, rw, rh, c = 0xffffffff, lw = 1) { 79 let lx = -1; 80 let ly = -1; 81 let i = 0; 82 let gap = (Math.PI * 2) / 32; 83 while (i < Math.PI * 2 + 0.00001) { 84 let dx = Math.cos(i) * rw + ox; 85 let dy = Math.sin(i) * rh + oy; 86 if (lx !== -1) { 87 this.drawLine(lx, ly, dx, dy, c, lw); 88 } 89 lx = dx; 90 ly = dy; 91 i += gap; 92 } 93 } 94 95 fillRect(x, y, w, h, c = 0xffffffff) { 96 this.drawCut(this.whiteCut, x, y, w, h, 0, 0, 0, c); 97 } 98 99 drawLine(x1, y1, x2, y2, c = 0xffffffff, linewidth = 1) { 100 this.drawCut( 101 this.whiteCut, 102 x1, 103 y1, 104 iDistance(x1 - x2, y1 - y2), 105 linewidth, 106 fAngle(x2 - x1, y2 - y1), 107 0, 108 0.5, 109 c 110 ); 111 } 112 113 drawRect(x, y, w, h, c = 0xffffffff, lw = 1) { 114 this.drawLine(x - lw / 2, y, x + w + lw / 2, y, c, lw); 115 this.drawLine(x, y, x, y + h, c, lw); 116 this.drawLine(x + w, y + h, x + w, y, c, lw); 117 this.drawLine(x + w + lw / 2, y + h, x - lw / 2, y + h, c, lw); 118 } 119 120 static testTransform(x, y, sw, sh, ra, ox, oy, realw, realh) { 121 const LEFT = -1; 122 const MIDDLE = -2; 123 const RIGHT = -3; 124 const UP = -1; 125 const DOWN = -3; 126 const BY_MIDDLE = 2; 127 X2DFast.tmpMat.unit(); 128 if (ox === LEFT) { 129 ox = 0; 130 } 131 if (ox === MIDDLE) { 132 ox = Math.floor(realw / BY_MIDDLE); 133 } 134 if (ox === RIGHT) { 135 ox = realw; 136 } 137 if (oy === UP) { 138 oy = 0; 139 } 140 if (oy === MIDDLE) { 141 oy = Math.floor(realh / BY_MIDDLE); 142 } 143 if (oy === DOWN) { 144 oy = realh; 145 } 146 if (ox !== 0 || oy !== 0) { 147 X2DFast.tmpMat.move(-ox, -oy, 0); 148 } 149 if (sw !== 1 || sh !== 1) { 150 X2DFast.tmpMat.scale(sw, sh, 1); 151 } 152 if (ra !== 0) { 153 X2DFast.tmpMat.rotate(0, 0, ra); 154 } 155 if (x !== 0 || y !== 0) { 156 X2DFast.tmpMat.move(x, y, 0); 157 } 158 } 159 clearBuffer() { 160 this.ridDict = {}; 161 this.ridPoint = 0; 162 this.drawCount = 0; 163 } 164 swapC(c) { 165 let r = Math.floor((((c >> 16) & 0xff) * 63) / 255); 166 let g = Math.floor((((c >> 8) & 0xff) * 63) / 255); 167 let b = Math.floor(((c & 0xff) * 63) / 255); 168 let a = Math.floor((((c >> 24) & 0xff) * 63) / 255); 169 return ((a * 64 + r) * 64 + g) * 64 + b; 170 } 171 drawCut_(pcut, m00, m01, m10, m11, m22, m30, m31, c = COLOR) { 172 if (c === -1) { 173 c = COLOR; 174 } 175 c = this.swapC(c); 176 this.vertexFloat32.set([0.0, 0.0, 0.0, pcut.u0, pcut.v0, m00, m01, m10, m11, m22, m30, m31, 177 this.ridDict[pcut.rid], c, 178 pcut.w, 0.0, 0.0, pcut.u1, pcut.v1, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c, 179 pcut.w, pcut.h, 0.0, pcut.u2, pcut.v2, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c, 180 0.0, 0.0, 0.0, pcut.u0, pcut.v0, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c, 181 pcut.w, pcut.h, 0.0, pcut.u2, pcut.v2, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c, 182 0.0, pcut.h, 0.0, pcut.u3, pcut.v3, m00, m01, m10, m11, m22, m30, m31, this.ridDict[pcut.rid], c,], 183 this.drawCount * 14 * 6); 184 this.drawCount += 1; 185 } 186 drawCutEx(cid, tmat, c = COLOR) { 187 let pcut = XTexture.pinstance_.allCuts[cid]; 188 if (!(pcut.rid in this.ridDict)) { 189 this.ridDict[pcut.rid] = this.ridPoint; 190 this.ridPoint += 1; 191 } 192 tmat = tmat.mat; 193 this.drawCut(pcut, tmat[0][0], tmat[0][1], tmat[1][0], tmat[1][1], tmat[2][2], tmat[3][0], tmat[3][1], c); 194 } 195 drawCut(cid, x = 0, y = 0, sw = 1, sh = 1, ra = 0, ox = 0, oy = 0, c = COLOR) { 196 let intX = parseInt(x); 197 let intY = parseInt(y); 198 let pcut = XTexture.gi().allCuts[cid]; 199 if (pcut === null) { 200 NapiLog.logError('error occured getting object'); 201 return; 202 } 203 if (!(pcut.rid in this.ridDict)) { 204 if (this.ridPoint >= 16) { 205 this.freshBuffer(); 206 this.clearBuffer(); 207 } 208 this.ridDict[pcut.rid] = this.ridPoint; 209 this.ridPoint += 1; 210 } 211 X2DFast.testTransform(intX, intY, sw, sh, ra, ox, oy, pcut.w, pcut.h); 212 let tmat = X2DFast.tmpMat.mat; 213 this.drawCut_(pcut, tmat[0][0], tmat[0][1], tmat[1][0], tmat[1][1], tmat[2][2], tmat[3][0], tmat[3][1], c); 214 } 215 drawText(s, size = DRAWTEXT_SIZE, x = 0, y = 0, sw = 1, sh = 1, ra = 0, ox = 0, oy = 0, c = COLOR) { 216 if (s.length <= 0) { 217 NapiLog.logError('error occured s is null'); 218 return 0; 219 } 220 let cid = XTexture.gi().getText(s, size); 221 if (cid >= 0) { 222 this.drawCut(cid, x, y, sw, sh, ra, ox, oy, c); 223 } 224 return XTexture.gi().allCuts[cid].w; 225 } 226 getTextWidth(s, size) { 227 if (s.length <= 0) { 228 return 0; 229 } 230 let cid = XTexture.gi().getText(s, size); 231 return XTexture.gi().allCuts[cid].w; 232 } 233 freshBuffer() { 234 XTexture.gi()._FreshText(); 235 if (this.drawCount === 0) { 236 return; 237 } 238 let ps = XShader.gi().use(XShader.ID_SHADER_FAST); 239 for (let rid in this.ridDict) { 240 gl.activeTexture(gl.TEXTURE0 + this.ridDict[rid]); 241 gl.bindTexture(gl.TEXTURE_2D, XTexture.gi().ximages[rid].tex); 242 243 gl.uniform1i(ps.tex[this.ridDict[rid]], this.ridDict[rid]); 244 } 245 246 gl.uniformMatrix4fv(ps.uMat, false, this.t2dExt); 247 248 gl.bindBuffer(gl.ARRAY_BUFFER, this.localBuffer); 249 gl.bufferData(gl.ARRAY_BUFFER, this.vertexArray, gl.STATIC_DRAW); 250 gl.vertexAttribPointer(ps.position, 3, gl.FLOAT, false, 4 * 14, 0); 251 gl.enableVertexAttribArray(ps.position); 252 gl.vertexAttribPointer(ps.aTexCoord, 2, gl.FLOAT, false, 4 * 14, 4 * 3); 253 gl.enableVertexAttribArray(ps.aTexCoord); 254 gl.vertexAttribPointer(ps.ext1, 4, gl.FLOAT, false, 4 * 14, 4 * 5); 255 gl.enableVertexAttribArray(ps.ext1); 256 gl.vertexAttribPointer(ps.ext2, 4, gl.FLOAT, false, 4 * 14, 4 * 9); 257 gl.enableVertexAttribArray(ps.ext2); 258 gl.vertexAttribPointer(ps.inColor, 1, gl.FLOAT, false, 4 * 14, 4 * 13); 259 gl.enableVertexAttribArray(ps.inColor); 260 261 gl.drawArrays(gl.TRIANGLES, 0, 6 * this.drawCount); 262 } 263} 264X2DFast.tmpMat = new XMat4(); 265X2DFast.transform2D = new XMat4(); 266 267X2DFast.px2f = null; 268