* refactor: reorganize package structure and decouple framework packages ## Package Structure Reorganization - Reorganized 55 packages into categorized subdirectories: - packages/framework/ - Generic framework (Laya/Cocos compatible) - packages/engine/ - ESEngine core modules - packages/rendering/ - Rendering modules (WASM dependent) - packages/physics/ - Physics modules - packages/streaming/ - World streaming - packages/network-ext/ - Network extensions - packages/editor/ - Editor framework and plugins - packages/rust/ - Rust WASM engine - packages/tools/ - Build tools and SDK ## Framework Package Decoupling - Decoupled behavior-tree and blueprint packages from ESEngine dependencies - Created abstracted interfaces (IBTAssetManager, IBehaviorTreeAssetContent) - ESEngine-specific code moved to esengine/ subpath exports - Framework packages now usable with Cocos/Laya without ESEngine ## CI Configuration - Updated CI to only type-check and lint framework packages - Added type-check:framework and lint:framework scripts ## Breaking Changes - Package import paths changed due to directory reorganization - ESEngine integrations now use subpath imports (e.g., '@esengine/behavior-tree/esengine') * fix: update es-engine file path after directory reorganization * docs: update README to focus on framework over engine * ci: only build framework packages, remove Rust/WASM dependencies * fix: remove esengine subpath from behavior-tree and blueprint builds ESEngine integration code will only be available in full engine builds. Framework packages are now purely engine-agnostic. * fix: move network-protocols to framework, build both in CI * fix: update workflow paths from packages/core to packages/framework/core * fix: exclude esengine folder from type-check in behavior-tree and blueprint * fix: update network tsconfig references to new paths * fix: add test:ci:framework to only test framework packages in CI * fix: only build core and math npm packages in CI * fix: exclude test files from CodeQL and fix string escaping security issue
229 lines
6.7 KiB
TypeScript
229 lines
6.7 KiB
TypeScript
import { GComponent } from '../core/GComponent';
|
|
import { GObject } from '../core/GObject';
|
|
import { GImage } from './GImage';
|
|
import { EProgressTitleType, EObjectPropID, EFillMethod } from '../core/FieldTypes';
|
|
import type { ByteBuffer } from '../utils/ByteBuffer';
|
|
|
|
/**
|
|
* GProgressBar
|
|
*
|
|
* Progress bar component.
|
|
*
|
|
* 进度条组件
|
|
*/
|
|
export class GProgressBar extends GComponent {
|
|
private _min: number = 0;
|
|
private _max: number = 100;
|
|
private _value: number = 50;
|
|
private _titleType: EProgressTitleType = EProgressTitleType.Percent;
|
|
private _reverse: boolean = false;
|
|
|
|
private _titleObject: GObject | null = null;
|
|
private _aniObject: GObject | null = null;
|
|
private _barObjectH: GObject | null = null;
|
|
private _barObjectV: GObject | null = null;
|
|
private _barMaxWidth: number = 0;
|
|
private _barMaxHeight: number = 0;
|
|
private _barMaxWidthDelta: number = 0;
|
|
private _barMaxHeightDelta: number = 0;
|
|
private _barStartX: number = 0;
|
|
private _barStartY: number = 0;
|
|
|
|
constructor() {
|
|
super();
|
|
}
|
|
|
|
/**
|
|
* Get/set title type
|
|
* 获取/设置标题类型
|
|
*/
|
|
public get titleType(): EProgressTitleType {
|
|
return this._titleType;
|
|
}
|
|
|
|
public set titleType(value: EProgressTitleType) {
|
|
if (this._titleType !== value) {
|
|
this._titleType = value;
|
|
this.update(this._value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get/set minimum value
|
|
* 获取/设置最小值
|
|
*/
|
|
public get min(): number {
|
|
return this._min;
|
|
}
|
|
|
|
public set min(value: number) {
|
|
if (this._min !== value) {
|
|
this._min = value;
|
|
this.update(this._value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get/set maximum value
|
|
* 获取/设置最大值
|
|
*/
|
|
public get max(): number {
|
|
return this._max;
|
|
}
|
|
|
|
public set max(value: number) {
|
|
if (this._max !== value) {
|
|
this._max = value;
|
|
this.update(this._value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get/set current value
|
|
* 获取/设置当前值
|
|
*/
|
|
public get value(): number {
|
|
return this._value;
|
|
}
|
|
|
|
public set value(value: number) {
|
|
if (this._value !== value) {
|
|
this._value = value;
|
|
this.update(value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update progress bar display
|
|
* 更新进度条显示
|
|
*/
|
|
public update(newValue: number): void {
|
|
let percent = this.clamp01((newValue - this._min) / (this._max - this._min));
|
|
|
|
if (this._titleObject) {
|
|
switch (this._titleType) {
|
|
case EProgressTitleType.Percent:
|
|
this._titleObject.text = Math.floor(percent * 100) + '%';
|
|
break;
|
|
case EProgressTitleType.ValueAndMax:
|
|
this._titleObject.text =
|
|
Math.floor(newValue) + '/' + Math.floor(this._max);
|
|
break;
|
|
case EProgressTitleType.Value:
|
|
this._titleObject.text = '' + Math.floor(newValue);
|
|
break;
|
|
case EProgressTitleType.Max:
|
|
this._titleObject.text = '' + Math.floor(this._max);
|
|
break;
|
|
}
|
|
}
|
|
|
|
const fullWidth = this.width - this._barMaxWidthDelta;
|
|
const fullHeight = this.height - this._barMaxHeightDelta;
|
|
|
|
if (!this._reverse) {
|
|
if (this._barObjectH) {
|
|
if (!this.setFillAmount(this._barObjectH, percent)) {
|
|
this._barObjectH.width = Math.round(fullWidth * percent);
|
|
}
|
|
}
|
|
if (this._barObjectV) {
|
|
if (!this.setFillAmount(this._barObjectV, percent)) {
|
|
this._barObjectV.height = Math.round(fullHeight * percent);
|
|
}
|
|
}
|
|
} else {
|
|
if (this._barObjectH) {
|
|
if (!this.setFillAmount(this._barObjectH, 1 - percent)) {
|
|
this._barObjectH.width = Math.round(fullWidth * percent);
|
|
this._barObjectH.x = this._barStartX + (fullWidth - this._barObjectH.width);
|
|
}
|
|
}
|
|
if (this._barObjectV) {
|
|
if (!this.setFillAmount(this._barObjectV, 1 - percent)) {
|
|
this._barObjectV.height = Math.round(fullHeight * percent);
|
|
this._barObjectV.y =
|
|
this._barStartY + (fullHeight - this._barObjectV.height);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (this._aniObject) {
|
|
this._aniObject.setProp(EObjectPropID.Frame, Math.floor(percent * 100));
|
|
}
|
|
}
|
|
|
|
private setFillAmount(bar: GObject, percent: number): boolean {
|
|
if (bar instanceof GImage && bar.fillMethod !== EFillMethod.None) {
|
|
bar.fillAmount = percent;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private clamp01(value: number): number {
|
|
if (value < 0) return 0;
|
|
if (value > 1) return 1;
|
|
return value;
|
|
}
|
|
|
|
protected constructExtension(buffer: ByteBuffer): void {
|
|
buffer.seek(0, 6);
|
|
|
|
this._titleType = buffer.readByte();
|
|
this._reverse = buffer.readBool();
|
|
|
|
this._titleObject = this.getChild('title');
|
|
this._barObjectH = this.getChild('bar');
|
|
this._barObjectV = this.getChild('bar_v');
|
|
this._aniObject = this.getChild('ani');
|
|
|
|
if (this._barObjectH) {
|
|
this._barMaxWidth = this._barObjectH.width;
|
|
this._barMaxWidthDelta = this.width - this._barMaxWidth;
|
|
this._barStartX = this._barObjectH.x;
|
|
}
|
|
if (this._barObjectV) {
|
|
this._barMaxHeight = this._barObjectV.height;
|
|
this._barMaxHeightDelta = this.height - this._barMaxHeight;
|
|
this._barStartY = this._barObjectV.y;
|
|
}
|
|
}
|
|
|
|
protected handleSizeChanged(): void {
|
|
super.handleSizeChanged();
|
|
|
|
if (this._barObjectH) {
|
|
this._barMaxWidth = this.width - this._barMaxWidthDelta;
|
|
}
|
|
if (this._barObjectV) {
|
|
this._barMaxHeight = this.height - this._barMaxHeightDelta;
|
|
}
|
|
if (!this._underConstruct) {
|
|
this.update(this._value);
|
|
}
|
|
}
|
|
|
|
public setup_afterAdd(buffer: ByteBuffer, beginPos: number): void {
|
|
super.setup_afterAdd(buffer, beginPos);
|
|
|
|
if (!buffer.seek(beginPos, 6)) {
|
|
this.update(this._value);
|
|
return;
|
|
}
|
|
|
|
if (buffer.readByte() !== this.packageItem?.objectType) {
|
|
this.update(this._value);
|
|
return;
|
|
}
|
|
|
|
this._value = buffer.getInt32();
|
|
this._max = buffer.getInt32();
|
|
if (buffer.version >= 2) {
|
|
this._min = buffer.getInt32();
|
|
}
|
|
|
|
this.update(this._value);
|
|
}
|
|
}
|