mirror of
https://github.com/tidys/cc-inspector-chrome
synced 2025-04-16 07:01:03 +00:00
鼠标滑过节点树,游戏高亮显示对应的节点
This commit is contained in:
parent
342d8b6f1c
commit
967fda7164
@ -102,6 +102,14 @@ export enum Msg {
|
||||
* 获取页面ID
|
||||
*/
|
||||
GetTabID = "GetTabID",
|
||||
/**
|
||||
* 鼠标滑过节点
|
||||
*/
|
||||
HoverNode = "hover-node",
|
||||
/**
|
||||
* 选中节点
|
||||
*/
|
||||
SelectNode = "select-node",
|
||||
/**
|
||||
* 更新页面的frame
|
||||
*/
|
||||
|
268
cc-inspector/src/scripts/inject/hint.ts
Normal file
268
cc-inspector/src/scripts/inject/hint.ts
Normal file
@ -0,0 +1,268 @@
|
||||
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();
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ import { uniq } from "lodash";
|
||||
import { Msg, PluginEvent, RequestLogData, RequestNodeInfoData, RequestSetPropertyData, ResponseGameInfoData, ResponseNodeInfoData, ResponseSetPropertyData, ResponseSupportData, ResponseTreeInfoData } from "../../core/types";
|
||||
import { ArrayData, BoolData, ColorData, DataType, EngineData, Group, ImageData, Info, InvalidData, NodeInfoData, NumberData, ObjectCircleData, ObjectData, Property, StringData, TreeData, Vec2Data, Vec3Data, Vec4Data } from "../../views/devtools/data";
|
||||
import { InjectEvent } from "./event";
|
||||
import { Hint } from "./hint";
|
||||
import { injectView } from "./inject-view";
|
||||
import { getValue, trySetValueWithConfig } from "./setValue";
|
||||
import { BuildArrayOptions, BuildImageOptions, BuildObjectOptions, BuildVecOptions } from "./types";
|
||||
@ -11,6 +12,7 @@ declare const cc: any;
|
||||
|
||||
export class Inspector extends InjectEvent {
|
||||
inspectorGameMemoryStorage: Record<string, any> = {};
|
||||
private hint: Hint = new Hint();
|
||||
|
||||
private getAtlasViewFunction() {
|
||||
// 之前只有v2版本支持
|
||||
@ -104,6 +106,34 @@ export class Inspector extends InjectEvent {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Msg.HoverNode: {
|
||||
const uuid: string = pluginEvent.data;
|
||||
if (uuid) {
|
||||
const node = this.inspectorGameMemoryStorage[uuid];
|
||||
if (node.isValid) {
|
||||
this.hint.setHover(node);
|
||||
} else {
|
||||
this.hint.cleanHover();
|
||||
}
|
||||
} else {
|
||||
this.hint.cleanHover();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Msg.SelectNode: {
|
||||
const uuid: string = pluginEvent.data;
|
||||
if (uuid) {
|
||||
const node = this.inspectorGameMemoryStorage[uuid];
|
||||
if (node.isValid) {
|
||||
this.hint.setSelected(node);
|
||||
} else {
|
||||
this.hint.cleanSelected();
|
||||
}
|
||||
} else {
|
||||
this.hint.cleanSelected();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Msg.RequestDestroy: {
|
||||
const uuid: string = pluginEvent.data;
|
||||
const node = this.inspectorGameMemoryStorage[uuid];
|
||||
@ -124,14 +154,18 @@ export class Inspector extends InjectEvent {
|
||||
if (b) {
|
||||
clearInterval(timer);
|
||||
injectView.init();
|
||||
cc.director.on(cc.Director.EVENT_AFTER_DRAW, () => {
|
||||
this.hint.update();
|
||||
});
|
||||
const version = this.getEngineVersion();
|
||||
this.hint.engineVersion = version;
|
||||
if (b && version) {
|
||||
this.uploadEngineVersion(version);
|
||||
}
|
||||
}
|
||||
}, 300);
|
||||
}
|
||||
private getEngineVersion() {
|
||||
private getEngineVersion(): string {
|
||||
if (this._isCocosGame()) {
|
||||
return cc.ENGINE_VERSION || "";
|
||||
} else {
|
||||
@ -180,44 +214,6 @@ export class Inspector extends InjectEvent {
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
draw: cc.Graphics = null;
|
||||
|
||||
_drawRect(node: any) {
|
||||
let draw = this.draw;
|
||||
|
||||
if (!draw) {
|
||||
// @ts-ignore
|
||||
let node = new cc.Node("draw-node");
|
||||
// @ts-ignore
|
||||
cc.director.getScene().addChild(node);
|
||||
// @ts-ignore
|
||||
draw = this.draw = node.addComponent(cc.Graphics);
|
||||
}
|
||||
draw.clear();
|
||||
draw.lineWidth = 10;
|
||||
// @ts-ignore
|
||||
draw.strokeColor = new cc.Color().fromHEX("#ff0000");
|
||||
const { anchorX, anchorY, width, height, x, y } = node;
|
||||
let halfWidth = width / 2;
|
||||
let halfHeight = height / 2;
|
||||
let leftBottom = node.convertToWorldSpaceAR(cc.v2(-halfWidth, -halfHeight));
|
||||
let leftTop = node.convertToWorldSpaceAR(cc.v2(-halfWidth, halfHeight));
|
||||
let rightBottom = node.convertToWorldSpaceAR(cc.v2(halfWidth, -halfHeight));
|
||||
let rightTop = node.convertToWorldSpaceAR(cc.v2(halfWidth, halfHeight));
|
||||
|
||||
function line(began: any, end: any) {
|
||||
draw.moveTo(began.x, began.y);
|
||||
draw.lineTo(end.x, end.y);
|
||||
}
|
||||
|
||||
line(leftBottom, rightBottom);
|
||||
line(rightBottom, rightTop);
|
||||
line(rightTop, leftTop);
|
||||
line(leftTop, leftBottom);
|
||||
this.draw.stroke();
|
||||
}
|
||||
|
||||
// 收集节点信息
|
||||
getNodeChildren(node: any, data: TreeData) {
|
||||
data.id = node.uuid;
|
||||
|
@ -10,7 +10,7 @@
|
||||
<i class="matchCase iconfont icon_font_size" @click.stop="onChangeCase" title="match case" :style="{ color: matchCase ? 'red' : '' }"></i>
|
||||
</slot>
|
||||
</CCInput>
|
||||
<CCTree @contextmenu.prevent.stop="onMenu" style="flex: 1" ref="elTree" :expand-keys="expandedKeys" :default-expand-all="false" :value="treeData" @node-expand="onNodeExpand" @node-collapse="onNodeCollapse" @node-click="handleNodeClick" @node-unclick="handleNodeUnclick"></CCTree>
|
||||
<CCTree @contextmenu.prevent.stop="onMenu" style="flex: 1" ref="elTree" :expand-keys="expandedKeys" :default-expand-all="false" :value="treeData" @node-expand="onNodeExpand" @node-collapse="onNodeCollapse" @node-click="handleNodeClick" @node-unclick="handleNodeUnclick" @node-enter="handleNodeEnter" @node-leave="handleNodeLeave"></CCTree>
|
||||
</CCDock>
|
||||
</div>
|
||||
</template>
|
||||
@ -171,6 +171,7 @@ export default defineComponent({
|
||||
function updateSelect(uuid: string | null) {
|
||||
selectedUUID = uuid;
|
||||
Bus.emit(BusMsg.SelectNode, uuid);
|
||||
bridge.send(Msg.SelectNode, uuid);
|
||||
}
|
||||
const freshAuto = ref(config.value.refreshHirarchy);
|
||||
return {
|
||||
@ -192,6 +193,16 @@ export default defineComponent({
|
||||
handleNodeUnclick() {
|
||||
updateSelect(null);
|
||||
},
|
||||
handleNodeEnter(data: TreeData | null) {
|
||||
if (data) {
|
||||
bridge.send(Msg.HoverNode, data.id);
|
||||
}
|
||||
},
|
||||
handleNodeLeave(data: TreeData | null) {
|
||||
if (data) {
|
||||
bridge.send(Msg.HoverNode, null);
|
||||
}
|
||||
},
|
||||
handleNodeClick(data: TreeData | null) {
|
||||
if (data) {
|
||||
updateSelect(data.id);
|
||||
|
Loading…
x
Reference in New Issue
Block a user