中化加油站项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

522 lines
17 KiB

import { AbstractMesh, EventState, Scene, setAndStartTimer, Vector2 } from "@babylonjs/core";
import { Button, Container, Control, Ellipse, MultiLine, RadioButton, Rectangle, StackPanel, TextBlock, Vector2WithInfo } from "@babylonjs/gui";
import { ConfigManager } from "../controller/config-manager";
import { SceneManager } from "../controller/scene-manager";
import { UIManager } from "../controller/ui-manager";
import { UIBase } from "../view/window-base/ui-base";
import { MyInputText } from "./babylon-tool";
//babylon UI 风格 工具
export class BabylonUIStyleTool {
static c_color_blue: string = "#0080FF";//普通蓝色,用于选中、确定等正面风格
static c_color_gray: string = "#E8ECF1";//普通灰色,用于取消、后退、输入背景等
static c_color_black: string = "black";//黑色
static c_color_blueBg: string = "#001121";//深蓝,用于长存界面的背景
static c_color_white: string = "white";
static c_color_green = "#439C08";//绿色按钮
static c_color_greenLight = '#00F424';//亮绿色
static c_color_red = "#C14242";//红色按钮,用于删除等危险操作
static c_color_3d_blueLight: string = "#99ECFC";//亮蓝,字
static c_color_3d_blue: string = "#47E0FF";//蓝, 框体
static c_color_3d_blueBg: string = "#122F49";//蓝黑,背景
static c_shadow_blur_button = 2;//按钮的阴影模糊
static c_shadow_blur_window = 20; //界面的阴影模糊
static readonly cornerRadius_window1 = 10;//界面圆角
static readonly cornerRadius_button = 6;//按钮圆角
static c_zIndex_gizmo = 200;//gizmo界面的z
static c_zIndex_topBar = 100;//topbar界面的z
static c_zIndex_buildingIcon = 50;//建筑标志的z
static c_zIndex_facilityIcon = 40;//设备标志的z
//#region 组件
//创建窗口根节点
static createWindoRoot(window: UIBase, name: string, width: string, height: string, isDialog: boolean) {
window.root = new Rectangle(name);
UIManager.Instance.uiRoot.addControl(window.root);
window.root.width = width;
window.root.height = height;
BabylonUIStyleTool.setDefaultStyle_windowRoot(window.root, isDialog);
}
//创建文本输入组件
static createInputText(name: string, parent: Container, width: string, height: string, textColor: string = "black", thickness: number = 0, cornerRadius: number = 6, backgroundColor: string = "#EEF1F5", focuseColor: string = "black", focuseBgColor: string = "#EEF1F5"): MyInputText {
let result = new MyInputText(name, parent, width, height);
result.inputText.color = textColor;
result.inputText.background = backgroundColor;
result.inputText.thickness = thickness;
result.inputText.focusedColor = focuseColor;
result.inputText.focusedBackground = focuseBgColor;
result.bg.cornerRadius = cornerRadius;
result.bg.color = backgroundColor;
result.bg.thickness = thickness;
return result;
}
//创建文本
static createTextBlock(name: string, text: string, width: string, height: string, fontSize: string): TextBlock {
let textBlock = new TextBlock(name, text);
BabylonUIStyleTool.setStyle_size(textBlock, width, height);
textBlock.fontSize = fontSize;
textBlock.color = "black";
return textBlock;
}
//创建统一风格的确定按钮
static createBtn_OK(name: string, text: string, width: string, height: string, fontSize: string): Button {
let result = BabylonUIStyleTool.createBtn(name, text, width, height, fontSize, "white", BabylonUIStyleTool.c_color_blue);
BabylonUIStyleTool.setStyle_Shadow(result, undefined, 1.5);
return result;
}
//创建统一风格的取消按钮
static createBtn_Cancel(name: string, text: string, width: string, height: string, fontSize: string): Button {
let result = BabylonUIStyleTool.createBtn(name, text, width, height, fontSize, "black", BabylonUIStyleTool.c_color_gray);
return result
}
//创建统一风格的删除按钮
static createBtn_Delete(name: string, text: string, width: string, height: string, fontSize: string,): Button {
let result = BabylonUIStyleTool.createBtn(name, text, width, height, fontSize, "white", BabylonUIStyleTool.c_color_red);
return result;
}
//创建按钮
static createBtn(name: string, text: string, width: string, height: string, fontSize: string, textColor: string = "black", bgColor: string = "white", thickness: number = 0, cornerRadius: number = 6): Button {
let result = Button.CreateSimpleButton(name, text);
result.background = bgColor;
result.color = textColor;
result.width = width;
result.height = height;
result.thickness = thickness;
result.cornerRadius = cornerRadius;
result.textBlock.color = textColor;
result.fontSize = fontSize;
return result;
}
//创建选择框
static createRadioButton(name: string, parent: Container, group: string, width: string, height: string, color: string, background: string, info?: string, infoWidth?: string, isChecked = false, callback?: (eventData: boolean, eventState: EventState) => void) {
let root = new StackPanel(name + "Root");
root.isVertical = false
root.width = width;
root.height = height;
parent.addControl(root);
let radioButton = new RadioButton(name);
root.addControl(radioButton);
radioButton.group = group;
BabylonUIStyleTool.setStyle_size(radioButton, height, height);
radioButton.background = background;
radioButton.color = color;
if (callback) {
radioButton.onIsCheckedChangedObservable.add(callback);
}
radioButton.isChecked = isChecked;
let header = new TextBlock(name + "_info", info);
root.addControl(header);
header.height = height;
header.width = width;
header.color = "black";
header.textHorizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
return radioButton;
}
/**
* 创建线性指示UI
* @param key
* @param mesh 跟随在此mesh 右侧
* @param size 外框的大小, 外框的左侧中点为线段起点
* @param infoSize 信息框的大小, 对齐于外框的右上角
*/
static createLineInfo(key: string, mesh: AbstractMesh, size: Vector2 = new Vector2(160, 60), infoSize: Vector2 = new Vector2(120, 20)): UI_LineInfo {
if (size.x < infoSize.x) {
size.x = infoSize.x;
}
if (size.y < infoSize.y) {
size.y = infoSize.y;
}
let lineInfo = new UI_LineInfo(key, mesh, size, infoSize);
return lineInfo;
}
//#endregion
//#region 风格样式
//统一设置窗口根节点风格
static setDefaultStyle_windowRoot(container: Rectangle, isDialog = true, shadow: boolean = true, corner: boolean = true) {
container.thickness = 0;
//弹框
if (isDialog) {
container.color = BabylonUIStyleTool.c_color_white;
container.background = BabylonUIStyleTool.c_color_white;
container.alpha = 1;
container.zIndex = 100;
}
else//长存界面
{
container.color = BabylonUIStyleTool.c_color_blueBg;
container.background = BabylonUIStyleTool.c_color_blueBg;
container.alpha = 0.8;
container.zIndex = 1;
}
//阴影
if (shadow) {
BabylonUIStyleTool.setStyle_Shadow(container, BabylonUIStyleTool.c_color_black, BabylonUIStyleTool.c_shadow_blur_window);
}
//圆角
if (corner) {
container.cornerRadius = BabylonUIStyleTool.cornerRadius_window1;
}
}
//设置尺寸
static setStyle_size(control: Control, width: string, height: string) {
control.width = width;
control.height = height;
}
//设置文本风格
static setStyle_bodyText(text: TextBlock, fontSize: string = "20px", color: string = "#333333", alpha: number = 1) {
text.fontSize = fontSize;
text.color = color;
text.alpha = alpha;
}
//设置对齐方式
//horizontal: Control.HORIZONTAL_ALIGNMENT_CENTER;Control.HORIZONTAL_ALIGNMENT_LEFT;Control.HORIZONTAL_ALIGNMENT_RIGHT;
//vertical: Control.VERTICAL_ALIGNMENT_CENTER ; Control.VERTICAL_ALIGNMENT_LEFT;Control.VERTICAL_ALIGNMENT_RIGHT;
//
static setStyle_Alignment(control: Control, horizontal: number, vertical: number) {
control.horizontalAlignment = horizontal;
control.verticalAlignment = vertical;
}
//设置边距
static setStyle_padding(control: Control, paddingTop?: string, paddingRight?: string, paddingBottom?: string, paddingLeft?: string) {
if (paddingTop != undefined) {
control.paddingTop = paddingTop;
}
if (paddingRight != undefined) {
control.paddingRight = paddingRight;
}
if (paddingBottom != undefined) {
control.paddingBottom = paddingBottom;
}
if (paddingLeft != undefined) {
control.paddingLeft = paddingLeft;
}
}
//设置阴影
static setStyle_Shadow(container: Control, color: string = BabylonUIStyleTool.c_color_black, blur: number = BabylonUIStyleTool.c_shadow_blur_window) {
container.shadowColor = color;
container.shadowBlur = blur;
}
//#endregion
//#region 功能封装
/**
* 在按钮上增加长按事件
* @param button 按钮
* @param scene 所在的场景
* @param onEnd 正常长按
* @param onAbort 长按中端
*/
static addLongPressButtonBehave(button: Button, scene: Scene, onEnd?: () => void, onAbort?: () => void) {
let pickDown = false;
let size = ConfigManager.c_size_facilityIconSize;
let vector2WithInfo: Vector2WithInfo;
let ellipse: Ellipse;
button.onPointerUpObservable.add((info) => {
if (pickDown) {
pickDown = false;
ellipse.dispose();
console.log("onPointerUpObservable");
vector2WithInfo = info;
}
});
button.onPointerDownObservable.add(() => {
ellipse = new Ellipse("ellipse");
ellipse.width = size + "px";
ellipse.height = size + "px";
ellipse.color = BabylonUIStyleTool.c_color_blue;
button.addControl(ellipse);
console.log("onPointerDownObservable");
pickDown = true;
setAndStartTimer({
timeout: ConfigManager.c_time_longPress,
contextObservable: scene.onBeforeRenderObservable,
breakCondition: () => {
return pickDown == false;
},
onEnded: (data) => {
if (onEnd) {
onEnd();
setTimeout(
function () {
button.onPointerUpObservable.notifyObservers(vector2WithInfo);
//此处存在问题,因为打开了前端页面,导致焦点小时,babylon无法确定鼠标抬起,则下一次的按下操作失效
},
250);
}
},
onAborted: () => {
if (onAbort) {
onAbort();
}
},
onTick: (data) => {
ellipse.thickness = data.completeRate * 0.5 * size * data.completeRate * data.completeRate;
}
})
});
}
/**
* 在按钮上增加双击事件
* @param button
* @param scene
* @param onClick 双击的回调
*/
static addDoubleClickButtonBehave(button: Button, scene: Scene, onClick: () => void) {
if (BabylonUIStyleTool.s_doubleClickHelper == null) {
BabylonUIStyleTool.s_doubleClickHelper = new DoubleClickHelper(scene);
}
button.onPointerClickObservable.add(
(eventData: Vector2WithInfo, eventState: EventState) => {
let buttonID = button.uniqueId.toString();
if (BabylonUIStyleTool.s_doubleClickHelper.isDoubleClick(buttonID)) {
onClick();
}
else {
BabylonUIStyleTool.s_doubleClickHelper.setClickEvent(buttonID);
}
}
);
}
static s_doubleClickHelper: DoubleClickHelper;
//#endregion
}
/**
* 双击帮助器
*/
class DoubleClickHelper {
readonly c_timer: number = 200; //双击的时间间隔
scene: Scene;
timer: number;
buttonID: string;
constructor(scene: Scene) {
this.scene = scene;
let instance = this;
this.scene.onBeforeRenderObservable.add(() => {
instance.update()
});
}
update() {
if (this.timer > 0) {
this.timer -= this.scene.deltaTime;
}
}
/**
* 判断双击
* @param buttonID 按钮id
*/
isDoubleClick(buttonID: string) {
if (this.buttonID == buttonID && this.timer > 0) {
return true;
}
else {
return false;
}
}
/**
* 记录点击
* @param buttonID
*/
setClickEvent(buttonID: string) {
this.buttonID = buttonID;
this.timer = this.c_timer;
}
}
//#region 功能类
export class UI_LineInfo {
key: string;
mesh: AbstractMesh;
root: Rectangle;
root_size: Vector2;
points: Ellipse[] = [];
lineLength: number;
infoBg: Rectangle;
info: TextBlock;
line: MultiLine;
constructor(l_key: string, l_mesh: AbstractMesh, rootSize: Vector2, infoSize: Vector2) {
this.key = l_key;
this.mesh = l_mesh;
this.root = new Rectangle("UI_LineRoot_" + this.key);
UIManager.Instance.uiRoot.addControl(this.root);
this.root.thickness = 0;
this.root_size = rootSize;
BabylonUIStyleTool.setStyle_size(this.root, rootSize.x + "px", rootSize.y + "px");
this.root.linkWithMesh(this.mesh);
this.root.linkOffsetXInPixels = rootSize.x * 0.5;
// this.root.linkOffsetYInPixels = -40;
let point_start = new Ellipse("start");
point_start.width = "5px";
point_start.height = "5px";
this.root.addControl(point_start);
point_start.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
point_start.color = BabylonUIStyleTool.c_color_3d_blue;
point_start.background = BabylonUIStyleTool.c_color_3d_blue;
point_start.shadowColor = BabylonUIStyleTool.c_color_3d_blue;
point_start.shadowBlur = 5;
this.points.push(point_start);
let point_end = new Ellipse("end");
point_end.width = "1px";
point_end.height = "1px";
this.root.addControl(point_end);
point_end.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
point_end.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
this.lineLength = 20;
point_end.left = this.lineLength + "px";
point_end.topInPixels = infoSize.y * 0.5;
this.points.push(point_end);
this.infoBg = new Rectangle("infoBg");
BabylonUIStyleTool.setStyle_size(this.infoBg, infoSize.x + "px", infoSize.y + "px");
this.root.addControl(this.infoBg);
this.infoBg.color = BabylonUIStyleTool.c_color_3d_blue;
this.infoBg.shadowBlur = 5;
this.infoBg.shadowColor = BabylonUIStyleTool.c_color_3d_blue;
this.infoBg.background = BabylonUIStyleTool.c_color_3d_blueBg;
this.infoBg.alpha = 0.7;
this.infoBg.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_RIGHT;
this.infoBg.verticalAlignment = Control.VERTICAL_ALIGNMENT_TOP;
this.info = new TextBlock("info", "info")
this.info.fontSize = 12;
this.infoBg.addControl(this.info);
this.info.color = BabylonUIStyleTool.c_color_3d_blueLight;
let point_infoBgLeft = new Ellipse("infoBgLeft");
this.infoBg.addControl(point_infoBgLeft);
BabylonUIStyleTool.setStyle_size(point_infoBgLeft, "1px", "1px");
point_infoBgLeft.horizontalAlignment = Control.HORIZONTAL_ALIGNMENT_LEFT;
point_infoBgLeft.leftInPixels = -1
this.points.push(point_infoBgLeft);
this.line = new MultiLine("ui_line_" + this.key);
for (let i = 0; i < this.points.length; i++) {
this.line.add(this.points[i]);
}
// this.line.add(this.mesh);//起点
// this.line.add(pointL);
// this.line.add(point);
this.line.lineWidth = 1.5;
this.line.color = BabylonUIStyleTool.c_color_3d_blue;
this.line.alpha = 0.7;
this.line.shadowColor = BabylonUIStyleTool.c_color_3d_blue;
this.line.shadowBlur = 5;
UIManager.Instance.uiRoot.addControl(this.line);
}
setEnable(show: boolean) {
this.root.isVisible = show;
this.line.isVisible = show;
}
dispose() {
this.root.dispose();
this.line.dispose();
}
}
//#endregion