From 0c5321e9dea3898b358fb2619d19627c5987d6b1 Mon Sep 17 00:00:00 2001 From: joylink_zhaoerwei Date: Thu, 4 Jul 2024 15:31:09 +0800 Subject: [PATCH] Squashed commit of the following: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 7a1925cfbec25532a649caec5a88675ed98e9472 Author: joylink_zhaoerwei Date: Thu Jul 4 15:29:41 2024 +0800 列车驾驶台按钮+灯备用 commit 6d54d2e5d5449d766c6a92b9aa67b701c5deeb26 Author: joylink_zhaoerwei Date: Thu Jul 4 09:17:51 2024 +0800 更改前端pixi绘图版本 --- package.json | 2 +- src/api/Simulation.ts | 2 +- src/components/draw-app/TccDrawProperties.vue | 5 + .../draw-app/properties/TccButtonProperty.vue | 2 +- .../draw-app/properties/TccLightProperty.vue | 44 +++++ src/drawApp/graphics/TccButtonInteraction.ts | 10 +- src/drawApp/graphics/TccLightInteraction.ts | 88 +++++++++ src/drawApp/lineScene.ts | 1 - src/drawApp/tccApp.ts | 13 ++ src/drawApp/tccScene.ts | 12 +- src/graphics/tccButton/TccButton.ts | 1 - .../tccButton/TccButtonDrawAssistant.ts | 2 +- src/graphics/tccLight/TccLight.ts | 99 ++++++++++ .../tccLight/TccLightDrawAssistant.ts | 129 +++++++++++++ src/graphics/tccLight/tcc-light-data.json | 29 +++ .../tccLight/tcc-light-spritesheet.png | Bin 0 -> 24727 bytes src/layouts/TrainControlCabDrawLayout.vue | 2 + src/protos/device_state.ts | 97 +++++++--- src/protos/request.ts | 99 ++++++++-- src/protos/tccGraphics.ts | 169 +++++++++++++++++- yarn.lock | 6 +- 21 files changed, 751 insertions(+), 61 deletions(-) create mode 100644 src/components/draw-app/properties/TccLightProperty.vue create mode 100644 src/drawApp/graphics/TccLightInteraction.ts create mode 100644 src/graphics/tccLight/TccLight.ts create mode 100644 src/graphics/tccLight/TccLightDrawAssistant.ts create mode 100644 src/graphics/tccLight/tcc-light-data.json create mode 100644 src/graphics/tccLight/tcc-light-spritesheet.png diff --git a/package.json b/package.json index 7a20af7..fda9882 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "default-passive-events": "^2.0.0", "echarts": "^5.4.3", "google-protobuf": "^3.21.2", - "jl-graphic": "git+http://120.46.212.6:3000/joylink/graphic-pixi.git#v0.1.14", + "jl-graphic": "git+http://120.46.212.6:3000/joylink/graphic-pixi.git#v0.1.15", "js-base64": "^3.7.5", "pinia": "^2.0.11", "quasar": "^2.6.0", diff --git a/src/api/Simulation.ts b/src/api/Simulation.ts index 259d381..7ba81c9 100644 --- a/src/api/Simulation.ts +++ b/src/api/Simulation.ts @@ -189,7 +189,7 @@ export interface TccOperationParams { trainId: string; deviceId: number; controlType: request.TrainControl.TrainControlType; - button?: object; + controlButton?: object; driverKey?: object; dirKey?: object; handler?: object; diff --git a/src/components/draw-app/TccDrawProperties.vue b/src/components/draw-app/TccDrawProperties.vue index d9d601d..bca34bd 100644 --- a/src/components/draw-app/TccDrawProperties.vue +++ b/src/components/draw-app/TccDrawProperties.vue @@ -27,6 +27,9 @@ + @@ -44,6 +47,8 @@ import { TccKey } from 'src/graphics/tccKey/TccKey'; import TccKeyProperty from './properties/TccKeyProperty.vue'; import { TccHandle } from 'src/graphics/tccHandle/TccHandle'; import TccHandleProperty from './properties/TccHandleProperty.vue'; +import { TccLight } from 'src/graphics/tccLight/TccLight'; +import TccLightProperty from './properties/TccLightProperty.vue'; const tccDrawStore = useTccDrawStore(); diff --git a/src/components/draw-app/properties/TccButtonProperty.vue b/src/components/draw-app/properties/TccButtonProperty.vue index 742074f..55f7975 100644 --- a/src/components/draw-app/properties/TccButtonProperty.vue +++ b/src/components/draw-app/properties/TccButtonProperty.vue @@ -5,7 +5,7 @@ outlined v-model="tccButtonModel.code" @blur="onUpdate" - label="紧急制动按钮" + label="Tcc按钮" lazy-rules /> + + + + + + + + + diff --git a/src/drawApp/graphics/TccButtonInteraction.ts b/src/drawApp/graphics/TccButtonInteraction.ts index 54ccd08..6d433cb 100644 --- a/src/drawApp/graphics/TccButtonInteraction.ts +++ b/src/drawApp/graphics/TccButtonInteraction.ts @@ -58,12 +58,12 @@ export class TccButtonState extends GraphicStateBase implements ITccButtonState { - constructor(proto?: state.TrainControlState.EmergentButton) { + constructor(proto?: state.TrainControlState.ControlButton) { let states; if (proto) { states = proto; } else { - states = new state.TrainControlState.EmergentButton(); + states = new state.TrainControlState.ControlButton(); } super(states, TccButton.Type); } @@ -76,8 +76,8 @@ export class TccButtonState set down(v: boolean) { this.states.passed = v; } - get states(): state.TrainControlState.EmergentButton { - return this.getState(); + get states(): state.TrainControlState.ControlButton { + return this.getState(); } clone(): TccButtonState { return new TccButtonState(this.states.cloneMessage()); @@ -125,7 +125,7 @@ export class TccButtonOperateInteraction extends GraphicInteractionPlugin { diff --git a/src/drawApp/graphics/TccLightInteraction.ts b/src/drawApp/graphics/TccLightInteraction.ts new file mode 100644 index 0000000..42e46c1 --- /dev/null +++ b/src/drawApp/graphics/TccLightInteraction.ts @@ -0,0 +1,88 @@ +import * as pb_1 from 'google-protobuf'; +import { + ItccLightData, + ItccLightState, + TccLight, +} from 'src/graphics/tccLight/TccLight'; +import { tccGraphicData } from 'src/protos/tccGraphics'; +import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase'; +import { state } from 'src/protos/device_state'; + +export class TccLightData extends GraphicDataBase implements ItccLightData { + constructor(data?: tccGraphicData.TccLight) { + let tccLight; + if (data) { + tccLight = data; + } else { + tccLight = new tccGraphicData.TccLight({ + common: GraphicDataBase.defaultCommonInfo(TccLight.Type), + }); + } + super(tccLight); + } + + public get data(): tccGraphicData.TccLight { + return this.getData(); + } + + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get lightColor(): tccGraphicData.TccElementColor { + return this.data.lightColor; + } + set lightColor(v: tccGraphicData.TccElementColor) { + this.data.lightColor = v; + } + get activeLevel(): boolean { + return this.data.activeLevel; + } + set activeLevel(v: boolean) { + this.data.activeLevel = v; + } + clone(): TccLightData { + return new TccLightData(this.data.cloneMessage()); + } + copyFrom(data: TccLightData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: TccLightData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} + +export class TccLightState extends GraphicStateBase implements ItccLightState { + constructor(proto?: state.TrainControlState.ControlButton) { + let states; + if (proto) { + states = proto; + } else { + states = new state.TrainControlState.ControlButton(); + } + super(states, TccLight.Type); + } + get code(): string { + return this.states.id + ''; + } + get active(): boolean { + return this.states.passed; + } + set active(v: boolean) { + this.states.passed = v; + } + get states(): state.TrainControlState.ControlButton { + return this.getState(); + } + clone(): TccLightState { + return new TccLightState(this.states.cloneMessage()); + } + copyFrom(data: GraphicStateBase): void { + pb_1.Message.copyInto(data._state, this._state); + } + eq(data: GraphicStateBase): boolean { + return pb_1.Message.equals(this._state, data._state); + } +} diff --git a/src/drawApp/lineScene.ts b/src/drawApp/lineScene.ts index 37d487e..9199b75 100644 --- a/src/drawApp/lineScene.ts +++ b/src/drawApp/lineScene.ts @@ -470,7 +470,6 @@ function handleSubscribe(lineScene: IGraphicScene) { states.push(new CarWashingState(item)); } }); - console.log(storage.allStatus.trainState, '===='); storage.allStatus.trainState.forEach((item) => { // 列车 if (!item.show) { diff --git a/src/drawApp/tccApp.ts b/src/drawApp/tccApp.ts index 5198803..617f9e4 100644 --- a/src/drawApp/tccApp.ts +++ b/src/drawApp/tccApp.ts @@ -32,6 +32,10 @@ import { TccKeyData, TccKeyState } from './graphics/TccKeyInteraction'; import { TccHandleDraw } from 'src/graphics/tccHandle/TccHandleDrawAssistant'; import { TccHandle, TccHandleTemplate } from 'src/graphics/tccHandle/TccHandle'; import { TccHandleData, TccHandleState } from './graphics/TccHandleInteraction'; +import { TccLightDraw } from 'src/graphics/tccLight/TccLightDrawAssistant'; +import { TccLightData, TccLightState } from './graphics/TccLightInteraction'; +import { TccLight, TccLightTemplate } from 'src/graphics/tccLight/TccLight'; + const UndoOptions: MenuItemOptions = { name: '撤销', @@ -87,6 +91,10 @@ export function initTccDrawApp(): IDrawApp { drawApp, new TccHandleTemplate(new TccHandleData(), new TccHandleState()) ); + new TccLightDraw( + app, + new TccLightTemplate(new TccLightData(), new TccLightState()) + ); // 画布右键菜单 app.registerMenu(DefaultCanvasMenu); @@ -181,6 +189,8 @@ export function saveTccDrawDatas(app: IDrawApp) { storage.tccKeys.push(g.saveData().data); } else if (g instanceof TccHandle) { storage.tccHandles.push(g.saveData().data); + } else if (g instanceof TccLight) { + storage.tccLights.push(g.saveData().data); } }); const base64 = fromUint8Array(storage.serialize()); @@ -214,6 +224,9 @@ export async function loadTccDrawDatas(): Promise { storage.tccTexts.forEach((tccText) => { datas.push(new TccTextData(tccText)); }); + storage.tccLights.forEach((tccLight) => { + datas.push(new TccLightData(tccLight)); + }); return { canvasProperty: storage.canvas, datas: datas, diff --git a/src/drawApp/tccScene.ts b/src/drawApp/tccScene.ts index 5beeca6..66b59df 100644 --- a/src/drawApp/tccScene.ts +++ b/src/drawApp/tccScene.ts @@ -31,6 +31,8 @@ import { TccHandleInteraction, TccHandleState, } from './graphics/TccHandleInteraction'; +import { TccLightTemplate } from 'src/graphics/tccLight/TccLight'; +import { TccLightData, TccLightState } from './graphics/TccLightInteraction'; export function initTccScene(lineApp: IGraphicApp, sceneName: string) { const tccScene = lineApp.initScene(sceneName, { @@ -45,6 +47,7 @@ export function initTccScene(lineApp: IGraphicApp, sceneName: string) { new TextContentTemplate(new TccTextData()), new TccKeyTemplate(new TccKeyData(), new TccKeyState()), new TccHandleTemplate(new TccHandleData(), new TccHandleState()), + new TccLightTemplate(new TccLightData(), new TccLightState()), ]; TccButtonOperateInteraction.init(tccScene); TccKeyInteraction.init(tccScene); @@ -84,9 +87,9 @@ function handleSubscribe(tccScene: IGraphicScene) { messageConverter: (message: Uint8Array) => { const states: GraphicState[] = []; const storage = state.TrainControlState.deserialize(message); - if (storage.ebutton) { - states.push(new TccButtonState(storage.ebutton)); - } + storage.buttons.forEach((button) => { + states.push(new TccButtonState(button)); + }); if (storage.dirKey) { states.push(new TccKeyState(storage.dirKey)); } @@ -130,6 +133,9 @@ async function loadTccDatas(): Promise { storage.tccTexts.forEach((tccText) => { datas.push(new TccTextData(tccText)); }); + storage.tccLights.forEach((tccLight) => { + datas.push(new TccLightData(tccLight)); + }); return Promise.resolve({ canvasProperty: storage.canvas, datas: datas, diff --git a/src/graphics/tccButton/TccButton.ts b/src/graphics/tccButton/TccButton.ts index 9bb23c0..9b42c3c 100644 --- a/src/graphics/tccButton/TccButton.ts +++ b/src/graphics/tccButton/TccButton.ts @@ -8,7 +8,6 @@ import Tcc_Button_Assets from './tcc-button-spritesheet.png'; import Tcc_Button_JSON from './tcc-button-data.json'; import { Assets, Sprite, Spritesheet, Texture } from 'pixi.js'; -import { tccGraphicData } from 'src/protos/tccGraphics'; interface TccButtonTextures { redBtn: Texture; diff --git a/src/graphics/tccButton/TccButtonDrawAssistant.ts b/src/graphics/tccButton/TccButtonDrawAssistant.ts index a2d26af..6e1562f 100644 --- a/src/graphics/tccButton/TccButtonDrawAssistant.ts +++ b/src/graphics/tccButton/TccButtonDrawAssistant.ts @@ -87,7 +87,7 @@ function buildAbsorbablePositions(tccButton: TccButton): AbsorbablePosition[] { } export class TccButtonInteraction extends GraphicInteractionPlugin { - static Name = 'tcc_light_transform'; + static Name = 'tcc_button_transform'; constructor(app: IDrawApp) { super(TccButtonInteraction.Name, app); } diff --git a/src/graphics/tccLight/TccLight.ts b/src/graphics/tccLight/TccLight.ts new file mode 100644 index 0000000..8943cee --- /dev/null +++ b/src/graphics/tccLight/TccLight.ts @@ -0,0 +1,99 @@ +import { + GraphicData, + GraphicState, + JlGraphic, + JlGraphicTemplate, +} from 'jl-graphic'; +import tcc_Light_Assets from './tcc-light-spritesheet.png'; +import tcc_Light_JSON from './tcc-light-data.json'; + +import { Assets, Sprite, Spritesheet, Texture } from 'pixi.js'; +import { tccGraphicData } from 'src/protos/tccGraphics'; + +interface TccLightTextures { + redOn: Texture; + redOff: Texture; + greenOn: Texture; + greenOff: Texture; + blueOn: Texture; + blueOff: Texture; +} + +export interface ItccLightData extends GraphicData { + get code(): string; + set code(v: string); + get lightColor(): tccGraphicData.TccElementColor; + set lightColor(v: tccGraphicData.TccElementColor); + get activeLevel(): boolean; + set activeLevel(v: boolean); +} + +export interface ItccLightState extends GraphicState { + id?: number; + get active(): boolean; + set active(v: boolean); +} + +export class TccLight extends JlGraphic { + static Type = 'TccLight'; + _tccLight: Sprite; + tccLightTextures: TccLightTextures; + __state = 0; + + constructor(tccLightTextures: TccLightTextures) { + super(TccLight.Type); + this.tccLightTextures = tccLightTextures; + this._tccLight = new Sprite(); + this._tccLight.texture = this.tccLightTextures.greenOff; + this._tccLight.scale.set(0.25); + this._tccLight.anchor.set(0.5); + this.addChild(this._tccLight); + } + get code(): string { + return this.datas.code; + } + get datas(): ItccLightData { + return this.getDatas(); + } + get states(): ItccLightState { + return this.getStates(); + } + doRepaint(): void { + if (this.states.active == this.datas.activeLevel) { + this._tccLight.texture = this.tccLightTextures.greenOn; + } else { + this._tccLight.texture = this.tccLightTextures.greenOff; + } + } +} + +export class TccLightTemplate extends JlGraphicTemplate { + tccLightTextures?: TccLightTextures; + constructor(dataTemplate: ItccLightData, stateTemplate: ItccLightState) { + super(TccLight.Type, { dataTemplate, stateTemplate }); + this.loadAssets(); + } + new(): TccLight { + if (this.tccLightTextures) { + const g = new TccLight(this.tccLightTextures); + g.loadData(this.datas); + g.loadState(this.states); + return g; + } + throw new Error('资源未加载/加载失败'); + } + async loadAssets(): Promise { + const texture = await Assets.load(tcc_Light_Assets); + const tccLightSheet = new Spritesheet(texture, tcc_Light_JSON); + const result = await tccLightSheet.parse(); + this.tccLightTextures = { + redOff: result['red-off.png'], + redOn: result['red-on.png'], + blueOff: result['blue-off.png'], + blueOn: result['blue-on.png'], + greenOff: result['green-off.png'], + greenOn: result['green-on.png'], + }; + return this.tccLightTextures as TccLightTextures; + } +} diff --git a/src/graphics/tccLight/TccLightDrawAssistant.ts b/src/graphics/tccLight/TccLightDrawAssistant.ts new file mode 100644 index 0000000..045dae1 --- /dev/null +++ b/src/graphics/tccLight/TccLightDrawAssistant.ts @@ -0,0 +1,129 @@ +import { DisplayObject, FederatedMouseEvent, Point } from 'pixi.js'; +import { + AbsorbableLine, + AbsorbablePosition, + GraphicDrawAssistant, + GraphicInteractionPlugin, + GraphicTransformEvent, + IDrawApp, + JlGraphic, +} from 'jl-graphic'; +import { TccButton } from '../tccButton/TccButton'; +import { ItccLightData, TccLight, TccLightTemplate } from './TccLight'; + +export class TccLightDraw extends GraphicDrawAssistant< + TccLightTemplate, + ItccLightData +> { + _tccLight: TccLight | null = null; + constructor(app: IDrawApp, template: TccLightTemplate) { + super(app, template, 'sym_o_lightbulb', 'Tcc灯'); + TccLightInteraction.init(app); + } + + bind(): void { + super.bind(); + if (!this._tccLight) { + this._tccLight = this.graphicTemplate.new(); + this.container.addChild(this._tccLight); + } + } + + public get tccLight(): TccLight { + if (!this._tccLight) { + this._tccLight = this.graphicTemplate.new(); + this.container.addChild(this._tccLight); + } + return this._tccLight; + } + + redraw(cp: Point): void { + this.tccLight.position.copyFrom(cp); + } + onLeftUp(e: FederatedMouseEvent): void { + this.tccLight.position.copyFrom(this.toCanvasCoordinates(e.global)); + this.createAndStore(true); + } + prepareData(data: ItccLightData): boolean { + data.transform = this.tccLight.saveTransform(); + return true; + } + onEsc(): void { + this.finish(); + } +} + +/** + * 构建吸附线 + * @param tccLight + */ +function buildAbsorbablePositions(tccLight: TccLight): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + const TccButtons = tccLight.queryStore.queryByType(TccButton.Type); + const tccLights = tccLight.queryStore.queryByType(TccLight.Type); + const canvas = tccLight.getCanvas(); + TccButtons.forEach((item) => { + const ala = new AbsorbableLine( + new Point(item.x, 0), + new Point(item.x, canvas.height) + ); + const alb = new AbsorbableLine( + new Point(0, item.y), + new Point(canvas.width, item.y) + ); + aps.push(ala); + aps.push(alb); + }); + tccLights.forEach((item) => { + if (item.id === tccLight.id) { + return; + } + const ala = new AbsorbableLine( + new Point(item.x, 0), + new Point(item.x, canvas.height) + ); + const alb = new AbsorbableLine( + new Point(0, item.y), + new Point(canvas.width, item.y) + ); + aps.push(ala); + aps.push(alb); + }); + + return aps; +} + +export class TccLightInteraction extends GraphicInteractionPlugin { + static Name = 'tcc_light_transform'; + constructor(app: IDrawApp) { + super(TccLightInteraction.Name, app); + } + static init(app: IDrawApp) { + return new TccLightInteraction(app); + } + filter(...grahpics: JlGraphic[]): TccLight[] | undefined { + return grahpics + .filter((g) => g.type === TccLight.Type) + .map((g) => g as TccLight); + } + bind(g: TccLight): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.scalable = true; + g.rotatable = true; + g.on('transformstart', this.transformstart, this); + } + unbind(g: TccLight): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + g.off('transformstart', this.transformstart, this); + } + transformstart(e: GraphicTransformEvent) { + const target = e.target as DisplayObject; + const tccLight = target.getGraphic() as TccLight; + tccLight.getGraphicApp().setOptions({ + absorbablePositions: buildAbsorbablePositions(tccLight), + }); + } +} diff --git a/src/graphics/tccLight/tcc-light-data.json b/src/graphics/tccLight/tcc-light-data.json new file mode 100644 index 0000000..225241a --- /dev/null +++ b/src/graphics/tccLight/tcc-light-data.json @@ -0,0 +1,29 @@ +{ + "frames": { + "green-off.png": { + "frame": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 128 }, + "anchor": { "x": 0.5, "y": 0.5 } + }, + "green-on.png": { + "frame": { "x": 128, "y": 0, "w": 128, "h": 128 }, + "rotated": false, + "trimmed": false, + "spriteSourceSize": { "x": 0, "y": 0, "w": 128, "h": 128 }, + "sourceSize": { "w": 128, "h": 64 }, + "anchor": { "x": 0.5, "y": 0.5 } + } + }, + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.1", + "image": "tcc-light.png", + "format": "RGBA8888", + "size": { "w": 256, "h": 128 }, + "scale": "0.5", + "smartupdate": "$TexturePacker:SmartUpdate:e7620bd2d73cc0b3e2deea9704e7eefc:f129a1d9e4b9ba57720b3861c22b155b:eb2d421f7759984b7713aa4aa5354134$" + } +} diff --git a/src/graphics/tccLight/tcc-light-spritesheet.png b/src/graphics/tccLight/tcc-light-spritesheet.png new file mode 100644 index 0000000000000000000000000000000000000000..8f8ffc0d497c9ca5df38ff09eea35bc52d5220d3 GIT binary patch literal 24727 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 { TextContent.Type, TccKey.Type, TccHandle.Type, + TccLight.Type, ]; drawAssistantsTypes.forEach((type) => { const drawAssistant = getTccDrawApp()?.getDrawAssistant(type); diff --git a/src/protos/device_state.ts b/src/protos/device_state.ts index 25c3f30..f4ca2de 100644 --- a/src/protos/device_state.ts +++ b/src/protos/device_state.ts @@ -2955,6 +2955,7 @@ export namespace state { atoSendTrainBtn?: boolean; trainIntegrity?: boolean; atpOrAtoBypassState?: boolean; + trainTractionCuted?: boolean; obstacleCheckBtn?: boolean; driverActiveReportBtn?: boolean; brakeHeavyFault?: boolean; @@ -2995,6 +2996,7 @@ export namespace state { atoTractionCommand2?: boolean; atoTractionCommand3?: boolean; mockInfo?: number; + atpCutSwitch?: boolean; }) { super(); pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); @@ -3098,6 +3100,9 @@ export namespace state { if ("atpOrAtoBypassState" in data && data.atpOrAtoBypassState != undefined) { this.atpOrAtoBypassState = data.atpOrAtoBypassState; } + if ("trainTractionCuted" in data && data.trainTractionCuted != undefined) { + this.trainTractionCuted = data.trainTractionCuted; + } if ("obstacleCheckBtn" in data && data.obstacleCheckBtn != undefined) { this.obstacleCheckBtn = data.obstacleCheckBtn; } @@ -3218,6 +3223,9 @@ export namespace state { if ("mockInfo" in data && data.mockInfo != undefined) { this.mockInfo = data.mockInfo; } + if ("atpCutSwitch" in data && data.atpCutSwitch != undefined) { + this.atpCutSwitch = data.atpCutSwitch; + } } } get lifeSignal() { @@ -3418,6 +3426,12 @@ export namespace state { set atpOrAtoBypassState(value: boolean) { pb_1.Message.setField(this, 33, value); } + get trainTractionCuted() { + return pb_1.Message.getFieldWithDefault(this, 34, false) as boolean; + } + set trainTractionCuted(value: boolean) { + pb_1.Message.setField(this, 34, value); + } get obstacleCheckBtn() { return pb_1.Message.getFieldWithDefault(this, 35, false) as boolean; } @@ -3658,6 +3672,12 @@ export namespace state { set mockInfo(value: number) { pb_1.Message.setField(this, 75, value); } + get atpCutSwitch() { + return pb_1.Message.getFieldWithDefault(this, 76, false) as boolean; + } + set atpCutSwitch(value: boolean) { + pb_1.Message.setField(this, 76, value); + } static fromObject(data: { lifeSignal?: number; tc1Active?: boolean; @@ -3692,6 +3712,7 @@ export namespace state { atoSendTrainBtn?: boolean; trainIntegrity?: boolean; atpOrAtoBypassState?: boolean; + trainTractionCuted?: boolean; obstacleCheckBtn?: boolean; driverActiveReportBtn?: boolean; brakeHeavyFault?: boolean; @@ -3732,6 +3753,7 @@ export namespace state { atoTractionCommand2?: boolean; atoTractionCommand3?: boolean; mockInfo?: number; + atpCutSwitch?: boolean; }): TrainVobcState { const message = new TrainVobcState({}); if (data.lifeSignal != null) { @@ -3833,6 +3855,9 @@ export namespace state { if (data.atpOrAtoBypassState != null) { message.atpOrAtoBypassState = data.atpOrAtoBypassState; } + if (data.trainTractionCuted != null) { + message.trainTractionCuted = data.trainTractionCuted; + } if (data.obstacleCheckBtn != null) { message.obstacleCheckBtn = data.obstacleCheckBtn; } @@ -3953,6 +3978,9 @@ export namespace state { if (data.mockInfo != null) { message.mockInfo = data.mockInfo; } + if (data.atpCutSwitch != null) { + message.atpCutSwitch = data.atpCutSwitch; + } return message; } toObject() { @@ -3990,6 +4018,7 @@ export namespace state { atoSendTrainBtn?: boolean; trainIntegrity?: boolean; atpOrAtoBypassState?: boolean; + trainTractionCuted?: boolean; obstacleCheckBtn?: boolean; driverActiveReportBtn?: boolean; brakeHeavyFault?: boolean; @@ -4030,6 +4059,7 @@ export namespace state { atoTractionCommand2?: boolean; atoTractionCommand3?: boolean; mockInfo?: number; + atpCutSwitch?: boolean; } = {}; if (this.lifeSignal != null) { data.lifeSignal = this.lifeSignal; @@ -4130,6 +4160,9 @@ export namespace state { if (this.atpOrAtoBypassState != null) { data.atpOrAtoBypassState = this.atpOrAtoBypassState; } + if (this.trainTractionCuted != null) { + data.trainTractionCuted = this.trainTractionCuted; + } if (this.obstacleCheckBtn != null) { data.obstacleCheckBtn = this.obstacleCheckBtn; } @@ -4250,6 +4283,9 @@ export namespace state { if (this.mockInfo != null) { data.mockInfo = this.mockInfo; } + if (this.atpCutSwitch != null) { + data.atpCutSwitch = this.atpCutSwitch; + } return data; } serialize(): Uint8Array; @@ -4322,6 +4358,8 @@ export namespace state { writer.writeBool(32, this.trainIntegrity); if (this.atpOrAtoBypassState != false) writer.writeBool(33, this.atpOrAtoBypassState); + if (this.trainTractionCuted != false) + writer.writeBool(34, this.trainTractionCuted); if (this.obstacleCheckBtn != false) writer.writeBool(35, this.obstacleCheckBtn); if (this.driverActiveReportBtn != false) @@ -4402,6 +4440,8 @@ export namespace state { writer.writeBool(74, this.atoTractionCommand3); if (this.mockInfo != 0) writer.writeUint32(75, this.mockInfo); + if (this.atpCutSwitch != false) + writer.writeBool(76, this.atpCutSwitch); if (!w) return writer.getResultBuffer(); } @@ -4510,6 +4550,9 @@ export namespace state { case 33: message.atpOrAtoBypassState = reader.readBool(); break; + case 34: + message.trainTractionCuted = reader.readBool(); + break; case 35: message.obstacleCheckBtn = reader.readBool(); break; @@ -4630,6 +4673,9 @@ export namespace state { case 75: message.mockInfo = reader.readUint32(); break; + case 76: + message.atpCutSwitch = reader.readBool(); + break; default: reader.skipField(); } } @@ -9994,16 +10040,16 @@ export namespace state { export class TrainControlState extends pb_1.Message { #one_of_decls: number[][] = []; constructor(data?: any[] | { - ebutton?: TrainControlState.EmergentButton; + buttons?: TrainControlState.ControlButton[]; driverKey?: TrainControlState.DriverKeySwitch[]; dirKey?: TrainControlState.DirectionKeySwitch; pushHandler?: TrainControlState.PushHandler; }) { super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2], this.#one_of_decls); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [1, 2], this.#one_of_decls); if (!Array.isArray(data) && typeof data == "object") { - if ("ebutton" in data && data.ebutton != undefined) { - this.ebutton = data.ebutton; + if ("buttons" in data && data.buttons != undefined) { + this.buttons = data.buttons; } if ("driverKey" in data && data.driverKey != undefined) { this.driverKey = data.driverKey; @@ -10016,14 +10062,11 @@ export namespace state { } } } - get ebutton() { - return pb_1.Message.getWrapperField(this, TrainControlState.EmergentButton, 1) as TrainControlState.EmergentButton; + get buttons() { + return pb_1.Message.getRepeatedWrapperField(this, TrainControlState.ControlButton, 1) as TrainControlState.ControlButton[]; } - set ebutton(value: TrainControlState.EmergentButton) { - pb_1.Message.setWrapperField(this, 1, value); - } - get has_ebutton() { - return pb_1.Message.getField(this, 1) != null; + set buttons(value: TrainControlState.ControlButton[]) { + pb_1.Message.setRepeatedWrapperField(this, 1, value); } get driverKey() { return pb_1.Message.getRepeatedWrapperField(this, TrainControlState.DriverKeySwitch, 2) as TrainControlState.DriverKeySwitch[]; @@ -10050,14 +10093,14 @@ export namespace state { return pb_1.Message.getField(this, 4) != null; } static fromObject(data: { - ebutton?: ReturnType; + buttons?: ReturnType[]; driverKey?: ReturnType[]; dirKey?: ReturnType; pushHandler?: ReturnType; }): TrainControlState { const message = new TrainControlState({}); - if (data.ebutton != null) { - message.ebutton = TrainControlState.EmergentButton.fromObject(data.ebutton); + if (data.buttons != null) { + message.buttons = data.buttons.map(item => TrainControlState.ControlButton.fromObject(item)); } if (data.driverKey != null) { message.driverKey = data.driverKey.map(item => TrainControlState.DriverKeySwitch.fromObject(item)); @@ -10072,13 +10115,13 @@ export namespace state { } toObject() { const data: { - ebutton?: ReturnType; + buttons?: ReturnType[]; driverKey?: ReturnType[]; dirKey?: ReturnType; pushHandler?: ReturnType; } = {}; - if (this.ebutton != null) { - data.ebutton = this.ebutton.toObject(); + if (this.buttons != null) { + data.buttons = this.buttons.map((item: TrainControlState.ControlButton) => item.toObject()); } if (this.driverKey != null) { data.driverKey = this.driverKey.map((item: TrainControlState.DriverKeySwitch) => item.toObject()); @@ -10095,8 +10138,8 @@ export namespace state { serialize(w: pb_1.BinaryWriter): void; serialize(w?: pb_1.BinaryWriter): Uint8Array | void { const writer = w || new pb_1.BinaryWriter(); - if (this.has_ebutton) - writer.writeMessage(1, this.ebutton, () => this.ebutton.serialize(writer)); + if (this.buttons.length) + writer.writeRepeatedMessage(1, this.buttons, (item: TrainControlState.ControlButton) => item.serialize(writer)); if (this.driverKey.length) writer.writeRepeatedMessage(2, this.driverKey, (item: TrainControlState.DriverKeySwitch) => item.serialize(writer)); if (this.has_dirKey) @@ -10113,7 +10156,7 @@ export namespace state { break; switch (reader.getFieldNumber()) { case 1: - reader.readMessage(message.ebutton, () => message.ebutton = TrainControlState.EmergentButton.deserialize(reader)); + reader.readMessage(message.buttons, () => pb_1.Message.addToRepeatedWrapperField(message, 1, TrainControlState.ControlButton.deserialize(reader), TrainControlState.ControlButton)); break; case 2: reader.readMessage(message.driverKey, () => pb_1.Message.addToRepeatedWrapperField(message, 2, TrainControlState.DriverKeySwitch.deserialize(reader), TrainControlState.DriverKeySwitch)); @@ -10137,7 +10180,7 @@ export namespace state { } } export namespace TrainControlState { - export class EmergentButton extends pb_1.Message { + export class ControlButton extends pb_1.Message { #one_of_decls: number[][] = []; constructor(data?: any[] | { id?: number; @@ -10169,8 +10212,8 @@ export namespace state { static fromObject(data: { id?: number; passed?: boolean; - }): EmergentButton { - const message = new EmergentButton({}); + }): ControlButton { + const message = new ControlButton({}); if (data.id != null) { message.id = data.id; } @@ -10203,8 +10246,8 @@ export namespace state { if (!w) return writer.getResultBuffer(); } - static deserialize(bytes: Uint8Array | pb_1.BinaryReader): EmergentButton { - const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new EmergentButton(); + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): ControlButton { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new ControlButton(); while (reader.nextField()) { if (reader.isEndGroup()) break; @@ -10223,8 +10266,8 @@ export namespace state { serializeBinary(): Uint8Array { return this.serialize(); } - static deserializeBinary(bytes: Uint8Array): EmergentButton { - return EmergentButton.deserialize(bytes); + static deserializeBinary(bytes: Uint8Array): ControlButton { + return ControlButton.deserialize(bytes); } } export class DriverKeySwitch extends pb_1.Message { diff --git a/src/protos/request.ts b/src/protos/request.ts index ebcb81b..c23e593 100644 --- a/src/protos/request.ts +++ b/src/protos/request.ts @@ -1421,7 +1421,7 @@ export namespace request { trainId?: string; deviceId?: number; controlType?: TrainControl.TrainControlType; - button?: TrainControl.EmergentButton; + controlButton?: TrainControl.ControlButton; driverKey?: TrainControl.DriverKeySwitch; dirKey?: TrainControl.DirectionKeySwitch; handler?: TrainControl.PushHandler; @@ -1441,8 +1441,8 @@ export namespace request { if ("controlType" in data && data.controlType != undefined) { this.controlType = data.controlType; } - if ("button" in data && data.button != undefined) { - this.button = data.button; + if ("controlButton" in data && data.controlButton != undefined) { + this.controlButton = data.controlButton; } if ("driverKey" in data && data.driverKey != undefined) { this.driverKey = data.driverKey; @@ -1479,13 +1479,13 @@ export namespace request { set controlType(value: TrainControl.TrainControlType) { pb_1.Message.setField(this, 4, value); } - get button() { - return pb_1.Message.getWrapperField(this, TrainControl.EmergentButton, 5) as TrainControl.EmergentButton; + get controlButton() { + return pb_1.Message.getWrapperField(this, TrainControl.ControlButton, 5) as TrainControl.ControlButton; } - set button(value: TrainControl.EmergentButton) { + set controlButton(value: TrainControl.ControlButton) { pb_1.Message.setWrapperField(this, 5, value); } - get has_button() { + get has_controlButton() { return pb_1.Message.getField(this, 5) != null; } get driverKey() { @@ -1520,7 +1520,7 @@ export namespace request { trainId?: string; deviceId?: number; controlType?: TrainControl.TrainControlType; - button?: ReturnType; + controlButton?: ReturnType; driverKey?: ReturnType; dirKey?: ReturnType; handler?: ReturnType; @@ -1538,8 +1538,8 @@ export namespace request { if (data.controlType != null) { message.controlType = data.controlType; } - if (data.button != null) { - message.button = TrainControl.EmergentButton.fromObject(data.button); + if (data.controlButton != null) { + message.controlButton = TrainControl.ControlButton.fromObject(data.controlButton); } if (data.driverKey != null) { message.driverKey = TrainControl.DriverKeySwitch.fromObject(data.driverKey); @@ -1558,7 +1558,7 @@ export namespace request { trainId?: string; deviceId?: number; controlType?: TrainControl.TrainControlType; - button?: ReturnType; + controlButton?: ReturnType; driverKey?: ReturnType; dirKey?: ReturnType; handler?: ReturnType; @@ -1575,8 +1575,8 @@ export namespace request { if (this.controlType != null) { data.controlType = this.controlType; } - if (this.button != null) { - data.button = this.button.toObject(); + if (this.controlButton != null) { + data.controlButton = this.controlButton.toObject(); } if (this.driverKey != null) { data.driverKey = this.driverKey.toObject(); @@ -1601,8 +1601,8 @@ export namespace request { writer.writeUint32(3, this.deviceId); if (this.controlType != TrainControl.TrainControlType.EMERGENT_BUTTON) writer.writeEnum(4, this.controlType); - if (this.has_button) - writer.writeMessage(5, this.button, () => this.button.serialize(writer)); + if (this.has_controlButton) + writer.writeMessage(5, this.controlButton, () => this.controlButton.serialize(writer)); if (this.has_driverKey) writer.writeMessage(6, this.driverKey, () => this.driverKey.serialize(writer)); if (this.has_dirKey) @@ -1631,7 +1631,7 @@ export namespace request { message.controlType = reader.readEnum(); break; case 5: - reader.readMessage(message.button, () => message.button = TrainControl.EmergentButton.deserialize(reader)); + reader.readMessage(message.controlButton, () => message.controlButton = TrainControl.ControlButton.deserialize(reader)); break; case 6: reader.readMessage(message.driverKey, () => message.driverKey = TrainControl.DriverKeySwitch.deserialize(reader)); @@ -1666,6 +1666,73 @@ export namespace request { FORWARD = 1, NEUTRALWARD = 2 } + export class ControlButton extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + active?: boolean; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("active" in data && data.active != undefined) { + this.active = data.active; + } + } + } + get active() { + return pb_1.Message.getFieldWithDefault(this, 1, false) as boolean; + } + set active(value: boolean) { + pb_1.Message.setField(this, 1, value); + } + static fromObject(data: { + active?: boolean; + }): ControlButton { + const message = new ControlButton({}); + if (data.active != null) { + message.active = data.active; + } + return message; + } + toObject() { + const data: { + active?: boolean; + } = {}; + if (this.active != null) { + data.active = this.active; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.active != false) + writer.writeBool(1, this.active); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): ControlButton { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new ControlButton(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.active = reader.readBool(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): ControlButton { + return ControlButton.deserialize(bytes); + } + } export class EmergentButton extends pb_1.Message { #one_of_decls: number[][] = []; constructor(data?: any[] | { diff --git a/src/protos/tccGraphics.ts b/src/protos/tccGraphics.ts index db13d88..158c176 100644 --- a/src/protos/tccGraphics.ts +++ b/src/protos/tccGraphics.ts @@ -6,6 +6,11 @@ import * as dependency_1 from "./stationLayoutGraphics"; import * as pb_1 from "google-protobuf"; export namespace tccGraphicData { + export enum TccElementColor { + green = 0, + red = 1, + blue = 2 + } export class TccGraphicStorage extends pb_1.Message { #one_of_decls: number[][] = []; constructor(data?: any[] | { @@ -14,9 +19,10 @@ export namespace tccGraphicData { tccTexts?: TccText[]; tccKeys?: TccKey[]; tccHandles?: TccHandle[]; + tccLights?: TccLight[]; }) { super(); - pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 5], this.#one_of_decls); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 5, 6], this.#one_of_decls); if (!Array.isArray(data) && typeof data == "object") { if ("canvas" in data && data.canvas != undefined) { this.canvas = data.canvas; @@ -33,6 +39,9 @@ export namespace tccGraphicData { if ("tccHandles" in data && data.tccHandles != undefined) { this.tccHandles = data.tccHandles; } + if ("tccLights" in data && data.tccLights != undefined) { + this.tccLights = data.tccLights; + } } } get canvas() { @@ -68,12 +77,19 @@ export namespace tccGraphicData { set tccHandles(value: TccHandle[]) { pb_1.Message.setRepeatedWrapperField(this, 5, value); } + get tccLights() { + return pb_1.Message.getRepeatedWrapperField(this, TccLight, 6) as TccLight[]; + } + set tccLights(value: TccLight[]) { + pb_1.Message.setRepeatedWrapperField(this, 6, value); + } static fromObject(data: { canvas?: ReturnType; tccButtons?: ReturnType[]; tccTexts?: ReturnType[]; tccKeys?: ReturnType[]; tccHandles?: ReturnType[]; + tccLights?: ReturnType[]; }): TccGraphicStorage { const message = new TccGraphicStorage({}); if (data.canvas != null) { @@ -91,6 +107,9 @@ export namespace tccGraphicData { if (data.tccHandles != null) { message.tccHandles = data.tccHandles.map(item => TccHandle.fromObject(item)); } + if (data.tccLights != null) { + message.tccLights = data.tccLights.map(item => TccLight.fromObject(item)); + } return message; } toObject() { @@ -100,6 +119,7 @@ export namespace tccGraphicData { tccTexts?: ReturnType[]; tccKeys?: ReturnType[]; tccHandles?: ReturnType[]; + tccLights?: ReturnType[]; } = {}; if (this.canvas != null) { data.canvas = this.canvas.toObject(); @@ -116,6 +136,9 @@ export namespace tccGraphicData { if (this.tccHandles != null) { data.tccHandles = this.tccHandles.map((item: TccHandle) => item.toObject()); } + if (this.tccLights != null) { + data.tccLights = this.tccLights.map((item: TccLight) => item.toObject()); + } return data; } serialize(): Uint8Array; @@ -132,6 +155,8 @@ export namespace tccGraphicData { writer.writeRepeatedMessage(4, this.tccKeys, (item: TccKey) => item.serialize(writer)); if (this.tccHandles.length) writer.writeRepeatedMessage(5, this.tccHandles, (item: TccHandle) => item.serialize(writer)); + if (this.tccLights.length) + writer.writeRepeatedMessage(6, this.tccLights, (item: TccLight) => item.serialize(writer)); if (!w) return writer.getResultBuffer(); } @@ -156,6 +181,9 @@ export namespace tccGraphicData { case 5: reader.readMessage(message.tccHandles, () => pb_1.Message.addToRepeatedWrapperField(message, 5, TccHandle.deserialize(reader), TccHandle)); break; + case 6: + reader.readMessage(message.tccLights, () => pb_1.Message.addToRepeatedWrapperField(message, 6, TccLight.deserialize(reader), TccLight)); + break; default: reader.skipField(); } } @@ -661,4 +689,143 @@ export namespace tccGraphicData { return TccHandle.deserialize(bytes); } } + export class TccLight extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: dependency_1.graphicData.CommonInfo; + code?: string; + lightColor?: TccElementColor; + activeLevel?: boolean; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("lightColor" in data && data.lightColor != undefined) { + this.lightColor = data.lightColor; + } + if ("activeLevel" in data && data.activeLevel != undefined) { + this.activeLevel = data.activeLevel; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, dependency_1.graphicData.CommonInfo, 1) as dependency_1.graphicData.CommonInfo; + } + set common(value: dependency_1.graphicData.CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get lightColor() { + return pb_1.Message.getFieldWithDefault(this, 3, TccElementColor.green) as TccElementColor; + } + set lightColor(value: TccElementColor) { + pb_1.Message.setField(this, 3, value); + } + get activeLevel() { + return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean; + } + set activeLevel(value: boolean) { + pb_1.Message.setField(this, 4, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + lightColor?: TccElementColor; + activeLevel?: boolean; + }): TccLight { + const message = new TccLight({}); + if (data.common != null) { + message.common = dependency_1.graphicData.CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.lightColor != null) { + message.lightColor = data.lightColor; + } + if (data.activeLevel != null) { + message.activeLevel = data.activeLevel; + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + lightColor?: TccElementColor; + activeLevel?: boolean; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.lightColor != null) { + data.lightColor = this.lightColor; + } + if (this.activeLevel != null) { + data.activeLevel = this.activeLevel; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.lightColor != TccElementColor.green) + writer.writeEnum(3, this.lightColor); + if (this.activeLevel != false) + writer.writeBool(4, this.activeLevel); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): TccLight { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new TccLight(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = dependency_1.graphicData.CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + message.lightColor = reader.readEnum(); + break; + case 4: + message.activeLevel = reader.readBool(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): TccLight { + return TccLight.deserialize(bytes); + } + } } diff --git a/yarn.lock b/yarn.lock index 729435e..f3828fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2413,9 +2413,9 @@ isobject@^3.0.1: resolved "https://registry.npmmirror.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -"jl-graphic@git+http://120.46.212.6:3000/joylink/graphic-pixi.git#v0.1.11": - version "0.1.11" - resolved "git+http://120.46.212.6:3000/joylink/graphic-pixi.git#36f3f0257e6ff257782f82ba103b9152f6cf6521" +"jl-graphic@git+http://120.46.212.6:3000/joylink/graphic-pixi.git#v0.1.15": + version "0.1.14" + resolved "git+http://120.46.212.6:3000/joylink/graphic-pixi.git#8b0ad14f7324a5eaba58239645a1fa0452e87ab4" dependencies: "@pixi/graphics-extras" "^7.3.2" "@pixi/utils" "^7.3.2"