追加在场景中选中节点的工具,增强易用性

This commit is contained in:
xu_yanfeng 2025-01-23 17:56:02 +08:00
parent 88cdcf1a8e
commit ef6fb9f517
6 changed files with 170 additions and 18 deletions

View File

@ -101,6 +101,10 @@ export enum Msg {
* ID
*/
GetTabID = "GetTabID",
/**
*
*/
InspectNode = "inspect-node",
/**
*
*/

View File

@ -12,6 +12,8 @@ export enum DocumentEvent {
EngineVersion = "engineVersion",
GoogleAnalytics = "googleAnalytics",
LoadInjectCss = "load-inject-css",
GameInspectorBegan = "GameInspectorBegan",
GameInspectorEnd = "GameInspectorEnd",
}
export interface GoogleAnalyticsData {
event: GA_EventName;

View File

@ -1,26 +1,28 @@
<template>
<div class="ad" ref="rootEl" v-show="!picking" @mouseleave="onMouseLeaveRoot">
<div class="ad" ref="rootEl" v-show="!picking" @mouseleave="onMouseLeaveRoot" @mousedown="onMouseDown" @mouseenter="onMouseEnterCocosLogo">
<div class="title">
<div class="btns" v-show="showBtns">
<div v-for="(item, index) in listArray" :key="index" class="list" @click="item.cb" :title="item.txt">
<i class="iconfont icon" :class="item.icon"></i>
</div>
</div>
<i class="iconfont icon_cocos cocos" @mousedown="onMouseDown" @mouseenter="onMouseEnterCocosLogo"></i>
<i class="iconfont icon_cocos cocos"></i>
</div>
<!-- <Memory></Memory> -->
<CCDialog></CCDialog>
<CCMenu></CCMenu>
</div>
</template>
<script lang="ts">
import ccui from "@xuyanfeng/cc-ui";
import { defineComponent, onMounted, ref, toRaw } from "vue";
import { GA_EventName } from "../../ga/type";
import { DocumentEvent } from "../const";
import Ad from "./ad.vue";
import Banner from "./banner.vue";
import Memory from "./memory.vue";
import { ga } from "./util";
const { CCDialog } = ccui.components;
const { CCDialog, CCMenu } = ccui.components;
interface ListItem {
icon: string;
txt: string;
@ -28,7 +30,7 @@ interface ListItem {
}
export default defineComponent({
name: "ad",
components: { CCDialog, Banner, Memory },
components: { CCDialog, Banner, Memory, CCMenu },
setup() {
const keyAssistant = "assistant";
@ -41,6 +43,7 @@ export default defineComponent({
title: "Recommended Plugins",
comp: Ad,
width: 310,
height: 500,
closeCB: () => {
ga(GA_EventName.CloseAd);
},
@ -54,16 +57,28 @@ export default defineComponent({
ga(GA_EventName.DoInspector);
showBtns.value = false;
picking.value = true;
const cursor = document.body.style.cursor;
document.body.style.cursor = "zoom-in";
document.addEventListener("mousedown", () => {
document.body.style.cursor = cursor;
picking.value = false;
});
if (false) {
testInspector();
} else {
const event = new CustomEvent(DocumentEvent.GameInspectorBegan);
document.dispatchEvent(event);
}
},
},
]);
document.addEventListener(DocumentEvent.GameInspectorEnd, () => {
picking.value = false;
});
function testInspector() {
const cursor = document.body.style.cursor;
document.body.style.cursor = "zoom-in";
function test(event: MouseEvent) {
document.removeEventListener("mousedown", test, true);
document.body.style.cursor = cursor;
picking.value = false;
}
document.addEventListener("mousedown", test, true);
}
function recoverAssistantTop() {
const top = Number(localStorage.getItem(keyAssistant) || "0");
updateAssistantTop(top);

View File

@ -1,3 +1,8 @@
import ccui from "@xuyanfeng/cc-ui";
import { IUiMenuItem } from "@xuyanfeng/cc-ui/types/cc-menu/const";
import { DocumentEvent } from "../const";
import { Inspector } from "./inspector";
import { Msg } from "../../core/types";
declare const cc: any;
class Point {
x: number;
@ -31,6 +36,104 @@ interface DrawOptions {
export class Hint {
private draw = null;
public engineVersion: string = "";
private inspector: Inspector = null;
constructor(inspector: Inspector) {
this.inspector = inspector;
document.addEventListener(DocumentEvent.GameInspectorBegan, (event: CustomEvent) => {
const el = this.getTargetElement();
if (!el) {
return;
}
const cursor = el.style.cursor;
el.style.cursor = "zoom-in";
const test = (event: MouseEvent) => {
event.stopPropagation();
event.preventDefault();
el.removeEventListener("mousedown", test, true);
el.style.cursor = cursor;
const e = new CustomEvent(DocumentEvent.GameInspectorEnd);
document.dispatchEvent(e);
this.updateHint(event, el);
};
el.addEventListener("mousedown", test, true);
});
}
private nodeVisible(node) {
let parent = node;
while (parent) {
if (parent) {
}
}
}
private updateHint(event: MouseEvent, canvas: HTMLCanvasElement) {
this.cleanHover();
this.cleanSelected();
const rect = canvas.getBoundingClientRect();
let x = event.clientX - rect.x;
let y = rect.y + rect.height - event.clientY;
x *= window.devicePixelRatio;
y *= window.devicePixelRatio;
this.inspector.updateTreeInfo(false);
const nodes = [];
this.inspector.forEachNode((item) => {
const b = item._uiProps?.uiTransformComp?.hitTest({ x, y }, 0);
if (b && item.active && item.activeInHierarchy) {
nodes.push(item);
}
});
if (nodes.length === 1) {
const item = nodes[0];
this.setSelected(item);
this.sendInspectNodeMsg(item);
} else {
nodes.reverse();
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;
}
}
private get isEngineV2() {
return this.engineVersion.startsWith("2.");
}
@ -122,10 +225,14 @@ export class Hint {
});
}
public setHover(node: any) {
this.hoverNodes = [node];
if (node.isValid) {
this.hoverNodes = [node];
}
}
public setSelected(node: any) {
this.selectedNodes = [node];
if (node.isValid) {
this.selectedNodes = [node];
}
}
private getRectPoints(node: any): RectPoints | null {
if (this.isEngineV2) {

View File

@ -12,7 +12,7 @@ declare const cc: any;
export class Inspector extends InjectEvent {
inspectorGameMemoryStorage: Record<string, any> = {};
private hint: Hint = new Hint();
private hint: Hint = new Hint(this);
private getAtlasViewFunction() {
// 之前只有v2版本支持
@ -148,6 +148,7 @@ export class Inspector extends InjectEvent {
console.log(...this.terminal.init());
this.watchIsCocosGame();
}
private watchIsCocosGame() {
const timer = setInterval(() => {
const b = this._isCocosGame();
@ -195,22 +196,30 @@ export class Inspector extends InjectEvent {
this.sendEngineVersion(version);
}
}
updateTreeInfo() {
forEachNode(cb: (node: any) => void) {
for (let key in this.inspectorGameMemoryStorage) {
const item = this.inspectorGameMemoryStorage[key];
if (item && item.isValid && item instanceof cc.Node) {
cb(item);
}
}
}
updateTreeInfo(notify: boolean = true) {
let isCocosCreatorGame = this._isCocosGame();
if (isCocosCreatorGame) {
let scene = cc.director.getScene();
if (scene) {
let treeData = new TreeData();
this.getNodeChildren(scene, treeData);
this.sendMsgToContent(Msg.ResponseTreeInfo, treeData as ResponseTreeInfoData);
notify && this.sendMsgToContent(Msg.ResponseTreeInfo, treeData as ResponseTreeInfoData);
} else {
let treeData = new TreeData();
treeData.id = "";
treeData.text = "empty scene";
this.sendMsgToContent(Msg.ResponseTreeInfo, treeData as ResponseTreeInfoData);
notify && this.sendMsgToContent(Msg.ResponseTreeInfo, treeData as ResponseTreeInfoData);
}
} else {
this.notifySupportGame(false);
notify && this.notifySupportGame(false);
}
}

View File

@ -30,6 +30,7 @@ import { EngineData, TreeData } from "./data";
import GameInfo from "./game-info.vue";
import { appStore } from "./store";
import { Timer } from "./timer";
import { HandExpandOptions } from "@xuyanfeng/cc-ui/types/cc-tree/const";
const { CCTree, CCFootBar, CCDock, CCDialog, CCInput, CCButton, CCInputNumber, CCSelect, CCButtonGroup, CCCheckBox, CCColor, CCDivider } = ccui.components;
export default defineComponent({
name: "hierarchy",
@ -71,6 +72,18 @@ export default defineComponent({
treeData.value = [];
selectedUUID = null;
}
function onInspectNode(data: PluginEvent) {
const uuid = data.data as string;
if (!uuid) {
return;
}
updateSelect(uuid);
nextTick(() => {
if (elTree.value) {
elTree.value.handExpand(uuid, { highlight: true, select: true, scroll: true } as HandExpandOptions);
}
});
}
onMounted(() => {
if (elTree.value) {
const el = toRaw(elTree.value);
@ -80,6 +93,7 @@ export default defineComponent({
Bus.on(BusMsg.ChangeContent, changeContent);
Bus.on(BusMsg.ShowPlace, funcShowPlace);
Bus.on(BusMsg.EnableSchedule, funcEnableSchedule);
bridge.on(Msg.InspectNode, onInspectNode);
if (config.value.refreshHirarchy) {
timer.create(true);
} else {
@ -93,6 +107,7 @@ export default defineComponent({
Bus.off(BusMsg.ChangeContent, changeContent);
Bus.off(BusMsg.ShowPlace, funcShowPlace);
Bus.off(BusMsg.EnableSchedule, funcEnableSchedule);
bridge.off(Msg.InspectNode, onInspectNode);
timer.clean();
});
function _expand(uuid: string) {