|
|
@ -3,8 +3,8 @@ import {CSG} from 'three-csg-ts' |
|
|
import gsap from 'gsap' |
|
|
import gsap from 'gsap' |
|
|
import mqtt from 'mqtt' |
|
|
import mqtt from 'mqtt' |
|
|
import {Euler} from 'three/src/math/Euler' |
|
|
import {Euler} from 'three/src/math/Euler' |
|
|
import Cl2Entity from '@/modules/cl2/Cl2Entity' |
|
|
import Cl2Entity from '@/modules/amr/ptr/cl2/Cl2Entity' |
|
|
import Cl23DGraphics from "@/modules/cl2/Cl23DGraphics" |
|
|
import Cl23DGraphics from "@/modules/amr/ptr/cl2/Cl23DGraphics" |
|
|
import { |
|
|
import { |
|
|
AmrErrorCode, |
|
|
AmrErrorCode, |
|
|
AmrMsg, |
|
|
AmrMsg, |
|
|
@ -20,8 +20,8 @@ import { |
|
|
AmrMsg20150, |
|
|
AmrMsg20150, |
|
|
AmrMsg20250, |
|
|
AmrMsg20250, |
|
|
CurBatteryData, |
|
|
CurBatteryData, |
|
|
type CEventId, type COperationType, type CTaskMode, |
|
|
type CEventId, type COperationType, type CTaskMode, type CPickMode, |
|
|
type LogicDirection, TaskCompletedData, TaskModeChangeData, TaskStatusChangeData, TaskTypeChangeData |
|
|
type LogicDirection, TaskCompletedData, TaskModeChangeData, TaskStatusChangeData, TaskTypeChangeData, AmrMsg20010 |
|
|
} from "@/core/manager/amr/AmrMessageDefine"; |
|
|
} from "@/core/manager/amr/AmrMessageDefine"; |
|
|
import {worldModel} from "@/core/manager/WorldModel"; |
|
|
import {worldModel} from "@/core/manager/WorldModel"; |
|
|
|
|
|
|
|
|
@ -64,6 +64,7 @@ export default class Cl23dObject extends THREE.Object3D { |
|
|
private __TaskMode: CTaskMode = 0 |
|
|
private __TaskMode: CTaskMode = 0 |
|
|
private __OperationType: COperationType = 0 |
|
|
private __OperationType: COperationType = 0 |
|
|
private __TaskStatus: CEventId = 0 |
|
|
private __TaskStatus: CEventId = 0 |
|
|
|
|
|
private __PickMode: CPickMode = 0 |
|
|
|
|
|
|
|
|
get TaskMode(): CTaskMode { |
|
|
get TaskMode(): CTaskMode { |
|
|
return this.__TaskMode |
|
|
return this.__TaskMode |
|
|
@ -125,6 +126,15 @@ export default class Cl23dObject extends THREE.Object3D { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
get PickMode(): CPickMode { |
|
|
|
|
|
return this.__PickMode |
|
|
|
|
|
} |
|
|
|
|
|
set PickMode(value: CPickMode) { |
|
|
|
|
|
if (this.__PickMode !== value) { |
|
|
|
|
|
this.__PickMode = value |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
private bootTime: number = 0 |
|
|
private bootTime: number = 0 |
|
|
|
|
|
|
|
|
// 心跳间隔 UInt32 单位: s
|
|
|
// 心跳间隔 UInt32 单位: s
|
|
|
@ -180,6 +190,10 @@ export default class Cl23dObject extends THREE.Object3D { |
|
|
|
|
|
|
|
|
this.vehicleId = parseInt(this.cl2Entity.id) |
|
|
this.vehicleId = parseInt(this.cl2Entity.id) |
|
|
this.cl2Entity.viewport.addFrameTimerCallback(this.cl2Entity.id, this.onFrameTimer.bind(this)) |
|
|
this.cl2Entity.viewport.addFrameTimerCallback(this.cl2Entity.id, this.onFrameTimer.bind(this)) |
|
|
|
|
|
if (!worldModel.state.runState.isVirtual) { |
|
|
|
|
|
this.subscribeMessage('/wcs_server/' + this.cl2Entity.id) |
|
|
|
|
|
this.subscribeMessage('/agv_robot/status') |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private AGVModel = "CYBER-LIFT-A_V1.0" |
|
|
private AGVModel = "CYBER-LIFT-A_V1.0" |
|
|
@ -216,28 +230,30 @@ export default class Cl23dObject extends THREE.Object3D { |
|
|
this.bootTime = Date.now(); |
|
|
this.bootTime = Date.now(); |
|
|
this.computeLogicXYAndDirection(); |
|
|
this.computeLogicXYAndDirection(); |
|
|
|
|
|
|
|
|
if (worldModel.state.runState.isVirtual) { |
|
|
if (!worldModel.state.runState.isVirtual) { |
|
|
this.subscribeMessage('/wcs_server/' + this.cl2Entity.id) |
|
|
return |
|
|
this.send20147() |
|
|
} |
|
|
|
|
|
this.subscribeMessage('/wcs_server/' + this.cl2Entity.id) |
|
|
|
|
|
this.send20147() |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
this.send20149() |
|
|
|
|
|
this.TaskMode = 1 |
|
|
|
|
|
// 检查当前所在位置和方向 根据车当前所在的xz坐标获取地标
|
|
|
setTimeout(() => { |
|
|
setTimeout(() => { |
|
|
this.send20149() |
|
|
this.sendCurrentPositionAndDirection() |
|
|
this.TaskMode = 1 |
|
|
|
|
|
// 检查当前所在位置和方向 根据车当前所在的xz坐标获取地标
|
|
|
|
|
|
setTimeout(() => { |
|
|
setTimeout(() => { |
|
|
this.sendCurrentPositionAndDirection() |
|
|
this.send20150() |
|
|
setTimeout(() => { |
|
|
|
|
|
this.send20150() |
|
|
|
|
|
}, 1000) |
|
|
|
|
|
}, 1000) |
|
|
}, 1000) |
|
|
}, 2000) |
|
|
}, 1000) |
|
|
} else { |
|
|
}, 2000) |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 关机
|
|
|
// 关机
|
|
|
shutdown() { |
|
|
shutdown() { |
|
|
|
|
|
if (!worldModel.state.runState.isVirtual) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
const content = new AmrMsg20148(this.vehicleId) |
|
|
const content = new AmrMsg20148(this.vehicleId) |
|
|
// 电量
|
|
|
// 电量
|
|
|
content.Battery = 100 |
|
|
content.Battery = 100 |
|
|
@ -310,6 +326,29 @@ export default class Cl23dObject extends THREE.Object3D { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
send20010() { |
|
|
|
|
|
const content: AmrMsg20010 = new AmrMsg20010(this.vehicleId) |
|
|
|
|
|
content.CurX = this.currentLogicX |
|
|
|
|
|
content.CurY = this.currentLogicY |
|
|
|
|
|
content.CurDirection = this.currentDirection |
|
|
|
|
|
content.OperationType = this.OperationType |
|
|
|
|
|
content.Battery = this.Battery |
|
|
|
|
|
content.OperationResult = 0 |
|
|
|
|
|
content.Summary = { |
|
|
|
|
|
ActuatorsData: [ |
|
|
|
|
|
{ |
|
|
|
|
|
MechNo: 1, |
|
|
|
|
|
Name: "Mech1", |
|
|
|
|
|
PickMode: this.PickMode |
|
|
|
|
|
} |
|
|
|
|
|
] |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const m20010 = new AmrMsg<AmrMsg20010>(content) |
|
|
|
|
|
this.sendMessage(m20010) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
send20011(content: AmrMsg20011<any>) { |
|
|
send20011(content: AmrMsg20011<any>) { |
|
|
const m20011 = new AmrMsg<AmrMsg20011<any>>(content) |
|
|
const m20011 = new AmrMsg<AmrMsg20011<any>>(content) |
|
|
this.sendMessage(m20011) |
|
|
this.sendMessage(m20011) |
|
|
@ -340,10 +379,13 @@ export default class Cl23dObject extends THREE.Object3D { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
subscribeMessage(topic: string) { |
|
|
subscribeMessage(topic: string) { |
|
|
this.cl2Entity.viewport.envManager.client.subscribe(topic, {qos: 0}) |
|
|
worldModel.envManager.client.subscribe(topic, {qos: 0}) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
sendMessage(msg: AmrMsg<any>) { |
|
|
sendMessage(msg: AmrMsg<any>) { |
|
|
|
|
|
if (!worldModel.state.runState.isVirtual) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
console.log('send message:', JSON.stringify(msg)) |
|
|
console.log('send message:', JSON.stringify(msg)) |
|
|
if (this.sendMessageQueue.indexOf(msg) < 0) { |
|
|
if (this.sendMessageQueue.indexOf(msg) < 0) { |
|
|
this.sendMessageQueue.push(msg) |
|
|
this.sendMessageQueue.push(msg) |
|
|
@ -351,26 +393,31 @@ export default class Cl23dObject extends THREE.Object3D { |
|
|
if (this.sendMessageQueue.length <= 0) { |
|
|
if (this.sendMessageQueue.length <= 0) { |
|
|
this.mqRetryTimeCount = 0 |
|
|
this.mqRetryTimeCount = 0 |
|
|
} |
|
|
} |
|
|
this.cl2Entity.viewport.envManager.client.publish('/agv_robot/status', JSON.stringify(msg)) |
|
|
worldModel.envManager.client.publish('/agv_robot/status', JSON.stringify(msg)) |
|
|
this.heartBeatTimeCount = 0 |
|
|
this.heartBeatTimeCount = 0 |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
sendHeartBeat() { |
|
|
sendHeartBeat() { |
|
|
|
|
|
if (!worldModel.state.runState.isVirtual) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
const content = new AmrMsg20100(this.vehicleId) |
|
|
const content = new AmrMsg20100(this.vehicleId) |
|
|
content.Temperature = {Battery: this.Battery} |
|
|
content.Temperature = {Battery: this.Battery} |
|
|
const m20100 = new AmrMsg<AmrMsg20100>(content) |
|
|
const m20100 = new AmrMsg<AmrMsg20100>(content) |
|
|
this.cl2Entity.viewport.envManager.client.publish('/agv_robot/status', JSON.stringify(m20100)) |
|
|
worldModel.envManager.client.publish('/agv_robot/status', JSON.stringify(m20100)) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
sendAck(seqNo: number, vehicleId: number) { |
|
|
sendAck(seqNo: number, vehicleId: number) { |
|
|
|
|
|
if (!worldModel.state.runState.isVirtual) { |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
const msg20050 = new AmrMsg20050(seqNo, vehicleId) |
|
|
const msg20050 = new AmrMsg20050(seqNo, vehicleId) |
|
|
const ack = new AmrMsg<AmrMsg20050>(msg20050) |
|
|
const ack = new AmrMsg<AmrMsg20050>(msg20050) |
|
|
this.heartBeatTimeCount = 0 |
|
|
this.heartBeatTimeCount = 0 |
|
|
this.cl2Entity.viewport.envManager.client.publish('/agv_robot/status', JSON.stringify(ack)) |
|
|
worldModel.envManager.client.publish('/agv_robot/status', JSON.stringify(ack)) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/*==========消息处理============*/ |
|
|
/*==========RCS消息处理============*/ |
|
|
|
|
|
|
|
|
// 处理任务
|
|
|
// 处理任务
|
|
|
handle10010Message(data: AmrMsg10010) { |
|
|
handle10010Message(data: AmrMsg10010) { |
|
|
if (this.currentStepTaskList.length > 0) { |
|
|
if (this.currentStepTaskList.length > 0) { |
|
|
@ -410,6 +457,8 @@ export default class Cl23dObject extends THREE.Object3D { |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*==========真车消息处理============*/ |
|
|
|
|
|
|
|
|
// 计算逻辑方向
|
|
|
// 计算逻辑方向
|
|
|
computeLogicXYAndDirection() { |
|
|
computeLogicXYAndDirection() { |
|
|
let ra = this.rotation.y |
|
|
let ra = this.rotation.y |
|
|
@ -610,7 +659,7 @@ export default class Cl23dObject extends THREE.Object3D { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
executeTask() { |
|
|
executeTask() { |
|
|
|
|
|
this.TaskMode = 2 |
|
|
while (this.currentStepTaskList.length > 0) { |
|
|
while (this.currentStepTaskList.length > 0) { |
|
|
const stepTask = this.currentStepTaskList[0] |
|
|
const stepTask = this.currentStepTaskList[0] |
|
|
if (this.runningStepTask) { |
|
|
if (this.runningStepTask) { |
|
|
@ -635,75 +684,29 @@ export default class Cl23dObject extends THREE.Object3D { |
|
|
} else if (stepTask.StepTaskType == "ROTATION") { |
|
|
} else if (stepTask.StepTaskType == "ROTATION") { |
|
|
this.addRotation(stepTask.EndDirection) |
|
|
this.addRotation(stepTask.EndDirection) |
|
|
} else if (stepTask.StepTaskType == "LOAD") { |
|
|
} else if (stepTask.StepTaskType == "LOAD") { |
|
|
// this.add
|
|
|
this.addLoad(stepTask.GoodsSlotHeight/1000) |
|
|
} else if (stepTask.StepTaskType == "UNLOAD") { |
|
|
} else if (stepTask.StepTaskType == "UNLOAD") { |
|
|
// this.add
|
|
|
this.addUnload(stepTask.GoodsSlotHeight/1000) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
onActionCompleted() { |
|
|
/*==========动画处理============*/ |
|
|
this.runningStepTaskList = [] |
|
|
|
|
|
this.runningStepTask = null |
|
|
animationShowFork(z: number): Promise<void> { |
|
|
this.computeLogicXYAndDirection() |
|
|
|
|
|
// 当前所有动作执行完毕
|
|
|
const ptrPillar = this.getObjectByName('ptrPillar') |
|
|
if (this.currentStepTaskList.length <= 0) { |
|
|
const time = 3 |
|
|
this.send20010() |
|
|
return new Promise(resolve => { |
|
|
} |
|
|
gsap.to(ptrPillar.position, { |
|
|
this.PickMode = 0 |
|
|
z: -z, |
|
|
this.OperationType = 0 |
|
|
duration: time, |
|
|
this.TaskMode = 0 |
|
|
repeat: 0, |
|
|
this.executeTask() |
|
|
ease: 'sine.inOut', |
|
|
|
|
|
onComplete: resolve |
|
|
|
|
|
}) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
animationHideFork(): Promise<void> { |
|
|
|
|
|
return this.animationShowFork(0) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
animationUpFork(y: number, time?: number = 3): Promise<void> { |
|
|
|
|
|
const ptrFork = this.getObjectByName('ptrFork') |
|
|
|
|
|
const ptrPillar = this.getObjectByName('ptrPillar') |
|
|
|
|
|
const pz = ptrPillar.position.z |
|
|
|
|
|
return new Promise(resolve => { |
|
|
|
|
|
const bh = 0.22 |
|
|
|
|
|
const children = ptrFork.children |
|
|
|
|
|
|
|
|
|
|
|
gsap.to(ptrFork.position, { |
|
|
|
|
|
y: y, |
|
|
|
|
|
duration: time, |
|
|
|
|
|
repeat: 0, |
|
|
|
|
|
ease: 'sine.inOut', |
|
|
|
|
|
onComplete: resolve, |
|
|
|
|
|
onUpdate: function () { |
|
|
|
|
|
const a = this.targets()[0] |
|
|
|
|
|
if (a.y < bh) { |
|
|
|
|
|
if (pz > -1) { |
|
|
|
|
|
for (let i = 0; i < children.length; i++) { |
|
|
|
|
|
const child = children[i] |
|
|
|
|
|
child.position.y = bh - a.y |
|
|
|
|
|
} |
|
|
|
|
|
} else if (a.y < 0) { |
|
|
|
|
|
for (let i = 0; i < children.length; i++) { |
|
|
|
|
|
const child = children[i] |
|
|
|
|
|
child.position.y = 0 - a.y |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
animationDownFork(): Promise<void> { |
|
|
|
|
|
return this.animationUpFork(0) |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/*==========动画处理============*/ |
|
|
|
|
|
|
|
|
// 转
|
|
|
// 转
|
|
|
addRotation(direction: number): Promise<void> { |
|
|
addRotation(direction: number): Promise<void> { |
|
|
@ -737,8 +740,7 @@ export default class Cl23dObject extends THREE.Object3D { |
|
|
ease: 'none', |
|
|
ease: 'none', |
|
|
onComplete: ()=>{ |
|
|
onComplete: ()=>{ |
|
|
resolve() |
|
|
resolve() |
|
|
this.runningStepTaskList = [] |
|
|
this.onActionCompleted() |
|
|
this.runningStepTask = null |
|
|
|
|
|
} |
|
|
} |
|
|
}) |
|
|
}) |
|
|
}) |
|
|
}) |
|
|
@ -746,7 +748,8 @@ export default class Cl23dObject extends THREE.Object3D { |
|
|
|
|
|
|
|
|
// 走
|
|
|
// 走
|
|
|
addTravel(logicX: number, logicY: number, speed: number = 1): Promise<void> { |
|
|
addTravel(logicX: number, logicY: number, speed: number = 1): Promise<void> { |
|
|
|
|
|
this.OperationType = 0 |
|
|
|
|
|
this.PickMode = 0 |
|
|
const pos = Model.getPositionByLogicXY(logicX, logicY) |
|
|
const pos = Model.getPositionByLogicXY(logicX, logicY) |
|
|
|
|
|
|
|
|
const fromPos = this.position |
|
|
const fromPos = this.position |
|
|
@ -769,9 +772,7 @@ export default class Cl23dObject extends THREE.Object3D { |
|
|
onComplete: () => { |
|
|
onComplete: () => { |
|
|
this.travelAnimation = null |
|
|
this.travelAnimation = null |
|
|
resolve() |
|
|
resolve() |
|
|
this.runningStepTaskList = [] |
|
|
this.onActionCompleted() |
|
|
this.runningStepTask = null |
|
|
|
|
|
this.computeLogicXYAndDirection() |
|
|
|
|
|
}, |
|
|
}, |
|
|
onUpdate: () => { |
|
|
onUpdate: () => { |
|
|
|
|
|
|
|
|
@ -807,10 +808,96 @@ export default class Cl23dObject extends THREE.Object3D { |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// fn = _.debounce((cl2: Cl2Entity) => {
|
|
|
// 取货
|
|
|
// cl2.taskStartRun()
|
|
|
addLoad(height: number): void { |
|
|
// }, 2000)
|
|
|
this.PickMode = 1 |
|
|
|
|
|
this.OperationType = 4 |
|
|
|
|
|
this.animationUpFork(height).then( |
|
|
|
|
|
() => this.animationShowFork(1.4).then( |
|
|
|
|
|
()=>this.animationUpFork(height + 0.2).then( |
|
|
|
|
|
()=>this.animationHideFork().then( |
|
|
|
|
|
()=>this.animationDownFork().then(()=>{ |
|
|
|
|
|
this.onActionCompleted() |
|
|
|
|
|
}) |
|
|
|
|
|
) |
|
|
|
|
|
) |
|
|
|
|
|
) |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
|
|
|
// 卸货
|
|
|
|
|
|
addUnload(height: number): void { |
|
|
|
|
|
this.PickMode = 2 |
|
|
|
|
|
this.OperationType = 4 |
|
|
|
|
|
this.animationUpFork(height + 0.2).then( |
|
|
|
|
|
() => this.animationShowFork(1.4).then( |
|
|
|
|
|
()=>this.animationUpFork(height).then( |
|
|
|
|
|
()=>this.animationHideFork().then( |
|
|
|
|
|
()=>this.animationDownFork().then(()=>{ |
|
|
|
|
|
this.onActionCompleted() |
|
|
|
|
|
}) |
|
|
|
|
|
) |
|
|
|
|
|
) |
|
|
|
|
|
) |
|
|
|
|
|
) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
animationShowFork(z: number): Promise<void> { |
|
|
|
|
|
|
|
|
|
|
|
const ptrPillar = this.getObjectByName('ptrPillar') |
|
|
|
|
|
const time = 3 |
|
|
|
|
|
return new Promise(resolve => { |
|
|
|
|
|
gsap.to(ptrPillar.position, { |
|
|
|
|
|
z: -z, |
|
|
|
|
|
duration: time, |
|
|
|
|
|
repeat: 0, |
|
|
|
|
|
ease: 'sine.inOut', |
|
|
|
|
|
onComplete: resolve |
|
|
|
|
|
}) |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
animationHideFork(): Promise<void> { |
|
|
|
|
|
return this.animationShowFork(0) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
animationUpFork(y: number, time?: number = 3): Promise<void> { |
|
|
|
|
|
const ptrFork = this.getObjectByName('ptrFork') |
|
|
|
|
|
const ptrPillar = this.getObjectByName('ptrPillar') |
|
|
|
|
|
const pz = ptrPillar.position.z |
|
|
|
|
|
return new Promise(resolve => { |
|
|
|
|
|
const bh = 0.22 |
|
|
|
|
|
const children = ptrFork.children |
|
|
|
|
|
|
|
|
|
|
|
gsap.to(ptrFork.position, { |
|
|
|
|
|
y: y, |
|
|
|
|
|
duration: time, |
|
|
|
|
|
repeat: 0, |
|
|
|
|
|
ease: 'sine.inOut', |
|
|
|
|
|
onComplete: resolve, |
|
|
|
|
|
onUpdate: function () { |
|
|
|
|
|
const a = this.targets()[0] |
|
|
|
|
|
if (a.y < bh) { |
|
|
|
|
|
if (pz > -1) { |
|
|
|
|
|
for (let i = 0; i < children.length; i++) { |
|
|
|
|
|
const child = children[i] |
|
|
|
|
|
child.position.y = bh - a.y |
|
|
|
|
|
} |
|
|
|
|
|
} else if (a.y < 0) { |
|
|
|
|
|
for (let i = 0; i < children.length; i++) { |
|
|
|
|
|
const child = children[i] |
|
|
|
|
|
child.position.y = 0 - a.y |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
animationDownFork(): Promise<void> { |
|
|
|
|
|
return this.animationUpFork(0) |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|