From 5fcbdd626bdbaebc56f28f69762a65a09eff3023 Mon Sep 17 00:00:00 2001 From: xu_yanfeng Date: Tue, 11 Feb 2025 13:51:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A3=80=E7=B4=A2node=E7=9A=84touch=E3=80=81cl?= =?UTF-8?q?ick=E5=9B=9E=E8=B0=83=E4=BA=8B=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cc-plugin.config.ts | 2 ++ src/core/types.ts | 7 +++++ src/scripts/inject/code-hint.ts | 46 +++++++++++++++++++++++++++ src/scripts/inject/index.ts | 9 ++++++ src/scripts/inject/inspector.ts | 27 ++++++++++++++-- src/scripts/inject/types.ts | 7 +++++ src/views/devtools/data.ts | 8 +++++ src/views/devtools/hierarchy.vue | 54 +++++++++++++++++++++++++++++++- 8 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 src/scripts/inject/code-hint.ts diff --git a/cc-plugin.config.ts b/cc-plugin.config.ts index 152d2e2..480b5e6 100644 --- a/cc-plugin.config.ts +++ b/cc-plugin.config.ts @@ -11,6 +11,7 @@ const manifest: CocosPluginManifest = { name: pkgName, version: "2.1.7", description: "Debug games made with CocosCreator and display node trees and node properties", + store: "https://store.cocos.com/app/detail/2002", author: "xu_yanfeng", main: "./src/main.ts", panels: [ @@ -42,6 +43,7 @@ const manifest: CocosPluginManifest = { // googleAnalytics: "G-0S2X4Z1FE7", }, chrome: { + url: "https://chromewebstore.google.com/detail/cc-inspector/hejbkamkfnkifppoaljcidepkhgaahcj?authuser=0&hl=en", version: 3, pem: "./crx-key.pem", view_devtools: "src/views/devtools/index.ts", diff --git a/src/core/types.ts b/src/core/types.ts index 1ccd701..b93a28c 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -1,3 +1,4 @@ +import { ShowCode } from "../scripts/inject/types"; import { Chunk } from "../scripts/terminal"; import { FrameDetails, Info, NodeInfoData, TreeData } from "../views/devtools/data"; @@ -72,6 +73,7 @@ export interface ResponseUseFrameData { export type RequestSetPropertyData = Info; export type ResponseSetPropertyData = Info; export type RequestLogData = string[]; +export type RequestOpenNodeTouchFuntionData = { uuid: string; code: ShowCode }; export type ResponseErrorData = string; export enum Msg { None = "None", @@ -135,6 +137,11 @@ export enum Msg { RequestDynamicAtlasView = "request-dynamic-atlas-view", ResponseDynamicAtlasView = "response-dynamic-atlas-view", + + /** + * 请求在source面板打开节点的touch函数 + */ + RequestOpenNodeTouchFuntion = "request-open-node-touch-funtion", } export class PluginEvent { diff --git a/src/scripts/inject/code-hint.ts b/src/scripts/inject/code-hint.ts new file mode 100644 index 0000000..adeee65 --- /dev/null +++ b/src/scripts/inject/code-hint.ts @@ -0,0 +1,46 @@ +import { TreeData } from "../../views/devtools/data"; +import { ShowCode } from "./types"; +declare const cc: any; + +function getKey(code: ShowCode): string { + const map = {}; + map[ShowCode.TouchStart] = cc.Node.EventType.TOUCH_START; + map[ShowCode.TouchMove] = cc.Node.EventType.TOUCH_MOVE; + map[ShowCode.TouchEnd] = cc.Node.EventType.TOUCH_END; + map[ShowCode.TouchCancel] = cc.Node.EventType.TOUCH_CANCEL; + map[ShowCode.ButtonClick] = cc.Button.EventType.CLICK; + const key = map[code]; + return key || ""; +} + +export function getCallbacks(node: any, code: ShowCode) { + const key = getKey(code); + if (!key) { + return []; + } + if (!node._eventProcessor.bubblingTarget) { + return []; + } + const tables = node._eventProcessor.bubblingTarget._callbackTable[key]; + if (!tables) { + return []; + } + const funArray: Function[] = tables.callbackInfos; + if (!funArray || funArray.length === 0) { + return []; + } + if (funArray.length > 1) { + console.warn(`多个事件回调函数${funArray.length}`); + } + return funArray.map((fun) => { + // @ts-ignore + return fun.callback; + }); +} +export function calcCodeHint(node: any, data: TreeData) { + data.codeTouchStart = getCallbacks(node, ShowCode.TouchStart).length; + data.codeTouchMove = getCallbacks(node, ShowCode.TouchMove).length; + data.codeTouchEnd = getCallbacks(node, ShowCode.TouchEnd).length; + data.codeTouchCancel = getCallbacks(node, ShowCode.TouchCancel).length; + data.codeButtonClick = getCallbacks(node, ShowCode.ButtonClick).length; +} diff --git a/src/scripts/inject/index.ts b/src/scripts/inject/index.ts index 6492606..9e298bb 100644 --- a/src/scripts/inject/index.ts +++ b/src/scripts/inject/index.ts @@ -2,3 +2,12 @@ import { Inspector } from "./inspector"; const inspector = new Inspector(); inspector.init(); window["CCInspector"] = inspector; + +window["DoInspect"] = function () { + const t = inspector.target; + if (typeof t === "function") { + //@ts-ignore + inspect(t); + } + inspector.target = null; +}; diff --git a/src/scripts/inject/inspector.ts b/src/scripts/inject/inspector.ts index b16aa80..841f414 100644 --- a/src/scripts/inject/inspector.ts +++ b/src/scripts/inject/inspector.ts @@ -1,6 +1,6 @@ // eval 注入脚本的代码,变量尽量使用var,后来发现在import之后,let会自动变为var import { uniq } from "lodash"; -import { Msg, PluginEvent, RequestLogData, RequestNodeInfoData, RequestSetPropertyData, ResponseGameInfoData, ResponseNodeInfoData, ResponseSetPropertyData, ResponseSupportData, ResponseTreeInfoData } from "../../core/types"; +import { Msg, PluginEvent, RequestLogData, RequestNodeInfoData, RequestOpenNodeTouchFuntionData, RequestSetPropertyData, ResponseGameInfoData, ResponseNodeInfoData, ResponseSetPropertyData, ResponseSupportData, ResponseTreeInfoData } from "../../core/types"; import { CompType, getNodeIcon } from "../../views/devtools/comp"; import { ArrayData, BoolData, ColorData, DataType, EngineData, EnumData, Group, ImageData, Info, InvalidData, NodeInfoData, NumberData, ObjectCircleData, ObjectData, Property, StringData, TreeData, Vec2Data, Vec3Data, Vec4Data } from "../../views/devtools/data"; import { getEnumListConfig } from "./enumConfig"; @@ -9,11 +9,16 @@ import { Hint } from "./hint"; import { injectView } from "./inject-view"; import { inspectTarget } from "./inspect-list"; import { getValue, trySetValueWithConfig } from "./setValue"; -import { BuildArrayOptions, BuildImageOptions, BuildObjectOptions, BuildVecOptions } from "./types"; +import { BuildArrayOptions, BuildImageOptions, BuildObjectOptions, BuildVecOptions, ShowCode } from "./types"; import { isHasProperty } from "./util"; +import { calcCodeHint, getCallbacks } from "./code-hint"; declare const cc: any; export class Inspector extends InjectEvent { + /** + * 要inspect的函数 + */ + public target: Function = null; inspectorGameMemoryStorage: Record = {}; private hint: Hint = new Hint(this); @@ -101,6 +106,23 @@ export class Inspector extends InjectEvent { logFunction(value); break; } + case Msg.RequestOpenNodeTouchFuntion: { + const data: RequestOpenNodeTouchFuntionData = pluginEvent.data; + const node = this.inspectorGameMemoryStorage[data.uuid]; + if (!node || !node.isValid) { + return; + } + const funArray = getCallbacks(node, data.code); + if (funArray && funArray.length) { + // @ts-ignore + const fn = funArray[0]; + this.target = fn; + if (funArray.length !== 1) { + debugger; + } + } + break; + } case Msg.RequestLogCustom: { const logFunction = console.log; logFunction(pluginEvent.data); @@ -316,6 +338,7 @@ export class Inspector extends InjectEvent { data.text = node.name; data.icon = this.calcIcon(node); data.color = this.calcColor(node); + calcCodeHint(node, data); // @ts-ignore if (node instanceof cc.Scene) { // 场景不允许获取active,引擎会报错 diff --git a/src/scripts/inject/types.ts b/src/scripts/inject/types.ts index e89deef..e4ed74e 100644 --- a/src/scripts/inject/types.ts +++ b/src/scripts/inject/types.ts @@ -41,3 +41,10 @@ export interface BuildImageOptions { value: Object; data: ImageData; } +export enum ShowCode { + TouchStart = "touchstart", + TouchMove = "touchmove", + TouchEnd = "touchend", + TouchCancel = "touchcancel", + ButtonClick = "buttonclick", +} diff --git a/src/views/devtools/data.ts b/src/views/devtools/data.ts index f360c64..4b60a9c 100644 --- a/src/views/devtools/data.ts +++ b/src/views/devtools/data.ts @@ -523,6 +523,14 @@ export class TreeData implements ITreeData { id: string = ""; icon: string = ""; color: string = ""; + /** + * 回调的数量 + */ + codeTouchStart: number = 0; + codeTouchMove: number = 0; + codeTouchEnd: number = 0; + codeTouchCancel: number = 0; + codeButtonClick: number = 0; active: boolean = true; text: string = ""; children: TreeData[] = []; diff --git a/src/views/devtools/hierarchy.vue b/src/views/devtools/hierarchy.vue index 0aff868..d293f6a 100644 --- a/src/views/devtools/hierarchy.vue +++ b/src/views/devtools/hierarchy.vue @@ -22,9 +22,10 @@ import { HandExpandOptions } from "@xuyanfeng/cc-ui/types/cc-tree/const"; import Mousetrap, { MousetrapInstance } from "mousetrap"; import { storeToRefs } from "pinia"; import { defineComponent, nextTick, onMounted, onUnmounted, ref, toRaw, watch } from "vue"; -import { Msg, PluginEvent, RequestTreeInfoData, RequestUseFrameData, ResponseSetPropertyData, ResponseSupportData } from "../../core/types"; +import { Msg, PluginEvent, RequestOpenNodeTouchFuntionData, RequestTreeInfoData, RequestUseFrameData, ResponseSetPropertyData, ResponseSupportData } from "../../core/types"; import { ga } from "../../ga"; import { GA_EventName } from "../../ga/type"; +import { ShowCode } from "../../scripts/inject/types"; import { bridge } from "./bridge"; import { Bus, BusMsg } from "./bus"; import { RotateType } from "./const"; @@ -273,6 +274,57 @@ export default defineComponent({ }, onMenu(event: MouseEvent, data: TreeData) { const menus: IUiMenuItem[] = []; + if (data) { + function hintCode(type: ShowCode) { + bridge.send(Msg.RequestOpenNodeTouchFuntion, { uuid: data.id, code: type } as RequestOpenNodeTouchFuntionData); + chrome.devtools.inspectedWindow.eval(`DoInspect()`); + } + menus.push({ + name: `code button-click [${data.codeButtonClick}]`, + visible: !!data.codeButtonClick, + callback: (item) => { + ga.fireEventWithParam(GA_EventName.MouseMenu, ShowCode.ButtonClick); + hintCode(ShowCode.ButtonClick); + }, + }); + menus.push({ + name: `code touch-start [${data.codeTouchStart}]`, + visible: !!data.codeTouchStart, + callback: (item) => { + ga.fireEventWithParam(GA_EventName.MouseMenu, ShowCode.TouchStart); + hintCode(ShowCode.TouchStart); + }, + }); + menus.push({ + name: `code touch-move [${data.codeTouchMove}]`, + visible: !!data.codeTouchMove, + callback: (item) => { + ga.fireEventWithParam(GA_EventName.MouseMenu, ShowCode.TouchMove); + hintCode(ShowCode.TouchMove); + }, + }); + menus.push({ + name: `code touch-end [${data.codeTouchEnd}]`, + visible: !!data.codeTouchEnd, + callback: (item) => { + ga.fireEventWithParam(GA_EventName.MouseMenu, ShowCode.TouchEnd); + hintCode(ShowCode.TouchEnd); + }, + }); + menus.push({ + name: `code touch-cancel [${data.codeTouchCancel}]`, + visible: !!data.codeTouchCancel, + callback: (item) => { + ga.fireEventWithParam(GA_EventName.MouseMenu, ShowCode.TouchCancel); + hintCode(ShowCode.TouchCancel); + }, + }); + + if (data.codeButtonClick || data.codeTouchStart || data.codeTouchMove || data.codeTouchEnd || data.codeTouchCancel) { + menus.push({ type: ccui.menu.MenuType.Separator }); + } + } + menus.push({ name: "update hierarchy", enabled: true,