From d3810fd51c2e09f2bf04371988c67fe9d6520c5d Mon Sep 17 00:00:00 2001 From: xiange Date: Sat, 7 Dec 2024 15:15:43 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=A6=84=20refactor:=20add=20findPropertyCo?= =?UTF-8?q?ntrol?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/expander/expander.ts | 2 +- packages/chili-ui/src/property/input.ts | 9 ++-- .../src/property/material/materialEditor.ts | 27 ++++------ .../src/property/material/textureEditor.ts | 20 ++++---- .../chili-ui/src/property/materialProperty.ts | 4 +- .../chili-ui/src/property/propertyView.ts | 45 +++++++++------- packages/chili-ui/src/property/utils.ts | 51 +++++++++++-------- 7 files changed, 84 insertions(+), 74 deletions(-) diff --git a/packages/chili-ui/src/components/expander/expander.ts b/packages/chili-ui/src/components/expander/expander.ts index f9317487..7bf50168 100644 --- a/packages/chili-ui/src/components/expander/expander.ts +++ b/packages/chili-ui/src/components/expander/expander.ts @@ -7,7 +7,7 @@ import style from "./expander.module.css"; export class Expander extends HTMLElement { private _isExpanded = true; - private expanderIcon: SVGSVGElement; + private readonly expanderIcon: SVGSVGElement; private readonly headerPanel = div({ className: style.headerPanel }); readonly contenxtPanel = div({ className: style.contextPanel }); diff --git a/packages/chili-ui/src/property/input.ts b/packages/chili-ui/src/property/input.ts index c5db8e8c..c91d92a9 100644 --- a/packages/chili-ui/src/property/input.ts +++ b/packages/chili-ui/src/property/input.ts @@ -66,9 +66,10 @@ export class InputProperty extends PropertyBase { readonly document: IDocument, objects: any[], readonly property: Property, + converter?: IConverter, ) { super(objects); - this.converter = property.converter ?? this.getConverter(); + this.converter = converter ?? this.getConverter(); let arrayConverter = new ArrayValueConverter(objects, property, this.converter); this.append( div( @@ -104,11 +105,11 @@ export class InputProperty extends PropertyBase { ); } - private handleBlur = (e: FocusEvent) => { + private readonly handleBlur = (e: FocusEvent) => { this.setValue(e.target as HTMLInputElement); }; - private handleKeyDown = (e: KeyboardEvent) => { + private readonly handleKeyDown = (e: KeyboardEvent) => { e.stopPropagation(); if (this.converter === undefined) return; if (e.key === "Enter") { @@ -116,7 +117,7 @@ export class InputProperty extends PropertyBase { } }; - private setValue = (input: HTMLInputElement) => { + private readonly setValue = (input: HTMLInputElement) => { let newValue = this.converter?.convertBack?.(input.value); if (!newValue?.isOk) { PubSub.default.pub("showToast", "error.default"); diff --git a/packages/chili-ui/src/property/material/materialEditor.ts b/packages/chili-ui/src/property/material/materialEditor.ts index 6acbaaeb..9d1a2207 100644 --- a/packages/chili-ui/src/property/material/materialEditor.ts +++ b/packages/chili-ui/src/property/material/materialEditor.ts @@ -1,13 +1,12 @@ // Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license. -import { Binding, IConverter, Material, PathBinding, Property, PubSub, Result, Texture } from "chili-core"; +import { Binding, IConverter, Material, PathBinding, Property, PubSub, Result } from "chili-core"; import { button, collection, div, localize, span, svg } from "../../components"; import { ColorConverter } from "../../converters"; -import { appendProperty } from "../utils"; +import { findPropertyControl } from "../utils"; import { MaterialDataContent } from "./materialDataContent"; import style from "./materialEditor.module.css"; import { UrlStringConverter } from "./urlConverter"; -import { TextureEditor } from "./textureEditor"; class ActiveStyleConverter implements IConverter { constructor(readonly material: Material) {} @@ -127,27 +126,21 @@ export class MaterialEditor extends HTMLElement { }; private initEditingControl(material: Material) { - let container = div({ - className: style.properties, - }); this.editingControl.appendChild( div( { className: style.editing, }, - container, + div( + { + className: style.properties, + }, + ...Property.getProperties(material).map((x) => + findPropertyControl(this.dataContent.document, [material], x), + ), + ), ), ); - - Property.getProperties(material).forEach((x) => { - let value = (material as any)[x.name]; - if (value instanceof Texture) { - container.append(new TextureEditor(this.dataContent.document, x.display, value)); - return; - } - - appendProperty(container, this.dataContent.document, [material], x); - }); } } diff --git a/packages/chili-ui/src/property/material/textureEditor.ts b/packages/chili-ui/src/property/material/textureEditor.ts index be9eb118..25f65c29 100644 --- a/packages/chili-ui/src/property/material/textureEditor.ts +++ b/packages/chili-ui/src/property/material/textureEditor.ts @@ -2,11 +2,11 @@ import { I18nKeys, IDocument, PathBinding, Property, readFileAsync, Texture } from "chili-core"; import { div, Expander, img, svg } from "../../components"; -import { appendProperty } from "../utils"; +import { findPropertyControl } from "../utils"; import style from "./textureEditor.module.css"; import { UrlStringConverter } from "./urlConverter"; -export class TextureEditor extends Expander { +export class TextureProperty extends Expander { constructor( readonly document: IDocument, display: I18nKeys, @@ -18,17 +18,17 @@ export class TextureEditor extends Expander { } private render() { - let properties = div({ className: style.properties }); - Property.getProperties(this.texture).forEach((x) => { - if ((x.name as keyof Texture) === "image") return; - appendProperty(properties, this.document, [this.texture], x); - }); - return div( { className: style.expander, }, - properties, + div( + { className: style.properties }, + ...Property.getProperties(this.texture).map((x) => { + if ((x.name as keyof Texture) === "image") return ""; + return findPropertyControl(this.document, [this.texture], x); + }), + ), div( { className: style.image, @@ -56,4 +56,4 @@ export class TextureEditor extends Expander { }; } -customElements.define("texture-editor", TextureEditor); +customElements.define("texture-editor", TextureProperty); diff --git a/packages/chili-ui/src/property/materialProperty.ts b/packages/chili-ui/src/property/materialProperty.ts index 8eb82864..4a54243d 100644 --- a/packages/chili-ui/src/property/materialProperty.ts +++ b/packages/chili-ui/src/property/materialProperty.ts @@ -42,7 +42,9 @@ export class MaterialProperty extends PropertyBase { button.textContent = material.name; Transaction.excute(this.document, "change material", () => { this.objects.forEach((x) => { - x[this.property.name] = material.id; + if (this.property.name in x) { + x[this.property.name] = material.id; + } }); }); this.document.visual.update(); diff --git a/packages/chili-ui/src/property/propertyView.ts b/packages/chili-ui/src/property/propertyView.ts index 187d4d09..8317d523 100644 --- a/packages/chili-ui/src/property/propertyView.ts +++ b/packages/chili-ui/src/property/propertyView.ts @@ -1,7 +1,6 @@ // Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license. import { - GeometryNode, I18nKeys, IConverter, IDocument, @@ -9,7 +8,6 @@ import { IView, Node, NodeLinkedList, - ParameterShapeNode, Property, PubSub, VisualNode, @@ -17,7 +15,7 @@ import { import { Expander, div, label, localize } from "../components"; import { MatrixConverter } from "./matrixConverter"; import style from "./propertyView.module.css"; -import { appendProperty } from "./utils"; +import { findPropertyControl } from "./utils"; export class PropertyView extends HTMLElement { private readonly panel = div({ className: style.panel }); @@ -59,18 +57,18 @@ export class PropertyView extends HTMLElement { private addModel(document: IDocument, nodes: INode[]) { if (nodes.length === 0) return; - let properties = div({ className: style.rootProperties }); + let controls: any[] = []; if (nodes[0] instanceof NodeLinkedList) { - Property.getProperties(Object.getPrototypeOf(nodes[0])).forEach((x) => { - appendProperty(properties, document, nodes, x); + controls = Property.getProperties(Object.getPrototypeOf(nodes[0])).map((x) => { + return findPropertyControl(document, nodes, x); }); } else if (nodes[0] instanceof Node) { - Property.getOwnProperties(Node.prototype).forEach((x) => { - appendProperty(properties, document, nodes, x); + controls = Property.getOwnProperties(Node.prototype).map((x) => { + return findPropertyControl(document, nodes, x); }); } - this.panel.append(properties); + this.panel.append(div({ className: style.rootProperties }, ...controls)); } private addGeometry(nodes: INode[], document: IDocument) { @@ -82,17 +80,24 @@ export class PropertyView extends HTMLElement { private addTransform(document: IDocument, geometries: VisualNode[]) { let matrix = new Expander("common.matrix"); + // 这部分代码有问题,待完善 + let converters = MatrixConverter.init(); this.panel.append(matrix); const addMatrix = (display: I18nKeys, converter: IConverter) => { - appendProperty(matrix, document, geometries, { - name: "transform", - display: display, - converter, - }); + matrix.contenxtPanel.append( + findPropertyControl( + document, + geometries, + { + name: "transform", + display: display, + }, + converter, + ), + ); }; - // 这部分代码有问题,待完善 - let converters = MatrixConverter.init(); + addMatrix("transform.translation", converters.translation); addMatrix("transform.scale", converters.scale); addMatrix("transform.rotation", converters.rotate); @@ -102,10 +107,12 @@ export class PropertyView extends HTMLElement { let entities = geometries.filter((x) => x instanceof VisualNode); if (entities.length === 0 || !this.isAllElementsOfTypeFirstElement(entities)) return; let parameters = new Expander(entities[0].display()); + parameters.contenxtPanel.append( + ...Property.getProperties(Object.getPrototypeOf(entities[0]), Node.prototype).map((x) => { + return findPropertyControl(document, entities, x); + }), + ); this.panel.append(parameters); - Property.getProperties(Object.getPrototypeOf(entities[0]), Node.prototype).forEach((x) => { - appendProperty(parameters.contenxtPanel, document, entities, x); - }); } private isAllElementsOfTypeFirstElement(arr: any[]): boolean { diff --git a/packages/chili-ui/src/property/utils.ts b/packages/chili-ui/src/property/utils.ts index 3b270edc..8d71fcac 100644 --- a/packages/chili-ui/src/property/utils.ts +++ b/packages/chili-ui/src/property/utils.ts @@ -1,34 +1,41 @@ // Copyright 2022-2023 the Chili authors. All rights reserved. AGPL-3.0 license. -import { GeometryNode, IDocument, Property, VisualNode } from "chili-core"; +import { IConverter, IDocument, Logger, Property, Texture } from "chili-core"; import { CheckProperty } from "./check"; import { ColorProperty } from "./colorProperty"; import { InputProperty } from "./input"; +import { TextureProperty } from "./material/textureEditor"; import { MaterialProperty } from "./materialProperty"; -export function appendProperty(container: HTMLElement, document: IDocument, objs: any[], prop?: Property) { - if (prop === undefined || objs.length === 0) return; - if (!(prop.name in objs[0])) { - alert(`Property ${prop.name} not found in ${Object.getPrototypeOf(objs[0]).constructor.name}`); - return; +export function findPropertyControl( + document: IDocument, + objs: any[], + prop: Property, + converter?: IConverter, +) { + if (prop === undefined || objs.length === 0) return ""; + + if (prop.type === "color") { + return new ColorProperty(document, objs, prop); } - const propValue = (objs[0] as unknown as any)[prop.name]; - const type = typeof propValue; + if (prop.type === "materialId") { + return new MaterialProperty(document, objs, prop); + } - if (prop.type === "color") { - container.append(new ColorProperty(document, objs, prop)); - } else if (prop.type === "materialId") { - container.append( - new MaterialProperty( - document, - objs.filter((x) => "materialId" in x), - prop, - ), - ); - } else if (type === "object" || type === "string" || type === "number") { - container.append(new InputProperty(document, objs, prop)); - } else if (type === "boolean") { - container.append(new CheckProperty(objs, prop)); + const value = objs[0][prop.name]; + if (value instanceof Texture) { + return new TextureProperty(document, prop.display, value); } + + if (["object", "string", "number"].includes(typeof value)) { + return new InputProperty(document, objs, prop, converter); + } + + if (typeof value === "boolean") { + return new CheckProperty(objs, prop); + } + + Logger.warn(`Property ${prop.name} not found in ${Object.getPrototypeOf(objs[0]).constructor.name}`); + return ""; }