处理循环引用的obj

This commit is contained in:
xu_yanfeng 2025-01-07 18:28:15 +08:00
parent 16e1fdf89f
commit f51162db06
4 changed files with 59 additions and 10 deletions

View File

@ -1,7 +1,7 @@
// eval 注入脚本的代码,变量尽量使用var,后来发现在import之后,let会自动变为var // eval 注入脚本的代码,变量尽量使用var,后来发现在import之后,let会自动变为var
import { uniq } from "lodash"; import { uniq } from "lodash";
import { debugLog, Msg, PluginEvent, RequestLogData, RequestNodeInfoData, RequestSetPropertyData, ResponseNodeInfoData, ResponseSetPropertyData, ResponseSupportData, ResponseTreeInfoData } from "../../core/types"; import { debugLog, Msg, PluginEvent, RequestLogData, RequestNodeInfoData, RequestSetPropertyData, ResponseNodeInfoData, ResponseSetPropertyData, ResponseSupportData, ResponseTreeInfoData } from "../../core/types";
import { ArrayData, BoolData, ColorData, DataType, EngineData, Group, ImageData, Info, InvalidData, NodeInfoData, NumberData, ObjectData, Property, StringData, TreeData, Vec2Data, Vec3Data, Vec4Data } from "../../views/devtools/data"; 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 { InjectEvent } from "./event";
import { getValue, trySetValueWithConfig } from "./setValue"; import { getValue, trySetValueWithConfig } from "./setValue";
import { BuildArrayOptions, BuildImageOptions, BuildObjectOptions, BuildVecOptions } from "./types"; import { BuildArrayOptions, BuildImageOptions, BuildObjectOptions, BuildVecOptions } from "./types";
@ -421,11 +421,18 @@ export class Inspector extends InjectEvent {
} }
if (typeof propertyValue === "object") { if (typeof propertyValue === "object") {
// 空{} MaterialVariant 2.4.0 // 空{} MaterialVariant 2.4.0
info = this._buildObjectData({ try {
data: new ObjectData(), JSON.stringify(propertyValue);
path: path, info = this._buildObjectData({
value: propertyValue, data: new ObjectData(),
}); path: path,
value: propertyValue,
});
} catch {
// Object存在循环引用的情况
info = new ObjectCircleData();
}
if (info) { if (info) {
return make(info); return make(info);
} }

View File

@ -14,7 +14,7 @@ export enum DataType {
Invalid = "Invalid", Invalid = "Invalid",
Array = "Array", // 暂时在控制台打印下 Array = "Array", // 暂时在控制台打印下
Object = "Object", Object = "Object",
ObjectItem = "ObjectItem", ObjectCircle = "ObjectCircle",
Image = "Image", // 图片 Image = "Image", // 图片
Engine = "Engine", // 引擎的类型cc.Node, cc.Sprite, cc.Label等。。。 Engine = "Engine", // 引擎的类型cc.Node, cc.Sprite, cc.Label等。。。
} }
@ -72,6 +72,9 @@ export class Info {
public isObject(): boolean { public isObject(): boolean {
return false; return false;
} }
public isObjectCircle(): boolean {
return false;
}
public isImage(): boolean { public isImage(): boolean {
return false; return false;
} }
@ -203,6 +206,19 @@ export class ArrayData extends Info {
return true; return true;
} }
} }
export class ObjectCircleData extends Info {
constructor() {
super();
this.type = DataType.ObjectCircle;
}
parse(data: ObjectCircleData) {
super.parse(data);
return this;
}
public isObjectCircle(): boolean {
return true;
}
}
export class ObjectData extends Info { export class ObjectData extends Info {
/** /**
* object无限递归的情况 * object无限递归的情况
@ -553,7 +569,9 @@ export class Property {
case DataType.Invalid: case DataType.Invalid:
this.value = new InvalidData(data.value).parse(data.value as InvalidData); this.value = new InvalidData(data.value).parse(data.value as InvalidData);
break; break;
case DataType.ObjectItem: case DataType.ObjectCircle:
this.value = new ObjectCircleData().parse(data.value as ObjectCircleData);
break;
default: default:
throw new Error(`not support type: ${typeof data === "string" ? data : JSON.stringify(data)}`); throw new Error(`not support type: ${typeof data === "string" ? data : JSON.stringify(data)}`);
} }

View File

@ -1,7 +1,7 @@
import { v4 } from "uuid"; import { v4 } from "uuid";
import { Msg, Page, PluginEvent, RequestNodeInfoData, ResponseNodeInfoData, ResponseSupportData, ResponseTreeInfoData } from "../../../core/types"; import { Msg, Page, PluginEvent, RequestNodeInfoData, ResponseNodeInfoData, ResponseSupportData, ResponseTreeInfoData } from "../../../core/types";
import { VisibleProp } from "../comp"; import { VisibleProp } from "../comp";
import { ArrayData, BoolData, ColorData, EngineData, EnumData, Group, ImageData, Info, InvalidData, NodeInfoData, NumberData, ObjectData, Property, StringData, TextData, TreeData, Vec2Data, Vec3Data, Vec4Data } from "../data"; import { ArrayData, BoolData, ColorData, EngineData, EnumData, Group, ImageData, Info, InvalidData, NodeInfoData, NumberData, ObjectCircleData, ObjectData, Property, StringData, TextData, TreeData, Vec2Data, Vec3Data, Vec4Data } from "../data";
export class TestClient { export class TestClient {
recv(event: PluginEvent) {} recv(event: PluginEvent) {}
} }
@ -107,6 +107,10 @@ export class TestServer {
.buildChild("obj") // .buildChild("obj") //
.buildComponent("group-obj") .buildComponent("group-obj")
.buildProperty("object", new ObjectData().testNormal()); // .buildProperty("object", new ObjectData().testNormal()); //
this.testData
.buildChild("obj-circle")
.buildComponent("group-obj-circle") //
.buildProperty("circle", new ObjectCircleData());
this.testData this.testData
.buildChild("arr[arr]") .buildChild("arr[arr]")

View File

@ -18,6 +18,7 @@
<Engine v-if="value.isEngine()" v-model:data="(value as EngineData)"> </Engine> <Engine v-if="value.isEngine()" v-model:data="(value as EngineData)"> </Engine>
<div v-if="value.isObject() && !expand" class="objectDesc"></div> <div v-if="value.isObject() && !expand" class="objectDesc"></div>
<div v-if="value.isArray()" class="array">Array[{{ value.data.length }}]</div> <div v-if="value.isArray()" class="array">Array[{{ value.data.length }}]</div>
<div v-if="value.isObjectCircle()" class="circle-obj" @click="onLogToConsole">circle object can't display, click to log in console</div>
</div> </div>
</CCProp> </CCProp>
<div v-if="value && value.isArrayOrObject()"> <div v-if="value && value.isArrayOrObject()">
@ -32,7 +33,7 @@
import ccui from "@xuyanfeng/cc-ui"; import ccui from "@xuyanfeng/cc-ui";
import { Option } from "@xuyanfeng/cc-ui/types/cc-select/const"; import { Option } from "@xuyanfeng/cc-ui/types/cc-select/const";
import { defineComponent, onMounted, PropType, ref, toRaw, watch } from "vue"; import { defineComponent, onMounted, PropType, ref, toRaw, watch } from "vue";
import { Msg, RequestSetPropertyData } from "../../../core/types"; import { Msg, RequestLogData, RequestSetPropertyData } from "../../../core/types";
import { bridge } from "../bridge"; import { bridge } from "../bridge";
import { ArrayData, EngineData, EnumData, ImageData, Info, NumberData, ObjectData, Property, StringData, TextData, Vec2Data, Vec3Data } from "../data"; import { ArrayData, EngineData, EnumData, ImageData, Info, NumberData, ObjectData, Property, StringData, TextData, Vec2Data, Vec3Data } from "../data";
import Engine from "./property-engine.vue"; import Engine from "./property-engine.vue";
@ -139,6 +140,10 @@ export default defineComponent({
bridge.send(Msg.RequestSetProperty, raw as RequestSetPropertyData); bridge.send(Msg.RequestSetProperty, raw as RequestSetPropertyData);
} }
}, },
onLogToConsole() {
const data = toRaw(props.value.path);
bridge.send(Msg.RequestLogData, data as RequestLogData);
},
}; };
}, },
}); });
@ -178,6 +183,21 @@ export default defineComponent({
color: #d2d2d2; color: #d2d2d2;
font-size: 12px; font-size: 12px;
} }
.circle-obj {
user-select: none;
cursor: pointer;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 12px;
color: gray;
&:hover {
color: white;
}
&:active {
color: chocolate;
}
}
.vec { .vec {
width: 100%; width: 100%;