mirror of
https://github.com/tidys/cc-inspector-chrome
synced 2025-10-23 00:45:25 +00:00
代码整理
This commit is contained in:
239
src/scripts/inject/enumConfig.ts
Normal file
239
src/scripts/inject/enumConfig.ts
Normal file
@@ -0,0 +1,239 @@
|
||||
declare const cc: any;
|
||||
|
||||
export function getEnumListConfig() {
|
||||
const enumConfig: Array<{
|
||||
type: any;
|
||||
list: Array<{
|
||||
key: string;
|
||||
values: () => Array<{ name: string; value: number }>;
|
||||
}>;
|
||||
}> = [
|
||||
{
|
||||
type: cc.Widget,
|
||||
list: [
|
||||
{
|
||||
key: "alignMode",
|
||||
values: () => {
|
||||
return cc.Widget.AlignMode.__enums__;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: cc.Button,
|
||||
list: [
|
||||
{
|
||||
key: "transition",
|
||||
values: () => {
|
||||
return cc.Button.Transition.__enums__;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: cc.Sprite,
|
||||
list: [
|
||||
{
|
||||
key: "sizeMode",
|
||||
values: () => {
|
||||
return cc.Sprite.SizeMode.__enums__;
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "type",
|
||||
values: () => {
|
||||
return cc.Sprite.Type.__enums__;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: cc.Mask,
|
||||
list: [
|
||||
{
|
||||
key: "type",
|
||||
values() {
|
||||
return cc.Mask.Type.__enums__;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: cc.Label,
|
||||
list: [
|
||||
{
|
||||
key: "cacheMode",
|
||||
values() {
|
||||
return cc.Label.CacheMode.__enums__;
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "overflow",
|
||||
values() {
|
||||
return cc.Label.Overflow.__enums__;
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "verticalAlign",
|
||||
values() {
|
||||
return cc.Label.VerticalAlign.__enums__;
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "horizontalAlign",
|
||||
values() {
|
||||
return cc.Label.HorizontalAlign.__enums__;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: cc.Slider,
|
||||
list: [
|
||||
{
|
||||
key: "direction",
|
||||
values() {
|
||||
return cc.Slider.Direction.__enums__;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: cc.PageView,
|
||||
list: [
|
||||
{
|
||||
key: "direction",
|
||||
values() {
|
||||
return cc.PageView.Direction.__enums__;
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "sizeMode",
|
||||
values() {
|
||||
return cc.PageView.SizeMode.__enums__;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: cc.PageViewIndicator,
|
||||
list: [
|
||||
{
|
||||
key: "direction",
|
||||
values() {
|
||||
return cc.PageViewIndicator.Direction.__enums__;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: cc.RichText,
|
||||
list: [
|
||||
{
|
||||
key: "cacheMode",
|
||||
values() {
|
||||
return cc.Label.CacheMode.__enums__;
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "horizontalAlign",
|
||||
values() {
|
||||
return cc.RichText.HorizontalAlign.__enums__;
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "verticalAlign",
|
||||
values() {
|
||||
return cc.RichText.VerticalAlign.__enums__;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: cc.ProgressBar,
|
||||
list: [
|
||||
{
|
||||
key: "mode",
|
||||
values() {
|
||||
return cc.ProgressBar.Mode.__enums__;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: cc.Scrollbar,
|
||||
list: [
|
||||
{
|
||||
key: "direction",
|
||||
values() {
|
||||
return cc.Scrollbar.Direction.__enums__;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: cc.EditBox,
|
||||
list: [
|
||||
{
|
||||
key: "inputMode",
|
||||
values() {
|
||||
return cc.EditBox.InputMode.__enums__;
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "inputFlag",
|
||||
values() {
|
||||
return cc.EditBox.InputFlag.__enums__;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: cc.Layout,
|
||||
list: [
|
||||
{
|
||||
key: "resizeMode",
|
||||
values() {
|
||||
return cc.Layout.ResizeMode.__enums__;
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "type",
|
||||
values() {
|
||||
return cc.Layout.Type.__enums__;
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "startAxis",
|
||||
values() {
|
||||
return cc.Layout.AxisDirection.__enums__;
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "horizontalDirection",
|
||||
values() {
|
||||
return cc.Layout.HorizontalDirection.__enums__;
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "verticalDirection",
|
||||
values() {
|
||||
return cc.Layout.VerticalDirection.__enums__;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: cc.VideoPlayer,
|
||||
list: [
|
||||
{
|
||||
key: "resourceType",
|
||||
values() {
|
||||
return cc.VideoPlayer.ResourceType.__enums__;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
return enumConfig;
|
||||
}
|
||||
32
src/scripts/inject/event.ts
Normal file
32
src/scripts/inject/event.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { debugLog, Msg, Page, PluginEvent } from "../../core/types";
|
||||
import { GA_EventName } from "../../ga/type";
|
||||
import { DocumentEvent, GoogleAnalyticsData } from "../const";
|
||||
import { Terminal } from "../terminal";
|
||||
|
||||
export class InjectEvent {
|
||||
protected terminal = new Terminal("Inject ");
|
||||
constructor() {
|
||||
document.addEventListener(DocumentEvent.Content2Inject, (event: CustomEvent) => {
|
||||
const pluginEvent: PluginEvent = PluginEvent.create(event.detail);
|
||||
debugLog && console.log(...this.terminal.chunkMessage(pluginEvent.toChunk()));
|
||||
this.onMessage(pluginEvent);
|
||||
});
|
||||
}
|
||||
onMessage(data: PluginEvent) {}
|
||||
sendMsgToContent(msg: Msg, data: any) {
|
||||
const detail = new PluginEvent(Page.Inject, Page.Content, msg, data);
|
||||
debugLog && console.log(...this.terminal.chunkSend(detail.toChunk()));
|
||||
const event = new CustomEvent(DocumentEvent.Inject2Content, { detail });
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
sendEngineVersion(version: string) {
|
||||
const detail = version;
|
||||
const event = new CustomEvent(DocumentEvent.EngineVersion, { detail });
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
sendAppVersion(version: string) {
|
||||
const detail = { event: GA_EventName.AppVersion, params: version } as GoogleAnalyticsData;
|
||||
const event = new CustomEvent(DocumentEvent.GoogleAnalytics, { detail });
|
||||
document.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
97
src/scripts/inject/hint/adapter.ts
Normal file
97
src/scripts/inject/hint/adapter.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
declare const cc: any;
|
||||
export interface DrawOptions {
|
||||
fill: boolean;
|
||||
fillColor: string;
|
||||
stroke: boolean;
|
||||
strokeColor: string;
|
||||
}
|
||||
export class Point {
|
||||
x: number;
|
||||
y: number;
|
||||
constructor(x: number, y: number) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
export class RectPoints {
|
||||
points: Point[] = [];
|
||||
get len() {
|
||||
return this.points.length;
|
||||
}
|
||||
add(point: Point) {
|
||||
this.points.push(point);
|
||||
}
|
||||
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));
|
||||
}
|
||||
}
|
||||
export class HintAdapter {
|
||||
protected draw = null;
|
||||
constructor() {}
|
||||
resetIndex() {
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
getRectPoints(node: any): RectPoints | null {
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
clear() {
|
||||
if (this.draw) {
|
||||
this.draw.clear();
|
||||
}
|
||||
}
|
||||
convertMousePos(event: MouseEvent, canvas: HTMLCanvasElement): { x: number; y: number } {
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
hitTest(node: any, x: number, y: number): boolean {
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
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");
|
||||
this.addDraw(scene, node);
|
||||
this.draw = node.addComponent(cc.Graphics || cc.GraphicsComponent);
|
||||
}
|
||||
public isDrawValid() {
|
||||
return this.draw && this.draw.isValid;
|
||||
}
|
||||
protected addDraw(scene: any, node: any) {
|
||||
throw new Error("not implemented");
|
||||
}
|
||||
public 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);
|
||||
}
|
||||
}
|
||||
if (points.len) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
136
src/scripts/inject/hint/hint-v2.ts
Normal file
136
src/scripts/inject/hint/hint-v2.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
import { HintAdapter, Point, RectPoints } from "./adapter";
|
||||
declare const cc: any;
|
||||
|
||||
export class HintV2 extends HintAdapter {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
protected addDraw(scene: any, node: any): void {
|
||||
scene.addChild(node);
|
||||
}
|
||||
private canvasBoundingRect = {
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
adjustedTop: 0,
|
||||
adjustedLeft: 0,
|
||||
};
|
||||
private _updateCanvasBoundingRect() {
|
||||
// @ts-ignore
|
||||
const element: any = cc.game.canvas;
|
||||
var docElem = document.documentElement;
|
||||
var leftOffset = window.pageXOffset - docElem.clientLeft;
|
||||
var topOffset = window.pageYOffset - docElem.clientTop;
|
||||
if (element.getBoundingClientRect) {
|
||||
var box = element.getBoundingClientRect();
|
||||
this.canvasBoundingRect.left = box.left + leftOffset;
|
||||
this.canvasBoundingRect.top = box.top + topOffset;
|
||||
this.canvasBoundingRect.width = box.width;
|
||||
this.canvasBoundingRect.height = box.height;
|
||||
} else if (element instanceof HTMLCanvasElement) {
|
||||
this.canvasBoundingRect.left = leftOffset;
|
||||
this.canvasBoundingRect.top = topOffset;
|
||||
this.canvasBoundingRect.width = element.width;
|
||||
this.canvasBoundingRect.height = element.height;
|
||||
} else {
|
||||
this.canvasBoundingRect.left = leftOffset;
|
||||
this.canvasBoundingRect.top = topOffset;
|
||||
this.canvasBoundingRect.width = parseInt(element.style.width);
|
||||
this.canvasBoundingRect.height = parseInt(element.style.height);
|
||||
}
|
||||
}
|
||||
getPointByEvent(event: MouseEvent) {
|
||||
this._updateCanvasBoundingRect();
|
||||
if (event.pageX != null)
|
||||
//not avalable in <= IE8
|
||||
return { x: event.pageX, y: event.pageY };
|
||||
|
||||
this.canvasBoundingRect.left -= document.body.scrollLeft;
|
||||
this.canvasBoundingRect.top -= document.body.scrollTop;
|
||||
|
||||
return { x: event.clientX, y: event.clientY };
|
||||
}
|
||||
convertMousePos(event: MouseEvent, canvas: HTMLCanvasElement): { x: number; y: number } {
|
||||
let location = this.getPointByEvent(event);
|
||||
// let p = cc.view._convertMouseToLocationInView(location, this.canvasBoundingRect);
|
||||
let p = cc.view.convertToLocationInView(location.x, location.y, this.canvasBoundingRect);
|
||||
let scaleX = cc.view._scaleX;
|
||||
let scaleY = cc.view._scaleY;
|
||||
let viewport = cc.view._viewportRect;
|
||||
let x = (p.x - viewport.x) / scaleX;
|
||||
let y = (p.y - viewport.y) / scaleY;
|
||||
|
||||
// let position = cc.v2(event.offsetX, event.offsetY);
|
||||
// let size = cc.view.getDesignResolutionSize();
|
||||
// let rect = { left: 0, top: 0, width: size.width, height: size.height };
|
||||
// cc.view._convertMouseToLocationInView(position, rect);
|
||||
// let wordPos = cc.v2();
|
||||
// cc.Camera.main.getScreenToWorldPoint(position, wordPos);
|
||||
|
||||
return { x, y };
|
||||
}
|
||||
hitTest(node: any, x: number, y: number): boolean {
|
||||
// let rect = item.getBoundingBox();
|
||||
// let p = item.parent.convertToNodeSpaceAR(wordPos);
|
||||
// if (rect.contains(p)) {
|
||||
// return item;
|
||||
// }
|
||||
const mask = this._searchComponentsInParent(node, cc.Mask);
|
||||
const b = node._hitTest(cc.v2(x, y), { mask });
|
||||
return b;
|
||||
}
|
||||
private _searchComponentsInParent(node: any, comp: any) {
|
||||
if (comp) {
|
||||
let index = 0;
|
||||
let list = null;
|
||||
for (var curr = node; curr && cc.Node.isNode(curr); curr = curr._parent, ++index) {
|
||||
if (curr.getComponent(comp)) {
|
||||
let next = {
|
||||
index: index,
|
||||
node: curr,
|
||||
};
|
||||
|
||||
if (list) {
|
||||
list.push(next);
|
||||
} else {
|
||||
list = [next];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
resetIndex(): void {
|
||||
const node = this.draw.node;
|
||||
node.zIndex = node.parent.children.length;
|
||||
}
|
||||
getRectPoints(node: any): RectPoints | null {
|
||||
const points: RectPoints = new RectPoints();
|
||||
const { anchorX, anchorY, width, height } = node;
|
||||
const x = -anchorX * width;
|
||||
const y = -anchorY * height;
|
||||
const matrixm = node._worldMatrix.m;
|
||||
const m00 = matrixm[0],
|
||||
m01 = matrixm[1],
|
||||
m04 = matrixm[4],
|
||||
m05 = matrixm[5],
|
||||
m12_tx = matrixm[12],
|
||||
m13_ty = matrixm[13];
|
||||
[
|
||||
new Point(x, y), //
|
||||
new Point(x + width, y),
|
||||
new Point(x + width, y + height),
|
||||
new Point(x, y + height),
|
||||
].forEach(({ x, y }: Point) => {
|
||||
const worldX = x * m00 + y * m04 + m12_tx; // x
|
||||
const worldY = x * m01 + y * m05 + m13_ty; // y
|
||||
const pos = this.draw.node.convertToNodeSpaceAR(cc.v2(worldX, worldY));
|
||||
points.add(new Point(pos.x, pos.y));
|
||||
});
|
||||
return points;
|
||||
}
|
||||
}
|
||||
149
src/scripts/inject/hint/hint-v3.ts
Normal file
149
src/scripts/inject/hint/hint-v3.ts
Normal file
@@ -0,0 +1,149 @@
|
||||
import { HintAdapter, Point, RectPoints } from "./adapter";
|
||||
declare const cc: any;
|
||||
|
||||
export class HintV3 extends HintAdapter {
|
||||
resetIndex(): void {
|
||||
const node = this.draw.node;
|
||||
if (node.parent) {
|
||||
const len = node.parent.children.length;
|
||||
node.setSiblingIndex(len);
|
||||
}
|
||||
}
|
||||
private get transformComponent() {
|
||||
return cc.UITransformComponent || cc.UITransform;
|
||||
}
|
||||
hitTest(node: any, x: number, y: number): boolean {
|
||||
let hitTest = null;
|
||||
// hitTest = node._uiProps?.uiTransformComp?.hitTest;
|
||||
const tr = node.getComponent(this.transformComponent);
|
||||
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 });
|
||||
}
|
||||
}
|
||||
});
|
||||
canvasArray.sort((a, b) => a.index - b.index);
|
||||
return canvasArray[0].canvas.node;
|
||||
}
|
||||
protected addDraw(scene: any, node: any): void {
|
||||
const canvas = this.getCanvas(scene);
|
||||
if (canvas) {
|
||||
if (canvas.layer) {
|
||||
node.layer = canvas.layer;
|
||||
}
|
||||
const tr = node.getComponent(this.transformComponent) || node.addComponent(this.transformComponent);
|
||||
if (tr) {
|
||||
tr.setContentSize(0, 0);
|
||||
}
|
||||
// FIXME: 多canvas的情况下,如果hover和select的节点不在一个canvas下,绘制线框有问题,暂时先不支持多canvas的情况
|
||||
canvas.addChild(node);
|
||||
}
|
||||
}
|
||||
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));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
217
src/scripts/inject/hint/index.ts
Normal file
217
src/scripts/inject/hint/index.ts
Normal file
@@ -0,0 +1,217 @@
|
||||
import ccui from "@xuyanfeng/cc-ui";
|
||||
import { IUiMenuItem } from "@xuyanfeng/cc-ui/types/cc-menu/const";
|
||||
import { throttle } from "lodash";
|
||||
import { toRaw } from "vue";
|
||||
import { Msg } from "../../../core/types";
|
||||
import { DocumentEvent } from "../../const";
|
||||
import { appStore } from "../../inject-view/store";
|
||||
import { Inspector } from "../inspector";
|
||||
import { DrawOptions, HintAdapter, RectPoints } from "./adapter";
|
||||
import { HintV2 } from "./hint-v2";
|
||||
import { HintV3 } from "./hint-v3";
|
||||
declare const cc: any;
|
||||
|
||||
/**
|
||||
* 只负责管理hint的流程
|
||||
*/
|
||||
export class Hint {
|
||||
private engineVersion: string = "";
|
||||
private hintAdapter: HintAdapter = null;
|
||||
public setEngineVersion(version: string) {
|
||||
this.engineVersion = version;
|
||||
if (version.startsWith("2.")) {
|
||||
this.hintAdapter = new HintV2();
|
||||
} else if (version.startsWith("3.")) {
|
||||
this.hintAdapter = new HintV3();
|
||||
}
|
||||
}
|
||||
private inspector: Inspector = null;
|
||||
constructor(inspector: Inspector) {
|
||||
this.inspector = inspector;
|
||||
document.addEventListener(DocumentEvent.InspectorClear, () => {
|
||||
this.cleanHover();
|
||||
this.cleanSelected();
|
||||
});
|
||||
document.addEventListener(DocumentEvent.GameInspectorBegan, (event: CustomEvent) => {
|
||||
const el = this.getTargetElement();
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cursor = el.style.cursor;
|
||||
el.style.cursor = "zoom-in";
|
||||
|
||||
const mousedown = (event: MouseEvent) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
el.removeEventListener("mousedown", mousedown, true);
|
||||
el.removeEventListener("mousemove", mousemove, true);
|
||||
el.style.cursor = cursor;
|
||||
const e = new CustomEvent(DocumentEvent.GameInspectorEnd);
|
||||
document.dispatchEvent(e);
|
||||
|
||||
if (event.button === 0) {
|
||||
// 左键拾取
|
||||
this.updateHintDown(event, el);
|
||||
} else {
|
||||
this.updateHitMoveThrottle.cancel();
|
||||
// 其他按键取消
|
||||
this.cleanHover();
|
||||
}
|
||||
};
|
||||
const mousemove = (event: MouseEvent) => {
|
||||
this.updateHitMoveThrottle(event, el);
|
||||
};
|
||||
|
||||
el.addEventListener("mousemove", mousemove, true);
|
||||
el.addEventListener("mousedown", mousedown, true);
|
||||
});
|
||||
}
|
||||
private updateHitMoveThrottle = throttle(this.updateHintMove, 300);
|
||||
private updateHintMove(event: MouseEvent, canvas: HTMLCanvasElement) {
|
||||
const nodes = this.getMouseNodes(event, canvas);
|
||||
if (nodes.length) {
|
||||
const node = nodes[0];
|
||||
this.setHover(node);
|
||||
}
|
||||
}
|
||||
private getMouseNodes(event: MouseEvent, canvas: HTMLCanvasElement): Array<any> {
|
||||
this.inspector.updateTreeInfo(false);
|
||||
const { x, y } = this.hintAdapter.convertMousePos(event, canvas);
|
||||
const nodes = [];
|
||||
this.inspector.forEachNode((node) => {
|
||||
const b = this.hintAdapter.hitTest(node, x, y);
|
||||
if (b && node.active && node.activeInHierarchy) {
|
||||
nodes.push(node);
|
||||
}
|
||||
});
|
||||
nodes.reverse();
|
||||
return nodes;
|
||||
}
|
||||
private updateHintDown(event: MouseEvent, canvas: HTMLCanvasElement) {
|
||||
this.cleanHover();
|
||||
this.cleanSelected();
|
||||
const nodes = this.getMouseNodes(event, canvas);
|
||||
const pickTop = toRaw(appStore().config.pickTop);
|
||||
if (nodes.length === 1 || (pickTop && nodes.length)) {
|
||||
const item = nodes[0];
|
||||
this.cleanHover();
|
||||
this.setSelected(item);
|
||||
this.sendInspectNodeMsg(item);
|
||||
} else {
|
||||
const menu = nodes.map((item) => {
|
||||
const path = this.getPath(item);
|
||||
return {
|
||||
name: path,
|
||||
callback: () => {
|
||||
this.cleanHover();
|
||||
this.setSelected(item);
|
||||
this.sendInspectNodeMsg(item);
|
||||
},
|
||||
enter: () => {
|
||||
this.setHover(item);
|
||||
},
|
||||
leave: () => {
|
||||
this.cleanHover();
|
||||
},
|
||||
} as IUiMenuItem;
|
||||
});
|
||||
ccui.menu.showMenuByMouseEvent(event, menu, 0.8);
|
||||
}
|
||||
}
|
||||
private sendInspectNodeMsg(node: any) {
|
||||
if (node.uuid) {
|
||||
this.inspector.sendMsgToContent(Msg.InspectNode, node.uuid);
|
||||
}
|
||||
}
|
||||
private getPath(node: any) {
|
||||
let path = [];
|
||||
let parent = node;
|
||||
while (parent) {
|
||||
path.push(parent.name);
|
||||
parent = parent.parent;
|
||||
}
|
||||
path = path.reverse();
|
||||
return path.join("/");
|
||||
}
|
||||
private getTargetElement(): HTMLCanvasElement | null {
|
||||
// @ts-ignore
|
||||
if (typeof cc !== "undefined" && cc.game && cc.game.canvas) {
|
||||
// @ts-ignore
|
||||
return cc.game.canvas;
|
||||
} else {
|
||||
null;
|
||||
}
|
||||
}
|
||||
public cleanHover() {
|
||||
this.hoverNodes = [];
|
||||
this.hintAdapter && this.hintAdapter.clear();
|
||||
}
|
||||
public cleanSelected() {
|
||||
this.selectedNodes = [];
|
||||
this.hintAdapter && this.hintAdapter.clear();
|
||||
}
|
||||
private hoverNodes = [];
|
||||
private selectedNodes = [];
|
||||
|
||||
public update() {
|
||||
if (!this.hintAdapter) {
|
||||
return;
|
||||
}
|
||||
this.hintAdapter.initDrawNode();
|
||||
if (!this.hintAdapter.isDrawValid()) {
|
||||
return;
|
||||
}
|
||||
this.hintAdapter.clear();
|
||||
this.hintAdapter.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.hintAdapter.drawRect(points, {
|
||||
fill: true,
|
||||
fillColor: "#00ff0099",
|
||||
stroke: true,
|
||||
strokeColor: "#ff000099",
|
||||
});
|
||||
}
|
||||
public setHover(node: any) {
|
||||
if (node.isValid) {
|
||||
this.hoverNodes = [node];
|
||||
}
|
||||
}
|
||||
public setSelected(node: any) {
|
||||
if (node.isValid) {
|
||||
this.selectedNodes = [node];
|
||||
}
|
||||
}
|
||||
|
||||
private hintNode(node: any, opts: DrawOptions) {
|
||||
const points = this.hintAdapter.getRectPoints(node);
|
||||
if (!points) {
|
||||
return;
|
||||
}
|
||||
this.hintAdapter.drawRect(points, opts);
|
||||
}
|
||||
}
|
||||
4
src/scripts/inject/index.ts
Normal file
4
src/scripts/inject/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { Inspector } from "./inspector";
|
||||
const inspector = new Inspector();
|
||||
inspector.init();
|
||||
window["CCInspector"] = inspector;
|
||||
56
src/scripts/inject/inject-view.ts
Normal file
56
src/scripts/inject/inject-view.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import ccui from "@xuyanfeng/cc-ui";
|
||||
import "@xuyanfeng/cc-ui/dist/ccui.css";
|
||||
import "@xuyanfeng/cc-ui/iconfont/iconfont.css";
|
||||
import { createPinia } from "pinia";
|
||||
import { createApp } from "vue";
|
||||
import { DocumentEvent } from "../const";
|
||||
import App from "../inject-view/app.vue";
|
||||
export class InjectView {
|
||||
private _inited = false;
|
||||
private css: string[] = [];
|
||||
private hasLoadCss = false;
|
||||
constructor() {
|
||||
document.addEventListener(DocumentEvent.LoadInjectCss, (event: CustomEvent) => {
|
||||
const cssArray: string[] = event.detail;
|
||||
this.css = cssArray;
|
||||
this.loadCss();
|
||||
});
|
||||
}
|
||||
public init() {
|
||||
if (this._inited) {
|
||||
return;
|
||||
}
|
||||
this._inited = true;
|
||||
this.createUI();
|
||||
}
|
||||
private loadCss() {
|
||||
if (this.hasLoadCss) {
|
||||
return;
|
||||
}
|
||||
if (this.css.length === 0) {
|
||||
return;
|
||||
}
|
||||
this.hasLoadCss = true;
|
||||
this.css.forEach((css) => {
|
||||
const link = document.createElement("link");
|
||||
link.href = css;
|
||||
link.rel = "stylesheet";
|
||||
document.head.appendChild(link);
|
||||
});
|
||||
}
|
||||
private createUI() {
|
||||
const el = document.createElement("div");
|
||||
el.setAttribute("app", "");
|
||||
el.style.zIndex = "9000";
|
||||
document.body.appendChild(el);
|
||||
// load css
|
||||
this.loadCss();
|
||||
// vue
|
||||
const app = createApp(App);
|
||||
app.use(createPinia());
|
||||
// ccui.uiElement.setDoc(document);
|
||||
app.use(ccui);
|
||||
app.mount(el);
|
||||
}
|
||||
}
|
||||
export const injectView = new InjectView();
|
||||
38
src/scripts/inject/inspect-list.ts
Normal file
38
src/scripts/inject/inspect-list.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
export class InspectTarget {
|
||||
private list = [];
|
||||
|
||||
/**
|
||||
* 是否启用过滤
|
||||
*/
|
||||
enabled: boolean = false;
|
||||
addInspectType(item: any) {
|
||||
if (!this.list.find((el) => item === el)) {
|
||||
this.list.push(item);
|
||||
}
|
||||
console.log(this.list);
|
||||
}
|
||||
|
||||
removeInspectType(item: any) {
|
||||
this.list.splice(this.list.indexOf(item), 1);
|
||||
console.log(this.list);
|
||||
}
|
||||
cleanInspectType() {
|
||||
this.list.length = 0;
|
||||
}
|
||||
isContainInspectType(type: any) {
|
||||
return !!this.list.find((el) => type === el);
|
||||
}
|
||||
|
||||
checkNodeComponentsIsInList(node: any) {
|
||||
const comps = node._components;
|
||||
for (let i = 0; i < comps.length; i++) {
|
||||
const comp = comps[i];
|
||||
if (this.list.find((el) => comp instanceof el)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export const inspectTarget = new InspectTarget();
|
||||
1050
src/scripts/inject/inspector.ts
Normal file
1050
src/scripts/inject/inspector.ts
Normal file
File diff suppressed because it is too large
Load Diff
99
src/scripts/inject/setValue.ts
Normal file
99
src/scripts/inject/setValue.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { isVersion3 } from "./util";
|
||||
|
||||
interface ConfigItem {
|
||||
path: string[],
|
||||
func: Function;
|
||||
}
|
||||
|
||||
const config: ConfigItem[] = [
|
||||
{
|
||||
path: ["position", "x"],
|
||||
func: (target: any, value: any) => {
|
||||
let pos = target.getPosition();
|
||||
pos.x = value;
|
||||
target.setPosition(pos);
|
||||
}
|
||||
},
|
||||
{
|
||||
path: ["position", "y"],
|
||||
func: (target: any, value: any) => {
|
||||
let pos = target.getPosition();
|
||||
pos.y = value;
|
||||
target.setPosition(pos);
|
||||
}
|
||||
},
|
||||
{
|
||||
path: ["position", "z"],
|
||||
func: (target: any, value: any) => {
|
||||
let pos = target.getPosition();
|
||||
pos.z = value;
|
||||
target.setPosition(pos);
|
||||
}
|
||||
},
|
||||
{
|
||||
path: ["scale", "x"],
|
||||
func: ((target: any, value: any) => {
|
||||
let scale = target.getScale();
|
||||
scale.x = value;
|
||||
target.setScale(scale);
|
||||
})
|
||||
},
|
||||
{
|
||||
path: ["scale", "y"],
|
||||
func: ((target: any, value: any) => {
|
||||
let scale = target.getScale();
|
||||
scale.y = value;
|
||||
target.setScale(scale);
|
||||
})
|
||||
},
|
||||
{
|
||||
path: ["scale", "z"],
|
||||
func: ((target: any, value: any) => {
|
||||
let scale = target.getScale();
|
||||
scale.z = value;
|
||||
target.setScale(scale);
|
||||
})
|
||||
}
|
||||
]
|
||||
|
||||
// 3.x不允许直接设置xyz,需要走setPosition
|
||||
export function trySetValueWithConfig(pathArray: string[], targetObject: any, targetValue: any) {
|
||||
if (isVersion3()) {
|
||||
let fullPath: string = pathArray.toString()
|
||||
let item = config.find(el => {
|
||||
return fullPath.endsWith(el.path.toString())
|
||||
});
|
||||
if (item) {
|
||||
// 将多余的path去掉
|
||||
let leftPathArray = [];
|
||||
let max = pathArray.length - item.path.length;
|
||||
for (let i = 0; i < max; i++) {
|
||||
leftPathArray.push(pathArray[i])
|
||||
}
|
||||
|
||||
let pathObjectValue = getValue(targetObject, leftPathArray);
|
||||
if (pathObjectValue) {
|
||||
try {
|
||||
item.func(pathObjectValue, targetValue);
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getValue(target: any, path: string[]) {
|
||||
for (let i = 0; i < path.length; i++) {
|
||||
let key = path[i];
|
||||
if (target[key] !== undefined || target.hasOwnProperty(key)) {
|
||||
target = target[key]
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
43
src/scripts/inject/types.ts
Normal file
43
src/scripts/inject/types.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { ArrayData, ImageData, Info, ObjectData, Vec2Data, Vec3Data } from "../../views/devtools/data";
|
||||
|
||||
export interface BuildObjectOptions {
|
||||
path: string[];
|
||||
value: Object;
|
||||
data: ObjectData;
|
||||
}
|
||||
|
||||
export interface BuildArrayOptions {
|
||||
path: string[];
|
||||
value: Object;
|
||||
data: ArrayData;
|
||||
keys: number[];
|
||||
}
|
||||
|
||||
export interface BuildVecOptions {
|
||||
path: string[];
|
||||
keys: Array<{
|
||||
key: string;
|
||||
/**
|
||||
* 分量使用的步进值,优先使用,主要是为了实现不同分量不同的步进
|
||||
*/
|
||||
step?: (key: string) => number;
|
||||
/**
|
||||
* 分量是否可以调整
|
||||
*/
|
||||
disabled?: (key: string, item: Info) => boolean;
|
||||
}>;
|
||||
/**
|
||||
* 所有的vec统一使用的步进值
|
||||
*/
|
||||
step?: number;
|
||||
ctor: Function;
|
||||
value: Object;
|
||||
data: Vec3Data | Vec2Data;
|
||||
}
|
||||
|
||||
export interface BuildImageOptions {
|
||||
path: string[];
|
||||
ctor: Function;
|
||||
value: Object;
|
||||
data: ImageData;
|
||||
}
|
||||
23
src/scripts/inject/util.ts
Normal file
23
src/scripts/inject/util.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
declare const cc: any;
|
||||
|
||||
export function isVersion3() {
|
||||
if (typeof cc.ENGINE_VERSION === "string") {
|
||||
const version: string = cc.ENGINE_VERSION;
|
||||
return version.startsWith("3.")
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isHasProperty(base: Object, key: string): boolean {
|
||||
let ret = Object.getOwnPropertyDescriptor(base, key)
|
||||
if (ret) {
|
||||
return true;
|
||||
} else {
|
||||
let proto = Object.getPrototypeOf(base);
|
||||
if (proto) {
|
||||
return isHasProperty(proto, key)
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user