205 lines
6.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { HintAdapter, Point, RectPoints } from "./adapter";
declare const cc: any;
export class HintV3 extends HintAdapter {
resetIndex(): void {
if (this.inspectorCanvas) {
const len = this.inspectorCanvas.parent.children.length;
this.inspectorCanvas.setSiblingIndex(len);
}
}
private get transformComponent() {
return cc.UITransformComponent || cc.UITransform;
}
hitTest(node: any, x: number, y: number): boolean {
if (node === this.inspectorCanvas) {
return false;
}
if (node.getComponent(cc.Canvas)) {
// 因为Canvas会全屏所以暂时不拾取会干扰体验
return false;
}
const tr = node.getComponent(this.transformComponent);
if (tr) {
const size = cc.view.getVisibleSize();
if (tr.width >= size.width || tr.height >= size.height) {
// 节点的区域非常大,并且没有渲染组件,在界面上看不到任何内容,也忽略掉
// 有些背景遮罩使用的是单色透明图片,这种情况暂时没有好办法过滤掉
const renderComp = [cc.Sprite, cc.Label].find((comp) => node.getComponent(comp));
if (!renderComp) {
return false;
}
}
}
let hitTest = null;
if (tr) {
if (tr.hitTest) {
hitTest = tr.hitTest.bind(tr);
} else if (tr.isHit) {
// TODO: 3.3.1使用的是这个接口hitTest有问题有人反馈再说修复老版本暂不花费太多精力
hitTest = tr.isHit.bind(tr);
}
}
if (hitTest) {
let b = hitTest({ x, y }, 0);
return b;
} else {
return false;
}
}
convertMousePos(event: MouseEvent, canvas: HTMLCanvasElement): { x: number; y: number } {
const rect = canvas.getBoundingClientRect();
let x = event.clientX - rect.x;
let y = rect.y + rect.height - event.clientY;
x *= window.devicePixelRatio;
y *= window.devicePixelRatio;
return { x, y };
}
/**
* 这种方式能够获取到优先绘制的canvas也能保证线框在顶部但是方案不完美会受到node.layer的影响
*/
private getCanvas(scene: any) {
const canvasArray: Array<{ canvas: any; index: number }> = [];
scene.walk((item: any) => {
if (cc.Canvas) {
const comp = item.getComponent(cc.Canvas);
if (comp) {
const idx = comp.cameraComponent?.priority || 0;
canvasArray.push({ canvas: comp, index: idx });
}
}
});
if (canvasArray.length) {
canvasArray.sort((a, b) => a.index - b.index);
return canvasArray[0].canvas.node;
}
return null;
}
private inspectorCanvas: any = null;
protected addDraw(scene: any, graphicsNode: any): boolean {
graphicsNode.layer = this.getLayerID();
const tr = graphicsNode.getComponent(this.transformComponent) || graphicsNode.addComponent(this.transformComponent);
if (tr) {
tr.setContentSize(0, 0);
}
const inspectorCanvas = this.createInspectorCanvas();
scene.addChild(inspectorCanvas);
const camera = this.createCamera();
inspectorCanvas.addChild(camera.node);
inspectorCanvas.addChild(graphicsNode);
const canvas = inspectorCanvas.addComponent(cc.Canvas);
canvas.cameraComponent = camera;
canvas.alignCavasWithScreen = true;
this.inspectorCanvas = inspectorCanvas;
return true;
}
private createInspectorCanvas() {
const node = new cc.Node("InspectorCanvas");
node.layer = this.getLayerID();
const widget = node.addComponent(cc.Widget);
widget.alignMode = cc.Widget.AlignMode.ALWAYS;
widget.isAlignBottom = true;
widget.isAlignTop = true;
widget.isAlignLeft = true;
widget.isAlignRight = true;
widget.left = widget.right = widget.top = widget.bottom = 0;
return node;
}
private createCamera() {
const node = new cc.Node("InspectorCamera");
node.layer = this.getLayerID();
const camera = node.addComponent(cc.Camera);
camera.priority = Number.MAX_VALUE;
camera.layer = this.getLayerID();
camera.visibility = this.getLayerID();
camera.clearFlags = cc.Camera.ClearFlag.DONT_CLEAR;
camera.clearColor = new cc.Color(0, 0, 0, 0);
camera.projection = cc.Camera.ProjectionType.ORTHO;
camera.far = 2000;
return camera;
}
private getLayerID() {
return cc.Layers.Enum.GIZMOS;
}
getRectPoints(node: any): RectPoints | null {
if (!node.worldPosition) {
return null;
}
if (!this.transformComponent) {
return null;
}
const tr = node.getComponent(this.transformComponent);
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(this.transformComponent).convertToNodeSpaceAR(cc.v3(worldX, worldY, worldZ));
points.add(new Point(pos.x, pos.y));
});
return points;
}
/**
* 尝试实现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));
}
});
}
}
}