Compare commits
	
		
			5 Commits
		
	
	
		
			e1a58d2cbe
			...
			aae7e54557
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| aae7e54557 | |||
| ca3a19f5b0 | |||
| e7533fab55 | |||
| 070a9daf42 | |||
| ac88c4d3fd | 
| @ -59,8 +59,16 @@ class CommandBar extends Component<ICommandBarProps & IMixinSettingProps & IMixi | ||||
|                     active: mouseMod === MouseMod.click, | ||||
|                     click: () => this.props.status ? this.props.status.setMouseMod(MouseMod.click) : undefined | ||||
|                 })} | ||||
|                 {this.getRenderButton({ iconName: "WebAppBuilderFragmentCreate", i18NKey: "Command.Bar.Add.Group.Info" })} | ||||
|                 {this.getRenderButton({ iconName: "CubeShape", i18NKey: "Command.Bar.Add.Range.Info" })} | ||||
|                 {this.getRenderButton({ | ||||
|                     iconName: "WebAppBuilderFragmentCreate", | ||||
|                     i18NKey: "Command.Bar.Add.Group.Info", | ||||
|                     click: () => this.props.status ? this.props.status.newGroup() : undefined | ||||
|                 })} | ||||
|                 {this.getRenderButton({ | ||||
|                     iconName: "CubeShape", | ||||
|                     i18NKey: "Command.Bar.Add.Range.Info", | ||||
|                     click: () => this.props.status ? this.props.status.newRange() : undefined | ||||
|                 })} | ||||
|                 {this.getRenderButton({ iconName: "StepSharedAdd", i18NKey: "Command.Bar.Add.Behavior.Info" })} | ||||
|                 {this.getRenderButton({ iconName: "Tag", i18NKey: "Command.Bar.Add.Tag.Info" })} | ||||
|                 {this.getRenderButton({ iconName: "Camera", i18NKey: "Command.Bar.Camera.Info" })} | ||||
|  | ||||
							
								
								
									
										49
									
								
								source/Component/DetailsList/DetailsList.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								source/Component/DetailsList/DetailsList.scss
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| @import "../Theme/Theme.scss"; | ||||
| 
 | ||||
