Add clip model & clipList component & recoder panel #48
							
								
								
									
										136
									
								
								source/Component/Recorder/Recorder.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								source/Component/Recorder/Recorder.scss
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,136 @@ | |||||||
|  | @import "../Theme/Theme.scss"; | ||||||
|  | 
 | ||||||
|  | div.recorder-root { | ||||||
|  | 	width: 100%; | ||||||
|  | 	box-sizing: border-box; | ||||||
|  | 	padding: 10px; | ||||||
|  | 
 | ||||||
|  | 	div.recorder-slider { | ||||||
|  | 		width: 100%; | ||||||
|  | 
 | ||||||
|  | 		div.ms-Slider-slideBox { | ||||||
|  | 			height: 16px; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		span.ms-Slider-thumb { | ||||||
|  | 			width: 12px; | ||||||
|  | 			height: 12px; | ||||||
|  | 			line-height: 16px; | ||||||
|  | 			border-width: 3px; | ||||||
|  | 			top: -4px; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		span.ms-Slider-active { | ||||||
|  | 			height: 3px; | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
|  | 		span.ms-Slider-inactive { | ||||||
|  | 			height: 3px; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	div.recorder-content { | ||||||
|  | 		width: 100%; | ||||||
|  | 		height: 32px; | ||||||
|  | 		display: flex; | ||||||
|  | 		justify-content: space-between; | ||||||
|  | 		align-items: center; | ||||||
|  | 		box-sizing: border-box; | ||||||
|  | 		padding: 0 8px; | ||||||
|  | 
 | ||||||
|  | 		div.time-view { | ||||||
|  | 			flex-shrink: 1; | ||||||
|  | 			width: 50%; | ||||||
|  | 			text-align: left; | ||||||
|  | 			white-space: nowrap; | ||||||
|  | 			overflow: hidden; | ||||||
|  | 			text-overflow: ellipsis; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		div.ctrl-button { | ||||||
|  | 			cursor: pointer; | ||||||
|  | 			user-select: none; | ||||||
|  | 			width: 96px; | ||||||
|  | 			flex-shrink: 0; | ||||||
|  | 			text-align: center; | ||||||
|  | 			display: flex; | ||||||
|  | 			justify-content: center; | ||||||
|  | 			align-items: center; | ||||||
|  | 
 | ||||||
|  | 			div.ctrl-action { | ||||||
|  | 				width: 32px; | ||||||
|  | 				height: 32px; | ||||||
|  | 				display: flex; | ||||||
|  | 				justify-content: center; | ||||||
|  | 				align-items: center; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			div.ctrl-action-main { | ||||||
|  | 				font-size: 1.5em; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		div.speed-view { | ||||||
|  | 			flex-shrink: 1; | ||||||
|  | 			width: 50%; | ||||||
|  | 			text-align: right; | ||||||
|  | 			white-space: nowrap; | ||||||
|  | 			overflow: hidden; | ||||||
|  | 			text-overflow: ellipsis; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | div.recorder-root.light { | ||||||
|  | 
 | ||||||
|  | 	div.recorder-slider { | ||||||
|  | 
 | ||||||
|  | 		span.ms-Slider-thumb { | ||||||
|  | 			background-color: $lt-bg-color-lvl1-light; | ||||||
|  | 			border-color: $lt-font-color-normal-light; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		span.ms-Slider-active { | ||||||
|  | 			background-color: $lt-font-color-normal-light; | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
|  | 		span.ms-Slider-inactive { | ||||||
|  | 			background-color: $lt-bg-color-lvl1-light; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	div.recorder-content { | ||||||
|  | 
 | ||||||
|  | 		div.ctrl-button div.ctrl-action:hover { | ||||||
|  | 			background-color: $lt-bg-color-lvl3-light; | ||||||
|  | 			color: $lt-font-color-lvl1-light; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | div.recorder-root.dark { | ||||||
|  | 	 | ||||||
|  | 	div.recorder-slider { | ||||||
|  | 
 | ||||||
|  | 		span.ms-Slider-thumb { | ||||||
|  | 			background-color: $lt-bg-color-lvl1-dark; | ||||||
|  | 			border-color: $lt-font-color-normal-dark; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		span.ms-Slider-active { | ||||||
|  | 			background-color: $lt-font-color-normal-dark; | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
|  | 		span.ms-Slider-inactive { | ||||||
|  | 			background-color: $lt-bg-color-lvl1-dark; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	div.recorder-content { | ||||||
|  | 
 | ||||||
|  | 		div.ctrl-button div.ctrl-action:hover { | ||||||
|  | 			background-color: $lt-bg-color-lvl3-dark; | ||||||
|  | 			color: $lt-font-color-lvl1-dark; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										73
									
								
								source/Component/Recorder/Recorder.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								source/Component/Recorder/Recorder.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,73 @@ | |||||||
|  | import { Localization } from "@Component/Localization/Localization"; | ||||||
|  | import { BackgroundLevel, FontLevel, Theme } from "@Component/Theme/Theme"; | ||||||
|  | import { Icon, Slider } from "@fluentui/react"; | ||||||
|  | import { Component, ReactNode } from "react"; | ||||||
|  | import "./Recorder.scss"; | ||||||
|  | 
 | ||||||
|  | interface IRecorderProps { | ||||||
|  | 	mode?: "P" | "R", | ||||||
|  | 	name?: string; | ||||||
|  | 	fps?: number; | ||||||
|  | 	allFrame?: number; | ||||||
|  | 	currentFrame?: number; | ||||||
|  | 	allTime?: number; | ||||||
|  | 	currentTime?: number; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | class Recorder extends Component<IRecorderProps> { | ||||||
|  | 
 | ||||||
|  | 	private parseTime(time?: number): string { | ||||||
|  | 		if (time === undefined) { | ||||||
|  | 			return "--:--:--:--"; | ||||||
|  | 		} | ||||||
|  | 		const h = Math.floor(time / 3600); | ||||||
|  | 		const m = Math.floor((time % 3600) / 60); | ||||||
|  | 		const s = Math.floor((time % 3600) % 60); | ||||||
|  | 		const ms = Math.floor((time % 1) * 1000); | ||||||
|  | 		return `${h}:${m}:${s}:${ms}`; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public render(): ReactNode { | ||||||
|  | 		return <Theme | ||||||
|  | 			className="recorder-root" | ||||||
|  | 			backgroundLevel={BackgroundLevel.Level4} | ||||||
|  | 			fontLevel={FontLevel.normal} | ||||||
|  | 		> | ||||||
|  | 			<Slider | ||||||
|  | 				min={0} | ||||||
|  | 				value={this.props.currentFrame} | ||||||
|  | 				max={this.props.allFrame} | ||||||
|  | 				className="recorder-slider" | ||||||
|  | 				showValue={false} | ||||||
|  | 			/> | ||||||
|  | 			<div className="recorder-content"> | ||||||
|  | 				<div className="time-view"> | ||||||
|  | 					<Localization | ||||||
|  | 						i18nKey="Panel.Info.Behavior.Clip.Time.Formate" | ||||||
|  | 						options={{ | ||||||
|  | 							current: this.parseTime(this.props.currentTime), | ||||||
|  | 							all: this.parseTime(this.props.allTime), | ||||||
|  | 							fps: this.props.fps ? this.props.fps.toString() : "--" | ||||||
|  | 						}} | ||||||
|  | 					/> | ||||||
|  | 				</div> | ||||||
|  | 				<div className="ctrl-button"> | ||||||
|  | 					<div className="ctrl-action"> | ||||||
|  | 						<Icon iconName="Back"/> | ||||||
|  | 					</div> | ||||||
|  | 					<div className="ctrl-action ctrl-action-main"> | ||||||
|  | 						<Icon iconName="Play"/> | ||||||
|  | 					</div> | ||||||
|  | 					<div className="ctrl-action"> | ||||||
|  | 						<Icon iconName="Forward"/> | ||||||
|  | 					</div> | ||||||
|  | 				</div> | ||||||
|  | 				<div className="speed-view"> | ||||||
|  | 					{this.props.name} | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 		</Theme>; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export { Recorder }; | ||||||
| @ -53,6 +53,9 @@ const EN_US = { | |||||||
|     "Panel.Info.Behavior.List.View": "Edit view behavior list", |     "Panel.Info.Behavior.List.View": "Edit view behavior list", | ||||||
|     "Panel.Title.Behavior.Details.View": "Behavior", |     "Panel.Title.Behavior.Details.View": "Behavior", | ||||||
|     "Panel.Info.Behavior.Details.View": "Edit view Behavior attributes", |     "Panel.Info.Behavior.Details.View": "Edit view Behavior attributes", | ||||||
|  |     "Panel.Title.Behavior.Clip.Player": "Recording", | ||||||
|  |     "Panel.Info.Behavior.Clip.Player": "Pre render recorded data", | ||||||
|  |     "Panel.Info.Behavior.Clip.Time.Formate": "{current} / {all} / {fps}fps", | ||||||
|     "Popup.Title.Unnamed": "Popup message", |     "Popup.Title.Unnamed": "Popup message", | ||||||
|     "Popup.Title.Confirm": "Confirm message", |     "Popup.Title.Confirm": "Confirm message", | ||||||
|     "Popup.Action.Yes": "Confirm", |     "Popup.Action.Yes": "Confirm", | ||||||
|  | |||||||
| @ -53,6 +53,9 @@ const ZH_CN = { | |||||||
|     "Panel.Info.Behavior.List.View": "编辑查看行为列表", |     "Panel.Info.Behavior.List.View": "编辑查看行为列表", | ||||||
|     "Panel.Title.Behavior.Details.View": "行为", |     "Panel.Title.Behavior.Details.View": "行为", | ||||||
|     "Panel.Info.Behavior.Details.View": "编辑查看行为属性", |     "Panel.Info.Behavior.Details.View": "编辑查看行为属性", | ||||||
|  |     "Panel.Title.Behavior.Clip.Player": "录制", | ||||||
|  |     "Panel.Info.Behavior.Clip.Player": "预渲染录制数据", | ||||||
|  |     "Panel.Info.Behavior.Clip.Time.Formate": "{current} / {all} / {fps} fps", | ||||||
|     "Popup.Title.Unnamed": "弹窗消息", |     "Popup.Title.Unnamed": "弹窗消息", | ||||||
|     "Popup.Title.Confirm": "确认消息", |     "Popup.Title.Confirm": "确认消息", | ||||||
|     "Popup.Action.Yes": "确定", |     "Popup.Action.Yes": "确定", | ||||||
|  | |||||||
| @ -55,7 +55,7 @@ class SimulatorWeb extends Component { | |||||||
|                     items: [ |                     items: [ | ||||||
|                         {panels: ["RenderView"]}, |                         {panels: ["RenderView"]}, | ||||||
|                         { |                         { | ||||||
|                             items: [{panels: ["BehaviorList"]}, {panels: ["LabelList"]}], |                             items: [{panels: ["ClipPlayer", "BehaviorList"]}, {panels: ["LabelList"]}], | ||||||
|                             scale: 80, |                             scale: 80, | ||||||
|                             layout: LayoutDirection.X |                             layout: LayoutDirection.X | ||||||
|                         } |                         } | ||||||
|  | |||||||
							
								
								
									
										0
									
								
								source/Panel/ClipPlayer/ClipPlayer.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								source/Panel/ClipPlayer/ClipPlayer.scss
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										13
									
								
								source/Panel/ClipPlayer/ClipPlayer.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								source/Panel/ClipPlayer/ClipPlayer.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,13 @@ | |||||||
|  | import { Component, ReactNode } from "react"; | ||||||
|  | import "./ClipPlayer.scss"; | ||||||
|  | 
 | ||||||
|  | class ClipPlayer extends Component { | ||||||
|  | 
 | ||||||
|  | 	public render(): ReactNode { | ||||||
|  | 		return <> | ||||||
|  | 			 | ||||||
|  | 		</>; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export { ClipPlayer }; | ||||||
							
								
								
									
										10
									
								
								source/Panel/ClipPlayer/ClipRecorder.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								source/Panel/ClipPlayer/ClipRecorder.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | |||||||
|  | import { Component, ReactNode } from "react"; | ||||||
|  | import { Recorder } from "@Component/Recorder/Recorder"; | ||||||
|  | 
 | ||||||
|  | class ClipRecorder extends Component { | ||||||
|  | 	public render(): ReactNode { | ||||||
|  | 		return <Recorder/> | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export { ClipRecorder }; | ||||||
| @ -10,6 +10,8 @@ import { LabelDetails } from "@Panel/LabelDetails/LabelDetails"; | |||||||
| import { GroupDetails } from "@Panel/GroupDetails/GroupDetails"; | import { GroupDetails } from "@Panel/GroupDetails/GroupDetails"; | ||||||
| import { BehaviorList } from "@Panel/BehaviorList/BehaviorList"; | import { BehaviorList } from "@Panel/BehaviorList/BehaviorList"; | ||||||
| import { BehaviorDetails } from "@Panel/BehaviorDetails/BehaviorDetails"; | import { BehaviorDetails } from "@Panel/BehaviorDetails/BehaviorDetails"; | ||||||
|  | import { ClipPlayer } from "@Panel/ClipPlayer/ClipPlayer"; | ||||||
|  | import { ClipRecorder } from "@Panel/ClipPlayer/ClipRecorder"; | ||||||
| 
 | 
 | ||||||
| interface IPanelInfo { | interface IPanelInfo { | ||||||
| 	nameKey: string; | 	nameKey: string; | ||||||
| @ -31,6 +33,7 @@ type PanelId = "" | |||||||
| | "GroupDetails" // 群属性
 | | "GroupDetails" // 群属性
 | ||||||
| | "BehaviorList" // 行为列表
 | | "BehaviorList" // 行为列表
 | ||||||
| | "BehaviorDetails" // 行为属性
 | | "BehaviorDetails" // 行为属性
 | ||||||
|  | | "ClipPlayer" // 剪辑影片
 | ||||||
| ; | ; | ||||||
| 
 | 
 | ||||||
| const PanelInfoMap = new Map<PanelId, IPanelInfo>(); | const PanelInfoMap = new Map<PanelId, IPanelInfo>(); | ||||||
| @ -66,6 +69,10 @@ PanelInfoMap.set("BehaviorDetails", { | |||||||
|     nameKey: "Panel.Title.Behavior.Details.View", introKay: "Panel.Info.Behavior.Details.View", |     nameKey: "Panel.Title.Behavior.Details.View", introKay: "Panel.Info.Behavior.Details.View", | ||||||
|     class: BehaviorDetails |     class: BehaviorDetails | ||||||
| }); | }); | ||||||
|  | PanelInfoMap.set("ClipPlayer", { | ||||||
|  |     nameKey: "Panel.Title.Behavior.Clip.Player", introKay: "Panel.Info.Behavior.Clip.Player", | ||||||
|  |     class: ClipPlayer, header: ClipRecorder, hidePadding: true | ||||||
|  | }); | ||||||
| 
 | 
 | ||||||
| function getPanelById(panelId: PanelId): ReactNode { | function getPanelById(panelId: PanelId): ReactNode { | ||||||
| 	switch (panelId) { | 	switch (panelId) { | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user