import Events , { EventName , preloadEvent } from "../../common/util/Events" ; import Res from "../../common/util/Res" ; import { ResUrl } from "../../constant/ResUrl" ; import State from "../data/State" ; import StateMachine from "../data/StateMachine" ; import Transition from "../data/Transition" ; import Line from "./Line" ; import NavBar from "./NavBar" ; import UnitBase from "./UnitBase" ; import UnitState from "./UnitState" ; import UnitStateMachine from "./UnitStateMachine" ; const { ccclass , property } = cc . _decorator ; /** 状态机视图界面边长 */ const LEN = 9000 ; @ ccclass export default class MachineLayer extends cc . Component { @ property ( cc . Node ) Grid : cc . Node = null ; @ property ( cc . Node ) UnitContent : cc . Node = null ; @ property ( cc . Node ) LineContent : cc . Node = null ; @ property ( NavBar ) NavBar : NavBar = null ; /** 默认状态，整个状态机运行的入口 */ private _defaultState : State = null ; public get defaultState ( ) { return this . _defaultState ; } public set defaultState ( v ) { this . _defaultState = v ; } /** 主状态机 */ private _mainStateMachine : StateMachine = null ; public get mainStateMachine ( ) { return this . _mainStateMachine ; } /** 当前视图显示的状态机 */ private _curStateMachine : StateMachine = null ; public get curStateMachine ( ) { return this . _curStateMachine ; } /** AnyState节点 */ private _anyState : UnitState = null ; public get anyState ( ) { return this . _anyState ; } /** 父状态机节点 */ private _upUnit : UnitStateMachine = null ; protected onLoad ( ) { this . node . setContentSize ( LEN , LEN ) ; this . Grid . setContentSize ( LEN , LEN ) ; this . _mainStateMachine = new StateMachine ( null ) ; this . _curStateMachine = this . _mainStateMachine ; this . _anyState = this . createState ( cc . v2 ( - 300 , 300 ) , true ) ; this . _curStateMachine . setAnyStatePos ( this . _anyState . node . position ) ; this . NavBar . refreshBar ( [ this . _mainStateMachine ] ) ; Events . targetOn ( this ) ; } protected onDestroy ( ) { this . clear ( ) ; Events . targetOff ( this ) ; } /**
     * 更新面包屑导航栏的显示
     */ private refreshNavBar ( curStateMachine ) { let arr = [ curStateMachine ] ; while ( curStateMachine . upStateMachine ) { arr . unshift ( curStateMachine . upStateMachine ) ; curStateMachine = curStateMachine . upStateMachine ; } this . NavBar . refreshBar ( arr ) ; } /**
     * 清空状态机数据
     */ public clear ( ) { this . _mainStateMachine . destroy ( ) ; } /**
     * 改变当前视图显示的状态机，不传参则刷新当前视图
     */ public setCurStateMachine ( stateMachine = null ) { if ( this . _curStateMachine === stateMachine ) { return ; } if ( stateMachine === null ) { stateMachine = this . _curStateMachine ; } this . _curStateMachine = stateMachine ; this . refreshNavBar ( stateMachine ) ; if ( ! stateMachine . upStateMachine ) { if ( this . _upUnit ) { this . _upUnit . node . removeFromParent ( ) ; this . _upUnit . node . destroy ( ) ; this . _upUnit = null ; } } else { if ( ! this . _upUnit ) { let node = cc . instantiate ( Res . getLoaded ( ResUrl . PREFAB . STATE_MACHINE_NODE ) ) ; this . UnitContent . addChild ( node ) ; let unitStateMachine = node . getComponent ( UnitStateMachine ) ; this . _upUnit = unitStateMachine ; } this . _upUnit . initByStateMachine ( stateMachine . upStateMachine , stateMachine . upStateMachinePos ) ; this . _upUnit . isDefault = stateMachine . upStateMachine . has ( this . _defaultState , false ) ; } this . _anyState . setPos ( stateMachine . anyStatePos ) ; this . node . position = stateMachine . layerPos ; this . node . scale = stateMachine . layerScale ; this . LineContent . destroyAllChildren ( ) ; this . LineContent . removeAllChildren ( ) ; for ( let i = this . UnitContent . childrenCount - 1 ; i >= 0 ; i -- ) { let node = this . UnitContent . children [ i ] ; let unit = node . getComponent ( UnitBase ) ; if ( unit === this . _anyState || unit === this . _upUnit ) { continue ; } node . removeFromParent ( ) ; node . destroy ( ) ; } let stateMap = new Map ( ) ; let machineMap = new Map ( ) ; this . _upUnit && machineMap . set ( stateMachine . upStateMachine , this . _upUnit ) ; stateMachine . subStates . forEach ( ( e ) => { let node = cc . instantiate ( Res . getLoaded ( ResUrl . PREFAB . STATE_NODE ) ) ; this . UnitContent . addChild ( node ) ; let unitState = node . getComponent ( UnitState ) ; unitState . initByState ( e ) ; unitState . isDefault = e === this . _defaultState ; stateMap . set ( e , unitState ) ; } ) ; stateMachine . subStateMachines . forEach ( ( e ) => { let node = cc . instantiate ( Res . getLoaded ( ResUrl . PREFAB . STATE_MACHINE_NODE ) ) ; this . UnitContent . addChild ( node ) ; let unitStateMachine = node . getComponent ( UnitStateMachine ) ; unitStateMachine . initByStateMachine ( e ) ; unitStateMachine . isDefault = e . has ( this . _defaultState ) ; if ( machineMap . size >= 1 ) { machineMap . forEach ( ( v , k ) => { if ( k . getTransitions ( e ) . length > 0 ) { let line = this . createLine ( ) ; line . onInit ( v , unitStateMachine ) ; } if ( e . getTransitions ( k ) . length > 0 ) { let line = this . createLine ( ) ; line . onInit ( unitStateMachine , v ) ; } } ) ; } machineMap . set ( e , unitStateMachine ) ; } ) ; let stateKeys = stateMap . keys ( ) ; for ( let i = 0 ; i < stateMap . size ; i ++ ) { let state = stateKeys . next ( ) . value ; let fromUnit = stateMap . get ( state ) ; let toUnitSet = new Set ( ) ; let transitions = state . getTransitions ( ) ; transitions . forEach ( ( t ) => { let toUnit = stateMap . get ( t . toState ) ; if ( ! toUnit ) { if ( stateMachine . has ( t . toState ) ) { let machineKeys = machineMap . keys ( ) ; for ( let j = 0 ; j < machineMap . size ; j ++ ) { let machine = machineKeys . next ( ) . value ; if ( machine !== stateMachine . upStateMachine && machine . has ( t . toState ) ) { toUnit = machineMap . get ( machine ) ; break ; } } } else { toUnit = this . _upUnit ; } if ( ! toUnit ) { cc . error ( `[MachineLayer.setCurStateMachine] error transition: ${ t }` ) ; return ; } } if ( ! toUnitSet . has ( toUnit ) ) { toUnitSet . add ( toUnit ) ; let line = this . createLine ( ) ; line . onInit ( fromUnit , toUnit ) ; } } ) ; if ( this . _anyState . state . getTransitions ( state ) . length > 0 ) { let line = this . createLine ( ) ; line . onInit ( this . _anyState , fromUnit ) ; } let machineKeys = machineMap . keys ( ) ; for ( let j = 0 ; j < machineMap . size ; j ++ ) { let machine = machineKeys . next ( ) . value ; if ( machine . getTransitions ( state ) . length > 0 ) { let line = this . createLine ( ) ; line . onInit ( machineMap . get ( machine ) , fromUnit ) ; } } } } /**
     * 新建状态机节点
     */ public createStateMachine ( pos ) { let node = cc . instantiate ( Res . getLoaded ( ResUrl . PREFAB . STATE_MACHINE_NODE ) ) ; this . UnitContent . addChild ( node ) ; let unitStateMachine = node . getComponent ( UnitStateMachine ) ; unitStateMachine . onInit ( this . _curStateMachine ) ; unitStateMachine . setPos ( pos ) ; return unitStateMachine ; } /**
     * 新建状态节点
     */ public createState ( pos , isAnyState = false ) { let node = cc . instantiate ( Res . getLoaded ( ResUrl . PREFAB . STATE_NODE ) ) ; this . UnitContent . addChild ( node ) ; let unitState = node . getComponent ( UnitState ) ; unitState . onInit ( this . _curStateMachine , isAnyState ) ; unitState . setPos ( pos ) ; if ( State . getStateNum ( ) === 1 ) { this . setDefaultState ( unitState ) ; } return unitState ; } public createLine ( ) { let node = cc . instantiate ( Res . getLoaded ( ResUrl . PREFAB . LINE ) ) ; this . LineContent . addChild ( node ) ; return node . getComponent ( Line ) ; } /**
     * 删除子状态机
     */ public deleteStateMachine ( unitStateMachine ) { for ( let i = this . LineContent . childrenCount - 1 ; i >= 0 ; i -- ) { let line = this . LineContent . children [ i ] . getComponent ( Line ) ; if ( line . relatedState ( unitStateMachine ) ) { this . deleteLine ( line ) ; } } this . _curStateMachine . delete ( unitStateMachine . stateMachine ) ; unitStateMachine . node . removeFromParent ( ) ; unitStateMachine . node . destroy ( ) ; if ( unitStateMachine . isDefault ) { this . setDefaultState ( ) ; } } /**
     * 删除状态
     */ public deleteState ( unitState ) { for ( let i = this . LineContent . childrenCount - 1 ; i >= 0 ; i -- ) { let line = this . LineContent . children [ i ] . getComponent ( Line ) ; if ( line . relatedState ( unitState ) ) { this . deleteLine ( line ) ; } } this . _curStateMachine . delete ( unitState . state ) ; unitState . node . removeFromParent ( ) ; unitState . node . destroy ( ) ; if ( unitState . isDefault ) { this . setDefaultState ( ) ; } } /**
     * 删除连线
     */ public deleteLine ( line ) { line . getTransitions ( ) . forEach ( ( e ) => { e . fromState . deleteTransition ( e ) ; } ) ; line . node . removeFromParent ( ) ; line . node . destroy ( ) ; } /**
     * 根据Layer层坐标获取点击到的unit
     */ public getUnitByPos ( pos ) { for ( let i = this . UnitContent . childrenCount - 1 ; i >= 0 ; i -- ) { let node = this . UnitContent . children [ i ] ; let rect = node . getBoundingBox ( ) ; if ( rect . contains ( pos ) ) { return node . getComponent ( UnitBase ) ; } } return null ; } /**
     * 根据Layer层坐标获取点击到的line
     */ public getLineByPos ( pos ) { for ( let i = this . LineContent . childrenCount - 1 ; i >= 0 ; i -- ) { let node = this . LineContent . children [ i ] ; let line = node . getComponent ( Line ) ; if ( line . contains ( pos ) ) { return line ; } } return null ; } /**
     * 根据连线两端节点获取line
     */ public getLineByUnit ( from , to ) { for ( let i = this . LineContent . childrenCount - 1 ; i >= 0 ; i -- ) { let node = this . LineContent . children [ i ] ; let line = node . getComponent ( Line ) ; if ( line . fromUnit === from && line . toUnit === to ) { return line ; } } return null ; } param moveUnit public checkMoveUnit ( moveUnit ) { if ( moveUnit === this . _anyState || moveUnit === this . _upUnit ) { return null ; } for ( let i = this . UnitContent . childrenCount - 1 ; i >= 0 ; i -- ) { let node = this . UnitContent . children [ i ] ; let unit = node . getComponent ( UnitStateMachine ) ; if ( ! unit || unit === moveUnit ) { continue ; } let rect = node . getBoundingBox ( ) ; if ( rect . contains ( moveUnit . node . position ) ) { return unit ; } } return null ; } param moveUnit returns public moveIntoStateMachine ( moveUnit ) { let unit = this . checkMoveUnit ( moveUnit ) ; if ( ! unit ) { return false ; } let needRefresh = false ; if ( moveUnit instanceof UnitState ) { needRefresh = unit . stateMachine . moveTargetIn ( moveUnit . state ) ; } else if ( moveUnit instanceof UnitStateMachine ) { needRefresh = unit . stateMachine . moveTargetIn ( moveUnit . stateMachine ) ; } if ( ! needRefresh ) { return false ; } this . setCurStateMachine ( ) ; return true ; } param unitState public setDefaultState ( unitState = null ) { if ( ! unitState ) { if ( this . _curStateMachine . subStates . size === 0 ) { this . _defaultState = State . getRandState ( ) ; if ( ! this . _defaultState ) { return ; } for ( let i = this . UnitContent . childrenCount - 1 ; i >= 0 ; i -- ) { let node = this . UnitContent . children [ i ] ; let v = node . getComponent ( UnitStateMachine ) ; if ( v ) { v . isDefault = v . stateMachine . has ( this . _defaultState ) ; break ; } } } else { for ( let i = this . UnitContent . childrenCount - 1 ; i >= 0 ; i -- ) { let node = this . UnitContent . children [ i ] ; let v = node . getComponent ( UnitState ) ; if ( v && ! v . isAnyState ) { v . isDefault = true ; this . _defaultState = v . state ; break ; } } } } else { if ( unitState . state === this . _defaultState || unitState . isAnyState ) { return ; } this . UnitContent . children . forEach ( ( e ) => { let v = e . getComponent ( UnitBase ) ; if ( v === this . _anyState ) { return ; } if ( v === unitState ) { v . isDefault = true ; this . _defaultState = unitState . state ; } else { v . isDefault = false ; } } ) ; } } param pos public setPos ( pos ) { let rect = this . node . getBoundingBox ( ) ; let x = cc . misc . clampf ( pos . x , - this . node . parent . width / 2 + rect . width / 2 , this . node . parent . width / 2 - rect . width / 2 ) ; let y = cc . misc . clampf ( pos . y , - this . node . parent . height / 2 + rect . height / 2 , this . node . parent . height / 2 - rect . height / 2 ) ; this . node . x = x ; this . node . y = y ; this . _curStateMachine . setLayerPos ( x , y ) ; } param value param worldPos public changeScale ( value , worldPos ) { let localPos1 = this . node . convertToNodeSpaceAR ( worldPos ) ; this . node . scale = cc . misc . clampf ( value ? this . node . scale + 0.1 : this . node . scale - 0.1 , 0.3 , 3 ) ; let localPos2 = this . node . convertToNodeSpaceAR ( worldPos ) ; let delta = localPos2 . sub ( localPos1 ) . mul ( this . node . scale ) ; this . setPos ( this . node . position . add ( delta ) ) ; this . _curStateMachine . setLayerScale ( this . node . scale ) ; } @ preloadEvent ( EventName . ANY_STATE_MOVE ) private onEventAnyStateMove ( pos ) { this . _curStateMachine . setAnyStatePos ( pos ) ; } @ preloadEvent ( EventName . UP_STATE_MACHINE_MOVE ) private onEventUpStateMachineMove ( pos ) { this . _curStateMachine . setUpStateMachinePos ( pos ) ; } }