| div.details-list { | ||||
|     width: 100%; | ||||
| 
 | ||||
|     div.details-list-item { | ||||
|         display: flex; | ||||
|         align-items: stretch; | ||||
|         user-select: none; | ||||
|         cursor: pointer; | ||||
|         min-height: 30px; | ||||
| 
 | ||||
|         div.details-list-value { | ||||
|             padding: 5px 10px; | ||||
|             display: flex; | ||||
|             justify-content: center; | ||||
|             align-items: center; | ||||
|         } | ||||
| 
 | ||||
|         div.details-list-checkbox { | ||||
|             display: flex; | ||||
|             align-items: center; | ||||
|             justify-content: center; | ||||
|             padding: 0 10px; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| div.light.details-list { | ||||
|      | ||||
|     div.details-list-item:nth-child(2n) { | ||||
|         background-color: rgba($lt-bg-color-lvl5-light, .4); | ||||
|     } | ||||
| 
 | ||||
|     div.details-list-item:hover { | ||||
|         background-color: $lt-bg-color-lvl3-light; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| div.dark.details-list { | ||||
| 
 | ||||
|     div.details-list-item:nth-child(2n) { | ||||
|         background-color: rgba($lt-bg-color-lvl5-dark, .4); | ||||
|     } | ||||
| 
 | ||||
|     div.details-list-item:hover { | ||||
|         background-color: $lt-bg-color-lvl3-dark; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										79
									
								
								source/Component/DetailsList/DetailsList.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								source/Component/DetailsList/DetailsList.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,79 @@ | ||||
| import { Icon } from "@fluentui/react"; | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { BackgroundLevel, FontLevel, Theme } from "../Theme/Theme"; | ||||
| import "./DetailsList.scss"; | ||||
| 
 | ||||
| type IItems = Record<string, any> & {key: string, select?: boolean}; | ||||
| 
 | ||||
| interface IColumns<D extends IItems, K extends keyof D> { | ||||
|     key: K; | ||||
|     className?: string; | ||||
|     noDefaultStyle?: boolean; | ||||
|     beforeCheckbox?: boolean; | ||||
|     render: (data: D[K]) => ReactNode, | ||||
|     click?: (data: D[K]) => any, | ||||
| } | ||||
| 
 | ||||
| interface IDetailsListProps { | ||||
|     items: IItems[]; | ||||
|     columns: IColumns<this["items"][number], keyof this["items"][number]>[]; | ||||
|     hideCheckBox?: boolean; | ||||
|     checkboxClassName?: string; | ||||
| } | ||||
| 
 | ||||
| class DetailsList extends Component<IDetailsListProps> { | ||||
| 
 | ||||
|     private renderValue<D extends IItems, K extends keyof D>(item: IItems, column: IColumns<D, K>) { | ||||
|         const classList: string[] = []; | ||||
|         if (!column.noDefaultStyle) { | ||||
|             classList.push("details-list-value"); | ||||
|         } | ||||
|         if (column.className) { | ||||
|             classList.push(column.className); | ||||
|         } | ||||
|         return <div | ||||
|             className={classList.join(" ")} | ||||
|             key={column.key as any} | ||||
|         > | ||||
|             {column.render(item[column.key as any])} | ||||
|         </div> | ||||
|     } | ||||
| 
 | ||||
|     public render(): ReactNode { | ||||
|         return <Theme | ||||
|             className="details-list" | ||||
|             backgroundLevel={BackgroundLevel.Level4} | ||||
|             fontLevel={FontLevel.normal} | ||||
|         >{ | ||||
|             this.props.items.map((item) => { | ||||
|                 const { checkboxClassName } = this.props; | ||||
|                 return <div className="details-list-item" key={item.key}> | ||||
|                     { | ||||
|                         this.props.columns.map((column) => { | ||||
|                             if (column.beforeCheckbox) { | ||||
|                                 return this.renderValue(item, column); | ||||
|                             } | ||||
|                         }) | ||||
|                     } | ||||
|                     { | ||||
|                         this.props.hideCheckBox ? null : | ||||
|                         <div  | ||||
|                             className={"details-list-checkbox" + (checkboxClassName ? ` ${checkboxClassName}` : "")} | ||||
|                         > | ||||
|                             <Icon iconName="CheckMark"></Icon> | ||||
|                         </div> | ||||
|                     } | ||||
|                     { | ||||
|                         this.props.columns.map((column) => { | ||||
|                             if (!column.beforeCheckbox) { | ||||
|                                 return this.renderValue(item, column); | ||||
|                             } | ||||
|                         }) | ||||
|                     } | ||||
|                 </div> | ||||
|             }) | ||||
|         }</Theme> | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export { DetailsList }; | ||||
| @ -1,6 +1,6 @@ | ||||
| @import "@fluentui/react/dist/sass/References"; | ||||
| 
 | ||||
| $lt-font-size-normal: $ms-font-size-14; | ||||
| $lt-font-size-normal: 13px; | ||||
| $lt-font-size-lvl3: $ms-font-size-16; | ||||
| $lt-font-size-lvl2: $ms-font-size-18; | ||||
| $lt-font-size-lvl1: $ms-font-size-24; | ||||
|  | ||||
| @ -3,12 +3,29 @@ import { Emitter } from "@Model/Emitter"; | ||||
| import { Model } from "@Model/Model"; | ||||
| import { Archive } from "@Model/Archive"; | ||||
| import { AbstractRenderer } from "@Model/Renderer"; | ||||
| import ClassicRenderer, { MouseMod } from "@GLRender/ClassicRenderer"; | ||||
| import { ClassicRenderer, MouseMod } from "@GLRender/ClassicRenderer"; | ||||
| import { Setting } from "./Setting"; | ||||
| import { I18N } from "@Component/Localization/Localization"; | ||||
| 
 | ||||
| function randomColor() { | ||||
|     return [ | ||||
|         Math.random() * .8 + .2, | ||||
|         Math.random() * .8 + .2, | ||||
|         Math.random() * .8 + .2, 1 | ||||
|     ] | ||||
| } | ||||
| 
 | ||||
| class Status extends Emitter<{ | ||||
|     mouseModChange: MouseMod | ||||
| }> { | ||||
| 
 | ||||
|     public setting: Setting = undefined as any; | ||||
| 
 | ||||
|     /** | ||||
|      * 对象命名 | ||||
|      */ | ||||
|     public objectNameIndex = 1; | ||||
| 
 | ||||
|     /** | ||||
|      * 渲染器 | ||||
|      */ | ||||
| @ -29,6 +46,26 @@ class Status extends Emitter<{ | ||||
|      */ | ||||
|     public mouseMod: MouseMod = MouseMod.Drag; | ||||
| 
 | ||||
|     public newGroup() { | ||||
|         const group = this.model.addGroup(); | ||||
|         group.color = randomColor(); | ||||
|         group.displayName = I18N(this.setting.language, "Object.List.New.Group", { | ||||
|             id: this.objectNameIndex.toString() | ||||
|         }); | ||||
|         this.objectNameIndex ++; | ||||
|         return group; | ||||
|     } | ||||
| 
 | ||||
|     public newRange() { | ||||
|         const range = this.model.addRange(); | ||||
|         range.color = randomColor(); | ||||
|         range.displayName = I18N(this.setting.language, "Object.List.New.Range", { | ||||
|             id: this.objectNameIndex.toString() | ||||
|         }); | ||||
|         this.objectNameIndex ++; | ||||
|         return range; | ||||
|     } | ||||
| 
 | ||||
|     public setMouseMod(mod: MouseMod) { | ||||
|         this.mouseMod = mod; | ||||
|         if (this.renderer instanceof ClassicRenderer) { | ||||
|  | ||||
| @ -19,10 +19,15 @@ const EN_US = { | ||||
|     "Command.Bar.Add.Tag.Info": "Add label object", | ||||
|     "Command.Bar.Camera.Info": "Renderer settings", | ||||
|     "Command.Bar.Setting.Info": "Global Settings", | ||||
|     "Object.List.New.Group": "Group object {id}", | ||||
|     "Object.List.New.Range": "Range object {id}", | ||||
|     "Object.List.No.Data": "There are no objects in the model, click the button to create it", | ||||
|     "Panel.Title.Notfound": "{id}", | ||||
|     "Panel.Info.Notfound": "This panel with id {id} can not found!", | ||||
|     "Panel.Title.Render.View": "Live preview", | ||||
|     "Panel.Info.Render.View": "Live simulation results preview", | ||||
|     "Panel.Title.Object.List.View": "Object list", | ||||
|     "Panel.Info.Object.List.View": "Edit View All Object Properties", | ||||
| 
 | ||||
| } | ||||
| export default EN_US; | ||||
| @ -19,9 +19,14 @@ const ZH_CN = { | ||||
|     "Command.Bar.Add.Tag.Info": "添加标签对象", | ||||
|     "Command.Bar.Camera.Info": "渲染器设置", | ||||
|     "Command.Bar.Setting.Info": "全局设置", | ||||
|     "Object.List.New.Group": "组对象 {id}", | ||||
|     "Object.List.New.Range": "范围对象 {id}", | ||||
|     "Object.List.No.Data": "模型中没有任何对象,点击按钮以创建", | ||||
|     "Panel.Title.Notfound": "找不到面板: {id}", | ||||
|     "Panel.Info.Notfound": "这个编号为 {id} 的面板无法找到!", | ||||
|     "Panel.Title.Render.View": "实时预览", | ||||
|     "Panel.Info.Render.View": "实时仿真结果预览", | ||||
|     "Panel.Title.Object.List.View": "对象列表", | ||||
|     "Panel.Info.Object.List.View": "编辑查看全部对象属性", | ||||
| } | ||||
| export default ZH_CN; | ||||
| @ -7,6 +7,11 @@ import type { ObjectID } from "./Renderer"; | ||||
|  */ | ||||
| class CtrlObject extends LabelObject { | ||||
| 
 | ||||
|     /** | ||||
|      * 显示名称 | ||||
|      */ | ||||
|     public displayName: string = ""; | ||||
| 
 | ||||
|     /** | ||||
|      * 颜色 | ||||
|      */ | ||||
|  | ||||
| @ -36,11 +36,12 @@ class SimulatorWeb extends Component { | ||||
|         this.status = new Status(); | ||||
|         this.status.renderer = new ClassicRenderer({ className: "canvas" }).onLoad(); | ||||
|         this.status.model.bindRenderer(this.status.renderer); | ||||
|         this.status.setting = this.setting; | ||||
| 
 | ||||
|         // 测试代码
 | ||||
|         if (true) { | ||||
|             let group = this.status.model.addGroup(); | ||||
|             let range = this.status.model.addRange(); | ||||
|             let group = this.status.newGroup(); | ||||
|             let range = this.status.newRange(); | ||||
|             range.color = [.1, .5, .9]; | ||||
|             group.new(100); | ||||
|             group.color = [.8, .1, .6]; | ||||
| @ -72,7 +73,7 @@ class SimulatorWeb extends Component { | ||||
|                 }, | ||||
|                 { | ||||
|                     items: [{ | ||||
|                         panles: ["Label d"] | ||||
|                         panles: ["ObjectList"] | ||||
|                     }, { | ||||
|                         items: [{panles: ["Label e", "ee"]}, {panles: ["F"]}], | ||||
|                         layout: LayoutDirection.Y | ||||
|  | ||||
							
								
								
									
										7
									
								
								source/Panel/ObjectList/ObjectList.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								source/Panel/ObjectList/ObjectList.scss
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| div.object-list-color-value { | ||||
|     height: calc( 100% - 6px); | ||||
|     margin: 3px 0; | ||||
|     margin-left: 3px; | ||||
|     border-radius: 1000px; | ||||
|     width: 3px; | ||||
| } | ||||
							
								
								
									
										76
									
								
								source/Panel/ObjectList/ObjectList.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								source/Panel/ObjectList/ObjectList.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | ||||
| import { Component, ReactNode } from "react"; | ||||
| import { DetailsList } from "@Component/DetailsList/DetailsList"; | ||||
| import { useStatus, IMixinStatusProps } from "@Context/Status"; | ||||
| import { Localization } from "@Component/Localization/Localization"; | ||||
| import "./ObjectList.scss"; | ||||
| 
 | ||||
| @useStatus | ||||
| class ObjectList extends Component<IMixinStatusProps> { | ||||
| 
 | ||||
|     private handelChange = () => { | ||||
|         this.forceUpdate(); | ||||
|     } | ||||
| 
 | ||||
|     public componentDidMount(){ | ||||
|         if (this.props.status) { | ||||
|             this.props.status.model.on("objectChange", this.handelChange); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public componentWillUnmount(){ | ||||
|         if (this.props.status) { | ||||
|             this.props.status.model.off("objectChange", this.handelChange); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     private renderList() { | ||||
|         const objList = this.props.status?.model.objectPool ?? []; | ||||
| 
 | ||||
|         if (objList.length <= 0) { | ||||
|             return <Localization i18nKey="Object.List.No.Data" style={{ | ||||
|                 padding: "10px", | ||||
|                 display: "block" | ||||
|             }}/> | ||||
|         } | ||||
| 
 | ||||
|         return <DetailsList | ||||
|             items={objList.concat([]).map((object => { | ||||
|                 return { | ||||
|                     key: object.id.toString(), | ||||
|                     name: object.displayName, | ||||
|                     color: object.color, | ||||
|                     display: object.display, | ||||
|                     update: object.update | ||||
|                 } | ||||
|             }))} | ||||
|             columns={[ | ||||
|                 { | ||||
|                     key: "color", | ||||
|                     noDefaultStyle: true, | ||||
|                     beforeCheckbox: true, | ||||
|                     render: (color) => <div | ||||
|                         className="object-list-color-value" | ||||
|                         style={{ | ||||
|                             background: `rgb(${ | ||||
|                                 Math.floor(color[0] * 255) | ||||
|                             }, ${ | ||||
|                                 Math.floor(color[1] * 255) | ||||
|                             }, ${ | ||||
|                                 Math.floor(color[2] * 255) | ||||
|                             })` | ||||
|                         }} | ||||
|                     /> | ||||
|                 }, { | ||||
|                     key: "name", | ||||
|                     render: (name) => <span>{name}</span> | ||||
|                 } | ||||
|             ]} | ||||
|         /> | ||||
|     } | ||||
| 
 | ||||
|     public render(): ReactNode { | ||||
|         return this.renderList(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export { ObjectList }; | ||||
| @ -2,6 +2,7 @@ import { ReactNode, Component, FunctionComponent } from "react"; | ||||
| import { Theme } from "@Component/Theme/Theme"; | ||||
| import { Localization } from "@Component/Localization/Localization"; | ||||
| import { RenderView } from "./RenderView/RenderView"; | ||||
| import { ObjectList } from "./ObjectList/ObjectList"; | ||||
| 
 | ||||
| interface IPanelInfo { | ||||
| 	nameKey: string; | ||||
| @ -15,6 +16,7 @@ interface IPanelInfo { | ||||
| 
 | ||||
| type PanelId = "" | ||||
| | "RenderView" // 主渲染器
 | ||||
| | "ObjectList" // 对象列表
 | ||||
| ; | ||||
| 
 | ||||
| const PanelInfoMap = new Map<PanelId, IPanelInfo>(); | ||||
| @ -22,6 +24,10 @@ PanelInfoMap.set("RenderView", { | ||||
| 	nameKey: "Panel.Title.Render.View", introKay: "Panel.Info.Render.View", | ||||
|     class: RenderView, hidePadding: true, hideScrollBar: true, isDeepDark: true | ||||
| }); | ||||
| PanelInfoMap.set("ObjectList", { | ||||
|     nameKey: "Panel.Title.Object.List.View", introKay: "Panel.Info.Object.List.View", | ||||
|     class: ObjectList, hidePadding: true | ||||
| }) | ||||
| 
 | ||||
| function getPanelById(panelId: PanelId): ReactNode { | ||||
| 	switch (panelId) { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user