269 lines
6.9 KiB
TypeScript

declare const cc: any;
class Point {
x: number;
y: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
class RectPoints {
points: Point[] = [];
get len() {
return this.points.length;
}
at(index: number) {
return this.points[index];
}
test(width: number, height: number) {
this.points.push(new Point(0, 0));
this.points.push(new Point(width, 0));
this.points.push(new Point(width, height));
this.points.push(new Point(0, height));
}
}
interface DrawOptions {
fill: boolean;
fillColor: string;
stroke: boolean;
strokeColor: string;
}
export class Hint {
private draw = null;
public engineVersion: string = "";
private get isEngineV2() {
return this.engineVersion.startsWith("2.");
}
private get isEngineV3() {
return this.engineVersion.startsWith("3.");
}
public cleanHover() {
this.hoverNodes = [];
if (this.draw) {
this.draw.clear();
}
}
public cleanSelected() {
this.selectedNodes = [];
if (this.draw) {
this.draw.clear();
}
}
private initDrawNode() {
if (this.draw && !this.draw.isValid) {
this.draw = null;
}
if (this.draw) {
return;
}
const scene = cc.director.getScene();
if (!scene) {
return;
}
let node = new cc.Node("draw-node");
const canvas = cc.find("Canvas");
if (canvas) {
// 3.x 需要放到canvas下边
if (canvas.layer) {
node.layer = canvas.layer;
}
canvas.addChild(node);
} else {
scene.addChild(node);
}
this.draw = node.addComponent(cc.Graphics);
}
private hoverNodes = [];
private selectedNodes = [];
private resetIndex() {
if (this.isEngineV3) {
const len = this.draw.node.parent.children.length;
this.draw.node.setSiblingIndex(len);
} else if (this.isEngineV2) {
}
}
public update() {
this.initDrawNode();
if (!this.draw) {
return;
}
this.draw.clear();
this.resetIndex();
// this.testRect();
this.hoverNodes.forEach((node) => {
if (node.isValid) {
this.hintNode(node, {
fill: true,
fillColor: "#00ff0055",
stroke: true,
strokeColor: "#ffffff44",
});
}
});
this.selectedNodes.forEach((node) => {
if (node.isValid) {
this.hintNode(node, {
fill: false,
fillColor: "#ff0000",
stroke: true,
strokeColor: "#ff0000",
});
}
});
}
private testRect() {
const points = new RectPoints();
points.test(100, 100);
this.drawRect(points, {
fill: true,
fillColor: "#00ff0099",
stroke: true,
strokeColor: "#ff000099",
});
}
public setHover(node: any) {
this.hoverNodes = [node];
}
public setSelected(node: any) {
this.selectedNodes = [node];
}
private getRectPoints(node: any): RectPoints | null {
if (this.isEngineV2) {
const points: RectPoints = new RectPoints();
return points;
} else if (this.isEngineV3) {
// v3版本
if (!node.worldPosition) {
return null;
}
const transform = cc.UITransformComponent || cc.UITransform;
if (!transform) {
return null;
}
const tr = node.getComponent(transform);
if (!tr) {
return null;
}
const { anchorPoint, width, height } = tr;
const points: RectPoints = new RectPoints();
const x = -anchorPoint.x * width;
const y = -anchorPoint.y * height;
const m = node.worldMatrix;
[
new Point(x, y), //
new Point(x + width, y),
new Point(x + width, y + height),
new Point(x, y + height),
].forEach(({ x, y }: Point) => {
let rhw = m.m03 * x + m.m07 * y + m.m15;
rhw = rhw ? 1 / rhw : 1;
let worldX = (m.m00 * x + m.m04 * y + m.m12) * rhw;
let worldY = (m.m01 * x + m.m05 * y + m.m13) * rhw;
let worldZ = (m.m02 * x + m.m06 * y + m.m14) * rhw;
const pos = this.draw.getComponent(transform).convertToNodeSpaceAR(cc.v3(worldX, worldY, worldZ));
points.points.push(new Point(pos.x, pos.y));
});
return points;
}
return null;
}
/**
* 尝试实现wireframe模式
*/
private getTrangles(node: any) {
const comps = node._components;
if (comps && Array.isArray(comps)) {
const m = node.worldMatrix;
comps.forEach((comp) => {
const { renderData } = comp;
if (!renderData) {
return;
}
const { data, _vc: VertexCount, _ic: IndexCount, chunk } = renderData;
if (!data) {
return;
}
// 获取indexBuffer的索引顺序
const ib = chunk.meshBuffer.iData;
let indexOffset = chunk.meshBuffer.indexOffset;
const vidOrigin = chunk.vertexOffset;
const arr = [];
for (let i = 0; i < IndexCount; i++) {
const index = ib[indexOffset + i] - vidOrigin;
arr.push(index);
}
for (let j = 0; j < data.length; j++) {
const item = data[j];
const { x, y, z, u, v, color } = item;
let rhw = m.m03 * x + m.m07 * y + m.m15;
rhw = rhw ? 1 / rhw : 1;
let worldX = (m.m00 * x + m.m04 * y + m.m12) * rhw;
let worldY = (m.m01 * x + m.m05 * y + m.m13) * rhw;
let worldZ = (m.m02 * x + m.m06 * y + m.m14) * rhw;
// const pos = this.draw.getComponent(transform).convertToNodeSpaceAR(cc.v3(worldX, worldY, worldZ));
// points.points.push(new Point(pos.x, pos.y));
}
});
}
}
private getBox(node: any) {
if (node.getBoundingBoxToWorld) {
return node.getBoundingBoxToWorld();
}
if (cc.UITransformComponent) {
const tr = node.getComponent(cc.UITransformComponent);
if (tr && tr.getBoundingBoxToWorld) {
return tr.getBoundingBoxToWorld();
}
}
return null;
}
private hintNode(node: any, opts: DrawOptions) {
const points = this.getRectPoints(node);
if (!points) {
return;
}
this.drawRect(points, opts);
}
private drawRect(points: RectPoints, opts: DrawOptions) {
this.draw.lineWidth = 2;
for (let i = 0; i < points.len; i++) {
const p = points.at(i);
if (i === 0) {
this.draw.moveTo(p.x, p.y);
} else {
this.draw.lineTo(p.x, p.y);
}
}
this.draw.close();
if (opts.stroke) {
this.draw.strokeColor = new cc.Color().fromHEX(opts.strokeColor);
this.draw.stroke();
}
if (opts.fill) {
this.draw.fillColor = new cc.Color().fromHEX(opts.fillColor);
this.draw.fill();
}
}
private fillRect(points: RectPoints, color: string) {
this.draw.fillColor = new cc.Color().fromHEX(color);
for (let i = 0; i < points.len; i++) {
const p = points.at(i);
if (i === 0) {
this.draw.moveTo(p.x, p.y);
} else {
this.draw.lineTo(p.x, p.y);
}
}
this.draw.close();
this.draw.fill();
}
}