修复属性面板切换node,显示异常的bug

优化Image属性的显示
This commit is contained in:
xu_yanfeng 2024-12-11 21:05:49 +08:00
parent 05585163c0
commit 085e1528f0
7 changed files with 167 additions and 108 deletions

View File

@ -102,6 +102,14 @@ export class ArrayData extends Info {
test() { test() {
this.add(new Property("item1", new TextData("text"))); this.add(new Property("item1", new TextData("text")));
this.add(new Property("item2", new BoolData(true))); this.add(new Property("item2", new BoolData(true)));
this.add(new Property("item3", new NumberData(100)));
return this;
}
testSub() {
this.add(new Property("item1", new TextData("text")));
const sub = new ArrayData();
sub.add(new Property("sub", new StringData("sub")));
this.add(new Property('arr', sub));
return this; return this;
} }
public isArray(): boolean { return true; } public isArray(): boolean { return true; }
@ -266,12 +274,20 @@ export class Vec4Data extends Info {
} }
} }
export class ImageData extends Info { export class ImageData extends Info {
data: string | null = null; /**
* url路径
*/
data: string = "";
constructor() { constructor() {
super(); super();
this.type = DataType.Image; this.type = DataType.Image;
this.data = null; this.data = "";
return this;
}
test() {
const cocos = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAABz1JREFUaEO9WXuMHVUZ/32zfbHSQkDa3pkukALb7N6ZUjFGjBFjopCUBA1PRYyJaVIVMVTF3rlbhAh7z922EB8oVRKNlUcgSAwCMWAQlKg0msjOzPYFwdCdMy3U2tqy7Xbvzmfm7t7dO/fO7Jx799b5c77X73fOd77znXMIHfx04e6TttnbQZeZrihTowWFXMnbSRqulIX8/41ERwkYD7zVyxMn94B5WNrWuha4t63aUQIRCr3svQfmDzLwWmCbn2gbmaJhxwnkhrznKeT1UXxmeiEo5q9VxNKWWucJDA6/SpoWjXzVtwbtiVG7/9a20CkYdZSAIbztDP4SwEsBOmsmPk8+LIuXf10BT8sqHSPQUx65qsL8cnCJtxQ333zSEO5pBhbWEBHhfr9g3t0ywgyDjhBY9eBfzgrHlx0i0FHfzl8YxTSEV2KwXR9/krHpUNH8QSdJdISAUXLfZPAlXUsnjAN3XCFrAHXh+QDrdYAZC7puk3f1Pd4pEvMmkCt5zxPxegYOBraZiwH72d+79f8sOQGeWtDVj7mCicp6ec+HXuoEiXkRWFX2CiGziICMn72w7993rNnTCEoveb8H8TXRf6pFYzpVCSsfOTRwuTtfEm0TuFDsW13B6b0AFgD0nrTzy9PAGCX3fSZ018sZON61+JyLR7/Vc6T+v36/c4vcYj2pSqxtAkbJOcpE51Rr/YJFV47e1ft6WtAVg7tv7dImH2uW02Fp5y+o/58Tzh8D2/rUGSWgC2cEoL5qEKLDshAHkRRcF85+gC5NkI1K2+yZXfjuCWmbZ58xAnrJeRREX6wF6OpafM2B7172okpAXbiT1c256aN90s6vWbl9f782Me5J21TODGXFKObyoeHPLWB6Bjy9HBlHZNE8XwV8pGOUnB1MtDFZn97gEH8ljb/KpN0ZFPp/qOI3kUDP1v1XJ42qLpyx+haBuXJDUFz3jEqgmk792onZVZHQu2BeziHvCgasj6r4TSSgl71/yEL+w7HqINy3AVxc+0fgY75tnasSpF7nvAd29Sw53f1Oqh0DDJwIiuZSFd+JBHIl91hQNKsVJvp04TwHULwt1sKvyM1rf6kSpFEnJ7zXCPzxdFuCHO9fiHupkuU/lQBxZZMcWPeLlWX3do35oenueMof0XFZyC/Lcj6XXBfuxNQekvyF4B0HbetrWTFSCWiEYzx+3hW05Ihknu0qownmEHcGA5bSIksDkBMjGwjhI2lyIrziF8zM/SB9BoiWgVBdVPVBiHnML1ofyBoZFbkunFGAjERd5rdl0Vqd5WcOAlg2lTYc80EIv+fba+/Lcqwq14UbDzBtqFok5ibQgJ/BpwLbmj1pqaKcQ88Qw79maLc1qRAmZMFclBUiuYwK9wCAVU3GHG6VxbWbs5y2KjeEO8ZAfGAILAtmwq4d9548A8L9EwHTVyIz03Ba2ubiVsGp6Otl77dg/mwjNGnnMzuFZAKDziuk0SdjDhk/kUXzGyqAWtXJCfcgASua7LRFV8vNvXMefJQIEGHCV8jHVoHX9PWyVwFzV5N9iCE5YBbm8qtGABjzbbMjpbMRzKU/2r947P3xU0kgCfyCb1tzXowpEYicV8Lule8OrD7U7iin2eWE+yABm5LkDHICO7923jMQOSCiXX4hr9QhtkJSF94egNck2oQI5IBZvdXIDf3z+mBzc+ebUoW8pwh8U4PTM1KFdOFG6ZNc3QjHu/13LhjTL3qdWNvtF/u+0Eg0eR8ouQ+BcHv1GoFnN0oKsdEfMH/eyghn6erC4VijWGfAQIU4ul4Fpe0JiQQM4d7NwPcbgzNjJCia+SxQqnJj0LmWNXquWX/m/mVaxH+TtvWx5IWe8De3dWQDTSZ0iqRNykJ/agusCrymlys7TxPTDRl2FWmbM3esSilklJ0iQIN12TNjx4SdQcH8cqtgk/R14f0L4IuqsihTE/KBQE/6dv7zafFSt+pc2b2PGFuaDBn/lXWntfkQMYR7koElVR/NjW908tgRZBxq5uw19LK3DczfaQSpTeLG0S3mb+YDPrLVhTcJcGLDxuCdgW1lznRms6QL98cAGnug3dI2+9slYAztuZHDyk40dqA1h0RPyUL+FhX/mQSqI1Xyfgri2fMp81ECXvaLVtYCbMKgl4b3grTexJypZhL9zrfz16mAr2Wekq5ecraBKJ5OzBUCnlUhogtnOxF9M36+jocm8B982/qMEqBpJaUZqDnUB517odE9zQGqRB73E3I2N7Svj8LxFwGKH5Aaqg4Dfw5s86pWwLc0AzMkhLMdoG8nB+IKCL+SBWvDVOo5L4Ho01mgmGlXUGyvz2ppBmpAjLK3g5k3phZvILqQGgeg0oK/IW2z7Vf9tghMja77GAhN779N5Txlg5oejHlVs7ZSqD4d9JI7/XxEaUVlVr2eSPVym9+SBTPpvSAr42Lytmcg8rJi25vLuyZO7gVRi5e8fFjaVuxlpiXUdcr/A3Hqok9HdvAQAAAAAElFTkSuQmCC';
this.data = cocos;
return this; return this;
} }
public isImage(): boolean { return true; } public isImage(): boolean { return true; }

View File

@ -1,6 +1,6 @@
import { v4 } from "uuid"; import { v4 } from "uuid";
import { Msg, Page, PluginEvent } from "../../../core/types"; import { Msg, Page, PluginEvent } from "../../../core/types";
import { ArrayData, BoolData, ColorData, EngineData, EnumData, Group, Info, NodeInfoData, NumberData, ObjectData, ObjectItemRequestData, Property, StringData, TextData, TreeData, Vec2Data, Vec3Data, Vec4Data } from "../data"; import { ArrayData, BoolData, ColorData, EngineData, EnumData, Group, ImageData, Info, NodeInfoData, NumberData, ObjectData, ObjectItemRequestData, Property, StringData, TextData, TreeData, Vec2Data, Vec3Data, Vec4Data } from "../data";
export class TestClient { export class TestClient {
recv(event: PluginEvent) { recv(event: PluginEvent) {
@ -90,20 +90,28 @@ export class TestServer {
.buildProperty("string", new StringData("string")) .buildProperty("string", new StringData("string"))
.buildProperty("enum", new EnumData().test()) .buildProperty("enum", new EnumData().test())
.buildProperty("color", new ColorData('#f00')) .buildProperty("color", new ColorData('#f00'))
.buildProperty("array", new ArrayData().test()) .buildProperty("image", new ImageData().test())
.buildProperty("object", new ObjectData().test())
;
this.testData.buildChild('vec').buildComponent('group2') this.testData.buildChild('vec').buildComponent('group2')
.buildProperty("number", new NumberData(200)) .buildProperty("number", new NumberData(200))
.buildProperty("vec2", new Vec2Data().test()) .buildProperty("vec2", new Vec2Data().test())
.buildProperty("vec3", new Vec3Data().test()) .buildProperty("vec3", new Vec3Data().test())
.buildProperty("vec4", new Vec4Data().test()) .buildProperty("vec4", new Vec4Data().test())
this.testData.buildChild("obj/arr").buildComponent("group3")
this.testData.buildChild("engine").buildComponent("group3") .buildProperty("array", new ArrayData().test())
.buildProperty("object", new ObjectData().test())
.buildProperty("arr_arr", new ArrayData().testSub())
this.testData.buildChild("engine").buildComponent("group4")
.buildProperty("node", new EngineData().init('name', 'cc_Node', 'uuid')) .buildProperty("node", new EngineData().init('name', 'cc_Node', 'uuid'))
.buildProperty("sprite", new EngineData().init('name', 'cc_Sprite', 'uuid')) .buildProperty("sprite", new EngineData().init('name', 'cc_Sprite', 'uuid'))
.buildProperty("label", new EngineData().init('name', 'cc_Label', 'uuid')) .buildProperty("label", new EngineData().init('name', 'cc_Label', 'uuid'))
.buildProperty("un_known", new EngineData().init('name', 'un_known', 'uuid')) .buildProperty("un_known", new EngineData().init('name', 'un_known', 'uuid'))
const c = this.testData.buildChild("str1")
c.buildComponent("group51").buildProperty("str1", new StringData("str1"))
c.buildComponent("group52").buildProperty("num", new NumberData(200))
this.testData.buildChild("str2").buildComponent("group6")
.buildProperty("str2", new StringData("str2"))
} }
add(client: TestClient) { add(client: TestClient) {
this.clients.push(client); this.clients.push(client);

View File

@ -14,7 +14,7 @@
<script lang="ts"> <script lang="ts">
import ccui from "@xuyanfeng/cc-ui"; import ccui from "@xuyanfeng/cc-ui";
import { defineComponent, PropType, ref } from "vue"; import { defineComponent, PropType, ref, watch } from "vue";
import Bus, { BusMsg } from "../bus"; import Bus, { BusMsg } from "../bus";
import { Group } from "../data"; import { Group } from "../data";
import UiProp from "./ui-prop.vue"; import UiProp from "./ui-prop.vue";
@ -44,6 +44,12 @@ export default defineComponent({
fold.value = b; fold.value = b;
}); });
const fold = ref(false); const fold = ref(false);
watch(
() => props.group,
(v) => {
// console.log(v);
}
);
return { return {
fold, fold,
onLog() { onLog() {
@ -57,6 +63,7 @@ export default defineComponent({
<style scoped lang="less"> <style scoped lang="less">
.property-group { .property-group {
.print { .print {
cursor: pointer;
margin-right: 10px; margin-right: 10px;
&:hover { &:hover {
color: #ffffff; color: #ffffff;

View File

@ -0,0 +1,83 @@
<template>
<div v-if="data.isImage()" class="property-image">
<div class="box">
<img :src="data.data" alt="图片" class="img" />
</div>
<div class="url" :title="data.data">{{ data.data }}</div>
<div style="flex: 1"></div>
<i class="print iconfont icon_print" @click="onShowValueInConsole"></i>
</div>
</template>
<script lang="ts">
import { defineComponent, PropType } from "vue";
import { ImageData } from "../data";
export default defineComponent({
name: "property-image",
props: {
data: {
type: Object as PropType<ImageData>,
default: () => new ImageData().test(),
},
},
setup(props) {
return {
onShowValueInConsole() {
if (Array.isArray(props.data.path)) {
let uuid = props.data.path[0];
let key = props.data.path[1]; // todo key
if (uuid && key) {
chrome.devtools.inspectedWindow.eval(`window.CCInspector.logValue('${uuid}','${key}')`);
}
}
},
};
},
});
</script>
<style scoped lang="less">
.property-image {
display: flex;
overflow: hidden;
flex: 1;
flex-direction: row;
align-content: center;
align-items: center;
height: 30px;
.box {
display: flex;
flex-direction: row;
align-items: center;
min-width: 80px;
width: 80px;
justify-content: center;
.img {
height: 30px;
width: 30px;
object-fit: contain;
}
}
.url {
color: white;
font-weight: normal;
font-size: 12px;
overflow: hidden;
text-overflow: ellipsis;
}
.print {
cursor: pointer;
margin-right: 10px;
color: #d2d2d2;
&:hover {
color: #ffffff;
}
&:active {
color: #ffaa00;
}
}
}
</style>

View File

@ -29,12 +29,16 @@ export default defineComponent({
console.log(code); console.log(code);
} }
} }
watch(props.data, (newValue: NodeInfoData, oldValue: NodeInfoData) => { watch(
if (newValue.uuid !== oldValue.uuid) { () => props.data,
// node (newValue: NodeInfoData, oldValue: NodeInfoData) => {
Bus.emit(BusMsg.FoldAllGroup, false); // console.log(newValue);
if (newValue.uuid !== oldValue.uuid) {
// node
Bus.emit(BusMsg.FoldAllGroup, false);
}
} }
}); );
return {}; return {};
}, },
}); });

View File

@ -1,41 +0,0 @@
<template>
<div class="settings-prop">
<span class="label">{{ label }}</span>
<slot class="slot"></slot>
</div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
name: "SettingsProp",
props: {
label: {
type: String,
default: "",
},
},
});
</script>
<style scoped lang="less">
.settings-prop {
display: flex;
flex-direction: row;
align-items: center;
min-width: 300px;
margin: 2px 4px;
.label {
max-width: 80px;
min-width: 80px;
text-overflow: ellipsis;
white-space: nowrap;
}
.slot {
flex: 1;
}
}
</style>

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="ui-prop"> <div class="ui-prop">
<CCProp :name="name" :icon="icon" :head-width="headWidth" v-model:expand="expand" :arrow="value.isArrayOrObject()" :slide="value.isNumber()" :indent="indent * 10" @change-expand="onClickFold"> <CCProp :name="name" :icon="icon" :head-width="headWidth" v-model:expand="expand" :arrow="value && value.isArrayOrObject()" :slide="value && value.isNumber()" :indent="indent * 10" @change-expand="onClickFold">
<div class="prop-value"> <div class="prop-value" v-if="value">
<div v-if="value.isInvalid()" class="invalid"> <div v-if="value.isInvalid()" class="invalid">
{{ value.data }} {{ value.data }}
</div> </div>
@ -14,24 +14,13 @@
<CCSelect v-if="value.isEnum()" v-model:value="value.data" :disabled="value.readonly" :data="getEnumValues(value)" @change="onChangeValue"> </CCSelect> <CCSelect v-if="value.isEnum()" v-model:value="value.data" :disabled="value.readonly" :data="getEnumValues(value)" @change="onChangeValue"> </CCSelect>
<CCCheckBox v-if="value.isBool()" v-model:value="value.data" :disabled="value.readonly" @change="onChangeValue"> </CCCheckBox> <CCCheckBox v-if="value.isBool()" v-model:value="value.data" :disabled="value.readonly" @change="onChangeValue"> </CCCheckBox>
<CCColor v-if="value.isColor()" :show-color-text="true" :disabled="value.readonly" v-model:color="value.data" @change="onChangeValue"> </CCColor> <CCColor v-if="value.isColor()" :show-color-text="true" :disabled="value.readonly" v-model:color="value.data" @change="onChangeValue"> </CCColor>
<div v-if="value.isImage()" class="image-property"> <PropertyImage v-if="value.isImage()" v-model:data="(value as ImageData)"></PropertyImage>
<!-- TODO: 适配 -->
<div v-if="value.isImage() || true" placement="top" trigger="hover">
<div style="width: 100%; height: 100%; display: flex; flex-direction: row; align-items: center; justify-content: center">
<img :src="value.data" alt="图片" style="max-width: 100px; max-height: 100px; object-fit: contain" />
</div>
<img :src="value.data" style="height: 36px" alt="图片" />
</div>
<div style="flex: 1; display: flex; flex-direction: row-reverse">
<CCButton @click="onShowValueInConsole">log</CCButton>
</div>
</div>
<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">{{ value.data }}</div> <div v-if="value.isObject() && !expand" class="objectDesc">{{ value.data }}</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> </div>
</CCProp> </CCProp>
<div v-if="value.isArrayOrObject()"> <div v-if="value && value.isArrayOrObject()">
<div v-show="expand && subData"> <div v-show="expand && subData">
<UiProp v-for="(arr, index) in subData" :key="index" :indent="indent + 1" :value="arr.value" :name="getName(value.isArray(), arr)"> </UiProp> <UiProp v-for="(arr, index) in subData" :key="index" :indent="indent + 1" :value="arr.value" :name="getName(value.isArray(), arr)"> </UiProp>
</div> </div>
@ -42,16 +31,18 @@
<script lang="ts"> <script lang="ts">
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 { nextTick } from "process";
import { defineComponent, onMounted, onUnmounted, PropType, ref, toRaw, watch } from "vue"; import { defineComponent, onMounted, onUnmounted, PropType, ref, toRaw, watch } from "vue";
import { Msg } from "../../../core/types"; import { Msg } from "../../../core/types";
import Bus, { BusMsg } from "../bus"; import Bus, { BusMsg } from "../bus";
import { connectBackground } from "../connectBackground"; import { connectBackground } from "../connectBackground";
import { DataType, EngineData, EnumData, Info, NumberData, Property, StringData, TextData, Vec2Data, Vec3Data } from "../data"; import { DataType, EngineData, EnumData, ImageData, Info, NumberData, Property, StringData, TextData, Vec2Data, Vec3Data } from "../data";
import Engine from "./property-engine.vue"; import Engine from "./property-engine.vue";
import PropertyImage from "./property-image.vue";
const { CCInput, CCTextarea, CCProp, CCButton, CCInputNumber, CCSelect, CCCheckBox, CCColor } = ccui.components; const { CCInput, CCTextarea, CCProp, CCButton, CCInputNumber, CCSelect, CCCheckBox, CCColor } = ccui.components;
export default defineComponent({ export default defineComponent({
name: "ui-prop", name: "ui-prop",
components: { CCProp, Engine, CCTextarea, CCInput, CCButton, CCInputNumber, CCSelect, CCCheckBox, CCColor }, components: { PropertyImage, CCProp, Engine, CCTextarea, CCInput, CCButton, CCInputNumber, CCSelect, CCCheckBox, CCColor },
props: { props: {
name: { type: String, default: "" }, name: { type: String, default: "" },
indent: { type: Number, default: 0 }, indent: { type: Number, default: 0 },
@ -60,28 +51,31 @@ export default defineComponent({
arrow: { type: Boolean, default: false }, arrow: { type: Boolean, default: false },
step: { type: Number, default: 1 }, step: { type: Number, default: 1 },
value: { value: {
type: Object as PropType<Info | EngineData | EnumData | NumberData | StringData | TextData | Vec2Data | Vec3Data>, type: Object as PropType<Info | EngineData | EnumData | NumberData | StringData | TextData | Vec2Data | Vec3Data | ImageData>,
default: () => {}, default: () => new Info(),
}, },
}, },
setup(props, { emit }) { setup(props, { emit }) {
const { value, step } = props;
const expand = ref(false); const expand = ref(false);
onMounted(() => { onMounted(() => {
watchValue(); expand.value = false;
}); if (props.value.isArray()) {
function watchValue() { subData.value = props.value.data;
// fold.value = true;
if (value.isArray()) {
subData.value = value.data;
} else { } else {
subData.value = null; subData.value = null;
} }
}
watch(props.value, () => {
watchValue();
}); });
watch(
() => props.value,
(v) => {
expand.value = false;
if (v.isArray()) {
subData.value = v.data;
} else {
subData.value = null;
}
}
);
const subData = ref<Array<Property> | null>(null); const subData = ref<Array<Property> | null>(null);
return { return {
@ -100,10 +94,14 @@ export default defineComponent({
}, },
isImageValid() { isImageValid() {
return !!value.data; return !!props.value.data;
}, },
getName(isArray: boolean, arr: Property) { getName(isArray: boolean, arr: Property) {
if (!arr || !arr.value) {
// debugger;
return "xxx";
}
const type = arr.value.type; const type = arr.value.type;
if (isArray) { if (isArray) {
return arr.name; return arr.name;
@ -112,30 +110,22 @@ export default defineComponent({
} }
}, },
onClickFold(v: boolean) { onClickFold(v: boolean) {
if (value.isArray()) { if (props.value.isArray()) {
return; return;
} }
const s = toRaw(subData.value); const s = toRaw(subData.value);
const e = toRaw(expand.value); const e = toRaw(expand.value);
if (value.isObject() && s === null && e === true) { const rawValue = toRaw(props.value);
if (rawValue && rawValue.isObject() && s === null && e === true) {
// objectitem // objectitem
Bus.emit(BusMsg.RequestObjectData, toRaw(value), (info: Property[]) => { Bus.emit(BusMsg.RequestObjectData, rawValue, (info: Property[]) => {
subData.value = info; subData.value = info;
}); });
} }
}, },
onShowValueInConsole() {
if (Array.isArray(value.path)) {
let uuid = value.path[0];
let key = value.path[1]; // todo key
if (uuid && key) {
chrome.devtools.inspectedWindow.eval(`window.CCInspector.logValue('${uuid}','${key}')`);
}
}
},
onChangeValue() { onChangeValue() {
if (!value.readonly) { if (!props.value.readonly) {
connectBackground.postMessageToBackground(Msg.SetProperty, toRaw(value)); connectBackground.postMessageToBackground(Msg.SetProperty, toRaw(props.value));
} }
}, },
}; };
@ -207,14 +197,6 @@ export default defineComponent({
align-items: center; align-items: center;
} }
.image-property {
display: flex;
flex-direction: row;
align-content: center;
align-items: center;
height: 36px;
}
.slot { .slot {
display: flex; display: flex;
width: 100%; width: 100%;