init
This commit is contained in:
64
animator-editor/assets/script/editor/fsm/BarItem.ts
Normal file
64
animator-editor/assets/script/editor/fsm/BarItem.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import Events, { EventName, preloadEvent } from "../../common/util/Events";
|
||||
import { RecycleNode } from "../../common/util/RecyclePool";
|
||||
import StateMachine from "../data/StateMachine";
|
||||
|
||||
const { ccclass, property } = cc._decorator;
|
||||
|
||||
@ccclass
|
||||
export default class BarItem extends cc.Component implements RecycleNode {
|
||||
@property(cc.Node) BgNode: cc.Node = null;
|
||||
@property(cc.Label) NameLabel: cc.Label = null;
|
||||
@property(cc.SpriteFrame) BgFrames: cc.SpriteFrame[] = [];
|
||||
|
||||
private _stateMachine: StateMachine = null;
|
||||
private _needUpdate: boolean = false;
|
||||
|
||||
public reuse() {
|
||||
}
|
||||
|
||||
public unuse() {
|
||||
Events.targetOff(this);
|
||||
}
|
||||
|
||||
public onInit(stateMachine: StateMachine, isCur: boolean) {
|
||||
this._stateMachine = stateMachine;
|
||||
this._needUpdate = true;
|
||||
this.BgNode.getComponent(cc.Sprite).spriteFrame = this._stateMachine.isMain ? this.BgFrames[0] : this.BgFrames[1];
|
||||
this.NameLabel.string = stateMachine.name;
|
||||
this.getComponent(cc.Button).interactable = !isCur;
|
||||
|
||||
this.NameLabel.node.on(cc.Node.EventType.SIZE_CHANGED, this.onLabSizeChanged, this);
|
||||
Events.targetOn(this);
|
||||
}
|
||||
|
||||
protected onDestroy() {
|
||||
Events.targetOff(this);
|
||||
}
|
||||
|
||||
protected lateUpdate() {
|
||||
if (!this._needUpdate) {
|
||||
return;
|
||||
}
|
||||
this._needUpdate = false;
|
||||
|
||||
let left = this._stateMachine.isMain ? 35 : 40;
|
||||
this.node.width = this.NameLabel.node.width + left + 15;
|
||||
this.BgNode.width = (this.node.width + 30) * 2;
|
||||
}
|
||||
|
||||
private onLabSizeChanged() {
|
||||
this._needUpdate = true;
|
||||
}
|
||||
|
||||
private onClick() {
|
||||
Events.emit(EventName.SET_CUR_STATE_MACHINE, this._stateMachine);
|
||||
}
|
||||
|
||||
@preloadEvent(EventName.STATE_MACHINE_NAME_CHANGED)
|
||||
private onEventStateNameChanged(stateMachine: StateMachine) {
|
||||
if (this._stateMachine !== stateMachine) {
|
||||
return;
|
||||
}
|
||||
this.NameLabel.string = stateMachine.name;
|
||||
}
|
||||
}
|
||||
9
animator-editor/assets/script/editor/fsm/BarItem.ts.meta
Normal file
9
animator-editor/assets/script/editor/fsm/BarItem.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "685739a3-7df5-4f61-99e1-efbf0175cf35",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
||||
607
animator-editor/assets/script/editor/fsm/FsmCtr.ts
Normal file
607
animator-editor/assets/script/editor/fsm/FsmCtr.ts
Normal file
@@ -0,0 +1,607 @@
|
||||
import Events, { EventName, preloadEvent } from "../../common/util/Events";
|
||||
import { ANIMATOR_VERSION } from "../../constant/BaseConst";
|
||||
import Condition from "../data/Condition";
|
||||
import State from "../data/State";
|
||||
import StateMachine from "../data/StateMachine";
|
||||
import Transition from "../data/Transition";
|
||||
import Editor from "../Editor";
|
||||
import ParamItem from "../parameters/ParamItem";
|
||||
import Line from "./Line";
|
||||
import MachineLayer from "./MachineLayer";
|
||||
import UnitBase from "./UnitBase";
|
||||
import UnitState from "./UnitState";
|
||||
import UnitStateMachine from "./UnitStateMachine";
|
||||
|
||||
const { ccclass, property } = cc._decorator;
|
||||
|
||||
@ccclass
|
||||
export default class FsmCtr extends cc.Component {
|
||||
@property(MachineLayer) MachineLayer: MachineLayer = null;
|
||||
@property(cc.Node) Cross: cc.Node = null;
|
||||
|
||||
/** 当前按下的鼠标按键 */
|
||||
private _curMouseBtn: number = null;
|
||||
/** moveUnit跟随鼠标的偏移值 */
|
||||
private _moveUnitOffset: cc.Vec2 = cc.v2(0, 0);
|
||||
/** 跟随鼠标移动的unit */
|
||||
private _moveUnit: UnitBase = null;
|
||||
/** 当前选中的unit */
|
||||
private _curUnit: UnitBase = null;
|
||||
/** 临时连线 */
|
||||
private _tempLine: Line = null;
|
||||
/** 当前选中的line */
|
||||
private _curLine: Line = null;
|
||||
|
||||
/** 上一次点击到StateMachine的时间 ms */
|
||||
private _lastClickTime: number = 0;
|
||||
|
||||
protected onLoad() {
|
||||
this.node.on(cc.Node.EventType.MOUSE_DOWN, this.onMouseDown, this);
|
||||
this.node.on(cc.Node.EventType.MOUSE_UP, this.onMouseUp, this);
|
||||
this.node.on(cc.Node.EventType.MOUSE_ENTER, this.onMouseEnter, this);
|
||||
this.node.on(cc.Node.EventType.MOUSE_MOVE, this.onMouseMove, this);
|
||||
this.node.on(cc.Node.EventType.MOUSE_LEAVE, this.onMouseLeave, this);
|
||||
this.node.on(cc.Node.EventType.MOUSE_WHEEL, this.onMouseWheel, this);
|
||||
|
||||
Events.targetOn(this);
|
||||
}
|
||||
|
||||
protected onDestroy() {
|
||||
Events.targetOff(this);
|
||||
}
|
||||
|
||||
protected lateUpdate() {
|
||||
if (this._moveUnit && this.MachineLayer.checkMoveUnit(this._moveUnit)) {
|
||||
this.Cross.active = true;
|
||||
} else {
|
||||
this.Cross.active = false;
|
||||
}
|
||||
}
|
||||
|
||||
//#region import and export
|
||||
private importTransitions(transitionsData: any[], state: State, stateMap: Map<string, State>, paramMap: Map<string, ParamItem>) {
|
||||
transitionsData.forEach((e) => {
|
||||
let toState: State = stateMap.get(e.toState);
|
||||
let transition: Transition = state.addTransition(toState);
|
||||
transition.hasExitTime = e.hasExitTime;
|
||||
e.conditions.forEach((cData) => {
|
||||
let paramItem = paramMap.get(cData.param);
|
||||
let condition: Condition = transition.addCondition(paramItem);
|
||||
condition.value = cData.value;
|
||||
condition.logic = cData.logic;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private importSubState(upData: any, upMachine: StateMachine, stateDataMap: Map<string, any>, stateMap: Map<string, State>, paramMap: Map<string, ParamItem>) {
|
||||
upData.subStates.forEach((name: string) => {
|
||||
let state = new State(upMachine, false);
|
||||
stateMap.set(name, state);
|
||||
let data = stateDataMap.get(name);
|
||||
state.setPosition(data.position[0], data.position[1]);
|
||||
state.name = data.state;
|
||||
state.motion = data.motion;
|
||||
state.speed = data.speed;
|
||||
state.multiplierParam = paramMap.get(data.multiplier) || null;
|
||||
state.loop = data.loop;
|
||||
|
||||
upMachine.add(state);
|
||||
});
|
||||
}
|
||||
|
||||
private importSubMachine(upData: any, upMachine: StateMachine, subMachineDataMap: Map<string, any>, subMachineMap: Map<string, StateMachine>, stateDataMap: Map<string, any>, stateMap: Map<string, State>, paramMap: Map<string, ParamItem>) {
|
||||
upData.subStateMachines.forEach((name: string) => {
|
||||
let stateMachine = new StateMachine(upMachine);
|
||||
subMachineMap.set(name, stateMachine);
|
||||
let data = subMachineDataMap.get(name);
|
||||
stateMachine.setLayerPos(data.layerPos[0], data.layerPos[1]);
|
||||
stateMachine.setLayerScale(data.layerScale);
|
||||
stateMachine.setAnyStatePos(data.anyStatePos[0], data.anyStatePos[1]);
|
||||
stateMachine.name = data.name;
|
||||
stateMachine.setPosition(data.position[0], data.position[1]);
|
||||
stateMachine.setUpStateMachinePos(data.upStateMachinePos[0], data.upStateMachinePos[1]);
|
||||
|
||||
upMachine.add(stateMachine);
|
||||
|
||||
this.importSubState(data, stateMachine, stateDataMap, stateMap, paramMap);
|
||||
this.importSubMachine(data, stateMachine, subMachineDataMap, subMachineMap, stateDataMap, stateMap, paramMap);
|
||||
});
|
||||
}
|
||||
|
||||
private exportAllSubMachine(arr: any[], stateMachine: StateMachine) {
|
||||
stateMachine.subStateMachines.forEach((sub) => {
|
||||
let data = {
|
||||
layerPos: [sub.layerPos.x, sub.layerPos.y],
|
||||
layerScale: sub.layerScale,
|
||||
anyStatePos: [sub.anyStatePos.x, sub.anyStatePos.y],
|
||||
name: sub.name,
|
||||
position: [sub.position.x, sub.position.y],
|
||||
upStateMachine: sub.upStateMachine.name,
|
||||
upStateMachinePos: [sub.upStateMachinePos.x, sub.upStateMachinePos.y],
|
||||
subStates: [],
|
||||
subStateMachines: [],
|
||||
}
|
||||
sub.subStates.forEach((e) => {
|
||||
data.subStates.push(e.name);
|
||||
});
|
||||
sub.subStateMachines.forEach((e) => {
|
||||
data.subStateMachines.push(e.name);
|
||||
});
|
||||
arr.push(data);
|
||||
this.exportAllSubMachine(arr, sub);
|
||||
});
|
||||
}
|
||||
|
||||
private exportAllState(arr: any[], stateMachine: StateMachine, isRuntimeData: boolean = false) {
|
||||
stateMachine.subStates.forEach((e) => {
|
||||
let data = null;
|
||||
if (isRuntimeData) {
|
||||
data = {
|
||||
state: e.name,
|
||||
motion: e.motion,
|
||||
speed: e.speed,
|
||||
multiplier: e.getMultiplierName(),
|
||||
loop: e.loop,
|
||||
transitions: e.getAllTransitionData()
|
||||
}
|
||||
} else {
|
||||
data = {
|
||||
position: [e.position.x, e.position.y],
|
||||
upStateMachine: e.upStateMachine.name,
|
||||
state: e.name,
|
||||
motion: e.motion,
|
||||
speed: e.speed,
|
||||
multiplier: e.getMultiplierName(),
|
||||
loop: e.loop,
|
||||
transitions: e.getAllTransitionData()
|
||||
}
|
||||
}
|
||||
arr.push(data);
|
||||
});
|
||||
stateMachine.subStateMachines.forEach((sub) => {
|
||||
this.exportAllState(arr, sub);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入工程数据
|
||||
*/
|
||||
public importProject(data: any) {
|
||||
let paramMap: Map<string, ParamItem> = Editor.Inst.ParamCtr.getParamMap();
|
||||
|
||||
let mainStateMachineData = data.mainStateMachine;
|
||||
let subStateMachinesData = data.subStateMachines;
|
||||
let defaultStateData: string = data.defaultState;
|
||||
let anyStateData = data.anyState;
|
||||
let statesData = data.states;
|
||||
|
||||
let stateDataMap: Map<string, any> = new Map();
|
||||
statesData.forEach((e: any) => { stateDataMap.set(e.state, e); });
|
||||
let stateMap: Map<string, State> = new Map();
|
||||
|
||||
let subMachineDataMap: Map<string, any> = new Map();
|
||||
subStateMachinesData.forEach((e: any) => { subMachineDataMap.set(e.name, e) });
|
||||
let subMachineMap: Map<string, StateMachine> = new Map();
|
||||
|
||||
let main = this.MachineLayer.mainStateMachine;
|
||||
main.setLayerPos(mainStateMachineData.layerPos[0], mainStateMachineData.layerPos[1]);
|
||||
main.setLayerScale(mainStateMachineData.layerScale);
|
||||
main.setAnyStatePos(mainStateMachineData.anyStatePos[0], mainStateMachineData.anyStatePos[1]);
|
||||
this.importSubState(mainStateMachineData, main, stateDataMap, stateMap, paramMap);
|
||||
this.importSubMachine(mainStateMachineData, main, subMachineDataMap, subMachineMap, stateDataMap, stateMap, paramMap);
|
||||
|
||||
if (stateMap.has(defaultStateData))
|
||||
this.MachineLayer.defaultState = stateMap.get(defaultStateData);
|
||||
|
||||
this.importTransitions(anyStateData.transitions, this.MachineLayer.anyState.state, stateMap, paramMap);
|
||||
statesData.forEach((e: any) => {
|
||||
let state: State = stateMap.get(e.state);
|
||||
if (!state) {
|
||||
cc.error('error');
|
||||
}
|
||||
this.importTransitions(e.transitions, state, stateMap, paramMap);
|
||||
});
|
||||
|
||||
this.MachineLayer.setCurStateMachine();
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出工程数据
|
||||
*/
|
||||
public exportProject() {
|
||||
let main = this.MachineLayer.mainStateMachine;
|
||||
let animator = ANIMATOR_VERSION;
|
||||
let mainStateMachine = {
|
||||
layerPos: [main.layerPos.x, main.layerPos.y],
|
||||
layerScale: main.layerScale,
|
||||
anyStatePos: [main.anyStatePos.x, main.anyStatePos.y],
|
||||
subStates: [],
|
||||
subStateMachines: [],
|
||||
};
|
||||
main.subStates.forEach((e) => {
|
||||
mainStateMachine.subStates.push(e.name);
|
||||
});
|
||||
main.subStateMachines.forEach((e) => {
|
||||
mainStateMachine.subStateMachines.push(e.name);
|
||||
});
|
||||
let subStateMachines = [];
|
||||
this.exportAllSubMachine(subStateMachines, main);
|
||||
|
||||
let defaultState: string = this.MachineLayer.defaultState ? this.MachineLayer.defaultState.name : '';
|
||||
let anyState = {
|
||||
transitions: this.MachineLayer.anyState.state.getAllTransitionData()
|
||||
};
|
||||
let states = [];
|
||||
this.exportAllState(states, main);
|
||||
return {
|
||||
animator: animator,
|
||||
mainStateMachine: mainStateMachine,
|
||||
subStateMachines: subStateMachines,
|
||||
defaultState: defaultState,
|
||||
anyState: anyState,
|
||||
states: states
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出runtime数据
|
||||
*/
|
||||
public exportRuntimeData() {
|
||||
let main = this.MachineLayer.mainStateMachine;
|
||||
let defaultState: string = this.MachineLayer.defaultState ? this.MachineLayer.defaultState.name : '';
|
||||
let anyState = {
|
||||
transitions: this.MachineLayer.anyState.state.getAllTransitionData()
|
||||
};
|
||||
let states = [];
|
||||
this.exportAllState(states, main, true);
|
||||
return {
|
||||
defaultState: defaultState,
|
||||
anyState: anyState,
|
||||
states: states
|
||||
};
|
||||
}
|
||||
//#endregion
|
||||
|
||||
/**
|
||||
* 按下鼠标左键的处理
|
||||
*/
|
||||
private onMouseDownLeft(worldPos: cc.Vec2, posInCurLayer: cc.Vec2) {
|
||||
let nextUnit = this.MachineLayer.getUnitByPos(posInCurLayer);
|
||||
if (nextUnit instanceof UnitState) {
|
||||
// 点击到AnyState删除临时连线
|
||||
if (nextUnit.isAnyState) {
|
||||
this.deleteLine(this._tempLine);
|
||||
}
|
||||
|
||||
this._curLine && this._curLine.select(false);
|
||||
this._curLine = null;
|
||||
this._moveUnitOffset = posInCurLayer.sub(nextUnit.node.position);
|
||||
this._moveUnit = nextUnit;
|
||||
|
||||
if (this._curUnit !== nextUnit) {
|
||||
if (this._tempLine) {
|
||||
this._moveUnit = null;
|
||||
|
||||
// 处理临时连线
|
||||
let line = this.MachineLayer.getLineByUnit(this._curUnit, nextUnit);
|
||||
// 新增transition
|
||||
this._curUnit.addTransition(nextUnit, nextUnit.state);
|
||||
if (line) {
|
||||
// 删除临时连线
|
||||
this.deleteLine(this._tempLine);
|
||||
} else {
|
||||
// 连接line
|
||||
this._tempLine.onInit(this._curUnit, nextUnit);
|
||||
// 清除
|
||||
this._tempLine = null;
|
||||
}
|
||||
} else {
|
||||
// 选中state
|
||||
this._curUnit && this._curUnit.select(false);
|
||||
this._curUnit = nextUnit;
|
||||
this._curUnit.select(true);
|
||||
Events.emit(EventName.INSPECTOR_SHOW_UNIT, this._curUnit);
|
||||
}
|
||||
}
|
||||
} else if (nextUnit instanceof UnitStateMachine) {
|
||||
let now = Date.now();
|
||||
let delt = now - this._lastClickTime;
|
||||
this._lastClickTime = now;
|
||||
if (this._curUnit === nextUnit && delt < 500) {
|
||||
this.setCurStateMachine(nextUnit.stateMachine);
|
||||
return;
|
||||
}
|
||||
|
||||
this._curLine && this._curLine.select(false);
|
||||
this._curLine = null;
|
||||
this._moveUnitOffset = posInCurLayer.sub(nextUnit.node.position);
|
||||
this._moveUnit = nextUnit;
|
||||
|
||||
if (this._curUnit !== nextUnit) {
|
||||
if (this._tempLine) {
|
||||
this._moveUnit = null;
|
||||
|
||||
// 弹出选择菜单,显示状态机中所有状态
|
||||
Events.emit(EventName.SHOW_LINE_TO_List, worldPos, nextUnit, this.MachineLayer.curStateMachine);
|
||||
} else {
|
||||
// 选中unit
|
||||
this._curUnit && this._curUnit.select(false);
|
||||
this._curUnit = nextUnit;
|
||||
this._curUnit.select(true);
|
||||
Events.emit(EventName.INSPECTOR_SHOW_UNIT, this._curUnit);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this._moveUnit = null;
|
||||
this._curUnit && this._curUnit.select(false);
|
||||
this._curUnit = null;
|
||||
let nextLine = this.MachineLayer.getLineByPos(posInCurLayer);
|
||||
if (nextLine) {
|
||||
if (this._curLine !== nextLine) {
|
||||
// 选中line
|
||||
this._curLine && this._curLine.select(false);
|
||||
this._curLine = nextLine;
|
||||
this._curLine.select(true);
|
||||
Events.emit(EventName.INSPECTOR_SHOW_LINE, this._curLine);
|
||||
}
|
||||
} else {
|
||||
this._curLine && this._curLine.select(false);
|
||||
this._curLine = null;
|
||||
Events.emit(EventName.INSPECTOR_HIDE);
|
||||
}
|
||||
|
||||
// 删除临时连线
|
||||
this.deleteLine(this._tempLine);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 按下鼠标右键的处理
|
||||
*/
|
||||
private onMouseDownRight(posInCurLayer: cc.Vec2) {
|
||||
// 判断是否选中state
|
||||
let nextUnit = this.MachineLayer.getUnitByPos(posInCurLayer);
|
||||
if (nextUnit) {
|
||||
this._curLine && this._curLine.select(false);
|
||||
this._curLine = null;
|
||||
this._moveUnitOffset = posInCurLayer.sub(nextUnit.node.position);
|
||||
|
||||
if (this._curUnit !== nextUnit) {
|
||||
this._curUnit && this._curUnit.select(false);
|
||||
this._curUnit = nextUnit;
|
||||
this._curUnit.select(true);
|
||||
Events.emit(EventName.INSPECTOR_SHOW_UNIT, this._curUnit);
|
||||
}
|
||||
}
|
||||
|
||||
// 删除临时连线
|
||||
this.deleteLine(this._tempLine);
|
||||
}
|
||||
|
||||
private onMouseDown(event: cc.Event.EventMouse) {
|
||||
this._curMouseBtn = event.getButton();
|
||||
let posInCtr: cc.Vec2 = this.node.convertToNodeSpaceAR(event.getLocation());
|
||||
let posInCurLayer: cc.Vec2 = this.MachineLayer.node.convertToNodeSpaceAR(event.getLocation());
|
||||
|
||||
if (this._curMouseBtn === cc.Event.EventMouse.BUTTON_LEFT) {
|
||||
// 按下鼠标左键
|
||||
this.onMouseDownLeft(event.getLocation(), posInCurLayer);
|
||||
} else if (this._curMouseBtn === cc.Event.EventMouse.BUTTON_RIGHT) {
|
||||
// 按下鼠标右键
|
||||
this.onMouseDownRight(posInCurLayer);
|
||||
} else if (this._curMouseBtn === cc.Event.EventMouse.BUTTON_MIDDLE) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private onMouseUp(event: cc.Event.EventMouse) {
|
||||
let posInCtr: cc.Vec2 = this.node.convertToNodeSpaceAR(event.getLocation());
|
||||
let posInCurLayer: cc.Vec2 = this.MachineLayer.node.convertToNodeSpaceAR(event.getLocation());
|
||||
|
||||
if (this._curMouseBtn === cc.Event.EventMouse.BUTTON_LEFT) {
|
||||
// bug: 没处理跨越多层transition
|
||||
if (this._moveUnit && this.MachineLayer.moveIntoStateMachine(this._moveUnit)) {
|
||||
this._moveUnit = null;
|
||||
this._curUnit = null;
|
||||
Events.emit(EventName.INSPECTOR_HIDE);
|
||||
}
|
||||
} else if (this._curMouseBtn === cc.Event.EventMouse.BUTTON_RIGHT) {
|
||||
// 松开鼠标右键 弹出右键菜单
|
||||
let state = this.MachineLayer.getUnitByPos(posInCurLayer);
|
||||
let curState = (this._curUnit && this._curUnit === state) ? this._curUnit : null;
|
||||
Events.emit(EventName.SHOW_RIGHT_MENU, event.getLocation(), curState);
|
||||
} else if (this._curMouseBtn === cc.Event.EventMouse.BUTTON_MIDDLE) {
|
||||
}
|
||||
|
||||
// 松开鼠标按键时清空
|
||||
this._curMouseBtn = null;
|
||||
}
|
||||
|
||||
private onMouseEnter(event: cc.Event.EventMouse) {
|
||||
if (event.getButton() === null) {
|
||||
this._curMouseBtn = null;
|
||||
}
|
||||
}
|
||||
|
||||
private onMouseMove(event: cc.Event.EventMouse) {
|
||||
let posInCtr: cc.Vec2 = this.node.convertToNodeSpaceAR(event.getLocation());
|
||||
let posInCurLayer: cc.Vec2 = this.MachineLayer.node.convertToNodeSpaceAR(event.getLocation());
|
||||
|
||||
if (event.getButton() === null) {
|
||||
this._curMouseBtn = null;
|
||||
}
|
||||
|
||||
// 移动临时连线
|
||||
if (this._curUnit && this._tempLine) {
|
||||
let unit = this.MachineLayer.getUnitByPos(posInCurLayer);
|
||||
if (unit && unit !== this._curUnit && ((unit instanceof UnitState && !unit.isAnyState) || unit instanceof UnitStateMachine)) {
|
||||
this._tempLine.setLine(this._curUnit.node.position, unit.node.position);
|
||||
} else {
|
||||
this._tempLine.setLine(this._curUnit.node.position, posInCurLayer);
|
||||
}
|
||||
}
|
||||
|
||||
if (this._curMouseBtn === cc.Event.EventMouse.BUTTON_LEFT) {
|
||||
// 按住鼠标左键 移动选中的状态
|
||||
if (this._moveUnit) {
|
||||
this._moveUnit.setPos(posInCurLayer.sub(this._moveUnitOffset));
|
||||
this.Cross.position = posInCtr;
|
||||
}
|
||||
} else if (this._curMouseBtn === cc.Event.EventMouse.BUTTON_RIGHT) {
|
||||
|
||||
} else if (this._curMouseBtn === cc.Event.EventMouse.BUTTON_MIDDLE) {
|
||||
// 按住鼠标中键 移动当前MachineLayer
|
||||
this.MachineLayer.setPos(this.MachineLayer.node.position.add(event.getDelta()));
|
||||
}
|
||||
}
|
||||
|
||||
private onMouseLeave(event: cc.Event.EventMouse) {
|
||||
if (event.getButton() === null) {
|
||||
this._curMouseBtn = null;
|
||||
}
|
||||
}
|
||||
|
||||
private onMouseWheel(event: cc.Event.EventMouse) {
|
||||
// 滚动鼠标滚轮 缩放当前MachineLayer
|
||||
this.MachineLayer.changeScale(event.getScrollY() > 0, event.getLocation());
|
||||
}
|
||||
|
||||
private setCurStateMachine(stateMachine: StateMachine) {
|
||||
if (this.MachineLayer.curStateMachine === stateMachine) {
|
||||
return;
|
||||
}
|
||||
this._lastClickTime = 0;
|
||||
this._moveUnit = null;
|
||||
this._curUnit = null;
|
||||
this._tempLine = null;
|
||||
this._curLine = null;
|
||||
this.MachineLayer.setCurStateMachine(stateMachine);
|
||||
Events.emit(EventName.INSPECTOR_HIDE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除line
|
||||
*/
|
||||
private deleteLine(line: Line) {
|
||||
if (!line) {
|
||||
return;
|
||||
}
|
||||
if (this._curLine === line) {
|
||||
this._curLine = null;
|
||||
}
|
||||
if (this._tempLine === line) {
|
||||
this._tempLine = null;
|
||||
}
|
||||
this.MachineLayer.deleteLine(line);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除当前选中的line
|
||||
*/
|
||||
public deleteCurLine() {
|
||||
if (!this._curLine) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.deleteLine(this._curLine);
|
||||
Events.emit(EventName.INSPECTOR_HIDE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除当前选中的unit
|
||||
*/
|
||||
public deleteCurUnit() {
|
||||
if (!this._curUnit) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._curUnit instanceof UnitState) {
|
||||
if (this._curUnit.isAnyState) {
|
||||
return;
|
||||
}
|
||||
this.MachineLayer.deleteState(this._curUnit);
|
||||
} else if (this._curUnit instanceof UnitStateMachine) {
|
||||
if (this._curUnit.isUp) {
|
||||
return;
|
||||
}
|
||||
this.MachineLayer.deleteStateMachine(this._curUnit);
|
||||
}
|
||||
this._curUnit = null;
|
||||
this._moveUnit = null;
|
||||
this.deleteLine(this._tempLine);
|
||||
Events.emit(EventName.INSPECTOR_HIDE);
|
||||
}
|
||||
|
||||
//#region 按钮回调
|
||||
private onClickCreateState(event: cc.Event) {
|
||||
Events.emit(EventName.CLOSE_MENU);
|
||||
let menuNode: cc.Node = Editor.Inst.Menu.RightMenu;
|
||||
let posInCurLayer: cc.Vec2 = this.MachineLayer.node.convertToNodeSpaceAR(menuNode.parent.convertToWorldSpaceAR(menuNode.position));
|
||||
this.MachineLayer.createState(posInCurLayer);
|
||||
}
|
||||
|
||||
private onClickCreateSubMachine() {
|
||||
Events.emit(EventName.CLOSE_MENU);
|
||||
let menuNode: cc.Node = Editor.Inst.Menu.RightMenu;
|
||||
let posInCurLayer: cc.Vec2 = this.MachineLayer.node.convertToNodeSpaceAR(menuNode.parent.convertToWorldSpaceAR(menuNode.position));
|
||||
this.MachineLayer.createStateMachine(posInCurLayer);
|
||||
}
|
||||
|
||||
private onClickMakeTrasition() {
|
||||
Events.emit(EventName.CLOSE_MENU);
|
||||
if (!this._curUnit) {
|
||||
return;
|
||||
}
|
||||
this._tempLine = this.MachineLayer.createLine();
|
||||
this._tempLine.setLine(this._curUnit.node.position, this._curUnit.node.position);
|
||||
}
|
||||
|
||||
private onClickSetDefault() {
|
||||
Events.emit(EventName.CLOSE_MENU);
|
||||
if (!this._curUnit || !(this._curUnit instanceof UnitState) || this._curUnit.isAnyState) {
|
||||
return;
|
||||
}
|
||||
this.MachineLayer.setDefaultState(this._curUnit);
|
||||
}
|
||||
|
||||
private onClickDeleteCurUnit() {
|
||||
Events.emit(EventName.CLOSE_MENU);
|
||||
this.deleteCurUnit();
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//#region 事件监听
|
||||
@preloadEvent(EventName.LINE_TO_MACHINE_STATE)
|
||||
private onEventLineToMachineState(state: State, to: UnitStateMachine) {
|
||||
if (!this._curUnit || !this._tempLine) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._moveUnit = null;
|
||||
|
||||
// 处理临时连线
|
||||
let line = this.MachineLayer.getLineByUnit(this._curUnit, to);
|
||||
// 新增transition
|
||||
this._curUnit.addTransition(to, state);
|
||||
if (line || (this._curUnit instanceof UnitState && this._curUnit.isAnyState)) {
|
||||
// 删除临时连线
|
||||
this.deleteLine(this._tempLine);
|
||||
} else {
|
||||
// 连接line
|
||||
this._tempLine.onInit(this._curUnit, to);
|
||||
// 清除
|
||||
this._tempLine = null;
|
||||
}
|
||||
}
|
||||
|
||||
@preloadEvent(EventName.LINE_DELETE)
|
||||
private onEventLineDelete(line: Line) {
|
||||
this.deleteLine(line);
|
||||
}
|
||||
|
||||
@preloadEvent(EventName.SET_CUR_STATE_MACHINE)
|
||||
private onEventSetCurStateMachine(stateMachine: StateMachine) {
|
||||
this.setCurStateMachine(stateMachine);
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
9
animator-editor/assets/script/editor/fsm/FsmCtr.ts.meta
Normal file
9
animator-editor/assets/script/editor/fsm/FsmCtr.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "323aebfe-14d1-4acd-8e95-b6085c8599dd",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
||||
173
animator-editor/assets/script/editor/fsm/Line.ts
Normal file
173
animator-editor/assets/script/editor/fsm/Line.ts
Normal file
@@ -0,0 +1,173 @@
|
||||
import Events, { EventName, preloadEvent } from "../../common/util/Events";
|
||||
import Transition from "../data/Transition";
|
||||
import UnitBase from "./UnitBase";
|
||||
|
||||
const { ccclass, property } = cc._decorator;
|
||||
|
||||
const RADIUS = 10;
|
||||
const Color = {
|
||||
NORMAL: cc.color(255, 255, 255),
|
||||
SELECT: cc.color(137, 161, 255),
|
||||
TEMP: cc.color(50, 200, 40)
|
||||
};
|
||||
|
||||
@ccclass
|
||||
export default class Line extends cc.Component {
|
||||
@property(cc.Node) SprNode: cc.Node = null;
|
||||
@property(cc.Node) TriNodes: cc.Node[] = [];
|
||||
|
||||
private _hasInit: boolean = false;
|
||||
private _needUpdate: boolean = false;
|
||||
|
||||
/** 连线起点 */
|
||||
private _fromPos: cc.Vec2 = cc.v2(0, 0);
|
||||
/** 连线终点 */
|
||||
private _toPos: cc.Vec2 = cc.v2(0, 0);
|
||||
/** 连线与节点中心的的偏移值 */
|
||||
private _offset: cc.Vec2 = cc.v2(0, 0);
|
||||
|
||||
private _fromUnit: UnitBase = null;
|
||||
public get fromUnit() { return this._fromUnit; }
|
||||
|
||||
private _toUnit: UnitBase = null;
|
||||
public get toUnit() { return this._toUnit; }
|
||||
|
||||
protected onLoad() {
|
||||
this.setColor(Color.TEMP);
|
||||
}
|
||||
|
||||
public onInit(from: UnitBase, to: UnitBase) {
|
||||
this._hasInit = true;
|
||||
this._needUpdate = true;
|
||||
this._fromUnit = from;
|
||||
this._toUnit = to;
|
||||
|
||||
this.setColor(Color.NORMAL);
|
||||
this.checkSize(this.getTransitions().length);
|
||||
|
||||
this._fromUnit.node.on(cc.Node.EventType.POSITION_CHANGED, this.onStateMoved, this);
|
||||
this._toUnit.node.on(cc.Node.EventType.POSITION_CHANGED, this.onStateMoved, this);
|
||||
|
||||
Events.targetOn(this);
|
||||
}
|
||||
|
||||
protected onDestroy() {
|
||||
if (!this._hasInit) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._fromUnit.node && this._fromUnit.node.off(cc.Node.EventType.POSITION_CHANGED, this.onStateMoved, this);
|
||||
this._toUnit.node && this._toUnit.node.off(cc.Node.EventType.POSITION_CHANGED, this.onStateMoved, this);
|
||||
|
||||
Events.targetOff(this);
|
||||
}
|
||||
|
||||
protected lateUpdate() {
|
||||
if (!this._needUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._needUpdate = true;
|
||||
this.setLine(this._fromUnit.node.position, this._toUnit.node.position);
|
||||
}
|
||||
|
||||
private onStateMoved() {
|
||||
this._needUpdate = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据transitionSet数量更改line上三角的显示
|
||||
*/
|
||||
private checkSize(size: number) {
|
||||
if (size > 1) {
|
||||
this.TriNodes[1].active = true;
|
||||
this.TriNodes[2].active = true;
|
||||
} else {
|
||||
this.TriNodes[1].active = false;
|
||||
this.TriNodes[2].active = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置连线颜色
|
||||
*/
|
||||
private setColor(color: cc.Color) {
|
||||
this.SprNode.color = color;
|
||||
this.TriNodes.forEach((e) => {
|
||||
e.color = color;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取连线所代表的所有Transition
|
||||
*/
|
||||
public getTransitions(): Transition[] {
|
||||
if (!this._hasInit) {
|
||||
return [];
|
||||
}
|
||||
return this._fromUnit.getTransitions(this._toUnit);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据起点坐标与终点坐标设置线段
|
||||
* @param fromPos 起点坐标
|
||||
* @param toPos 终点坐标
|
||||
*/
|
||||
public setLine(fromPos: cc.Vec2, toPos: cc.Vec2) {
|
||||
let dir = cc.v2(toPos.sub(fromPos));
|
||||
this._offset = this._hasInit ? dir.rotate(-Math.PI / 2).normalize().mul(RADIUS) : cc.v2(0, 0);
|
||||
this._fromPos = fromPos.add(this._offset);
|
||||
this._toPos = toPos.add(this._offset);
|
||||
|
||||
this.node.position = this._fromPos.add(this._toPos).mul(0.5);
|
||||
this.node.angle = dir.equals(cc.Vec2.ZERO) ? 0 : -cc.misc.radiansToDegrees(dir.signAngle(cc.v2(0, 1)));
|
||||
this.node.height = dir.mag();
|
||||
this.SprNode.height = this.node.height;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断参数是否为连线端点的state
|
||||
*/
|
||||
public relatedState(state: UnitBase) {
|
||||
return this._fromUnit === state || this._toUnit === state;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断Layer层坐标是否在line节点内
|
||||
* @param pos
|
||||
*/
|
||||
public contains(pos: cc.Vec2) {
|
||||
if (!this._hasInit) {
|
||||
return false;
|
||||
}
|
||||
let delt = this._offset;
|
||||
let points: cc.Vec2[] = [this._fromPos.add(delt), this._toPos.add(delt), this._toPos.sub(delt), this._fromPos.sub(delt)];
|
||||
return cc.Intersection.pointInPolygon(pos, points);
|
||||
}
|
||||
|
||||
/**
|
||||
* 选中line
|
||||
* @param value true:选中 false:取消选中
|
||||
*/
|
||||
public select(value: boolean) {
|
||||
this.setColor(value ? Color.SELECT : Color.NORMAL);
|
||||
}
|
||||
|
||||
@preloadEvent(EventName.TRANSITION_ADD)
|
||||
private onEventTransitionAdd(fromUnit: UnitBase, toUnit: UnitBase, transition: Transition) {
|
||||
if (this._fromUnit === fromUnit && this._toUnit === toUnit) {
|
||||
this.checkSize(this.getTransitions().length);
|
||||
}
|
||||
}
|
||||
|
||||
@preloadEvent(EventName.TRANSITION_DELETE)
|
||||
private onEventTransitionDelete(transition: Transition) {
|
||||
let arr = this.getTransitions();
|
||||
if (arr.length <= 0) {
|
||||
// 删除线条
|
||||
Events.emit(EventName.LINE_DELETE, this);
|
||||
} else {
|
||||
this.checkSize(arr.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
9
animator-editor/assets/script/editor/fsm/Line.ts.meta
Normal file
9
animator-editor/assets/script/editor/fsm/Line.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "2aff73f9-2e11-422c-bcc4-c338379b1548",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
||||
479
animator-editor/assets/script/editor/fsm/MachineLayer.ts
Normal file
479
animator-editor/assets/script/editor/fsm/MachineLayer.ts
Normal file
@@ -0,0 +1,479 @@
|
||||
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;
|
||||
|
||||
@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: State) { 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(6750, 6750);
|
||||
this.Grid.setContentSize(6750, 6750);
|
||||
this._mainStateMachine = new StateMachine(null);
|
||||
this._curStateMachine = this._mainStateMachine;
|
||||
this._anyState = this.createState(cc.v2(-360, 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: StateMachine) {
|
||||
// 更新面包屑导航栏的显示
|
||||
let arr: StateMachine[] = [curStateMachine];
|
||||
while (curStateMachine.upStateMachine) {
|
||||
arr.unshift(curStateMachine.upStateMachine);
|
||||
curStateMachine = curStateMachine.upStateMachine;
|
||||
}
|
||||
this.NavBar.refreshBar(arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空状态机数据
|
||||
*/
|
||||
public clear() {
|
||||
this._mainStateMachine.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* 改变当前视图显示的状态机,不传参则刷新当前视图
|
||||
*/
|
||||
public setCurStateMachine(stateMachine: StateMachine = null) {
|
||||
if (this._curStateMachine === stateMachine) {
|
||||
return;
|
||||
}
|
||||
if (stateMachine === null) {
|
||||
stateMachine = this._curStateMachine;
|
||||
}
|
||||
this._curStateMachine = stateMachine;
|
||||
|
||||
this.refreshNavBar(stateMachine);
|
||||
|
||||
// 处理父状态机节点和AnyState
|
||||
if (!stateMachine.upStateMachine) {
|
||||
if (this._upUnit) {
|
||||
this._upUnit.node.removeFromParent();
|
||||
this._upUnit.node.destroy();
|
||||
this._upUnit = null;
|
||||
}
|
||||
} else {
|
||||
if (!this._upUnit) {
|
||||
let node: cc.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: Map<State, UnitState> = new Map();
|
||||
let machineMap: Map<StateMachine, UnitStateMachine> = new Map();
|
||||
this._upUnit && machineMap.set(stateMachine.upStateMachine, this._upUnit);
|
||||
stateMachine.subStates.forEach((e) => {
|
||||
let node: cc.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.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: State = stateKeys.next().value;
|
||||
let fromUnit: UnitBase = stateMap.get(state);
|
||||
let toUnitSet: Set<UnitBase> = new Set();
|
||||
let transitions = state.getTransitions();
|
||||
transitions.forEach((t: Transition) => {
|
||||
let toUnit: UnitBase = 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: StateMachine = 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;
|
||||
}
|
||||
}
|
||||
|
||||
// fromUnit向其余状态、状态机的连线
|
||||
if (!toUnitSet.has(toUnit)) {
|
||||
toUnitSet.add(toUnit);
|
||||
let line = this.createLine();
|
||||
line.onInit(fromUnit, toUnit);
|
||||
}
|
||||
});
|
||||
|
||||
// AnyState连向fromUnit的连线
|
||||
if (this._anyState.state.getTransitions(state).length > 0) {
|
||||
let line = this.createLine();
|
||||
line.onInit(this._anyState, fromUnit);
|
||||
}
|
||||
|
||||
// 状态机节点连向fromUnit的连线
|
||||
let machineKeys = machineMap.keys();
|
||||
for (let j = 0; j < machineMap.size; j++) {
|
||||
let machine: StateMachine = machineKeys.next().value;
|
||||
if (machine.getTransitions(state).length > 0) {
|
||||
let line = this.createLine();
|
||||
line.onInit(machineMap.get(machine), fromUnit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新建状态机节点
|
||||
*/
|
||||
public createStateMachine(pos: cc.Vec2): UnitStateMachine {
|
||||
let node: cc.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: cc.Vec2, isAnyState: boolean = false): UnitState {
|
||||
let node: cc.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(): Line {
|
||||
let node: cc.Node = cc.instantiate(Res.getLoaded(ResUrl.PREFAB.LINE));
|
||||
this.LineContent.addChild(node);
|
||||
return node.getComponent(Line);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除子状态机
|
||||
*/
|
||||
public deleteStateMachine(unitStateMachine: UnitStateMachine) {
|
||||
// 先删除连线,再删除状态机(删除顺序倒过来会影响查找到的连线数据)
|
||||
for (let i = this.LineContent.childrenCount - 1; i >= 0; i--) {
|
||||
let line: 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: UnitState) {
|
||||
// 先删除连线,再删除状态(删除顺序倒过来会影响查找到的连线数据)
|
||||
for (let i = this.LineContent.childrenCount - 1; i >= 0; i--) {
|
||||
let line: 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) {
|
||||
line.getTransitions().forEach((e) => {
|
||||
e.fromState.deleteTransition(e);
|
||||
});
|
||||
|
||||
line.node.removeFromParent();
|
||||
line.node.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据Layer层坐标获取点击到的unit
|
||||
*/
|
||||
public getUnitByPos(pos: cc.Vec2): UnitBase {
|
||||
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: cc.Vec2): Line {
|
||||
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: UnitBase, to: UnitBase): Line {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断moveUnit节点是否可移入某个状态机节点内
|
||||
* @param moveUnit 跟随鼠标移动的unit
|
||||
*/
|
||||
public checkMoveUnit(moveUnit: UnitBase): UnitStateMachine {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试将moveUnit节点移入重叠的状态机内
|
||||
* @param moveUnit
|
||||
* @returns 是否进行移入操作
|
||||
*/
|
||||
public moveIntoStateMachine(moveUnit: UnitBase): boolean {
|
||||
let unit: UnitStateMachine = this.checkMoveUnit(moveUnit);
|
||||
if (!unit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let needRefresh: boolean = 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: UnitState = null) {
|
||||
if (!unitState) {
|
||||
if (this._curStateMachine.subStates.size === 0) {
|
||||
// 当前视图没有State
|
||||
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: cc.Vec2) {
|
||||
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 true为放大, false为缩小
|
||||
* @param worldPos 鼠标所在的世界坐标
|
||||
*/
|
||||
public changeScale(value: boolean, worldPos: cc.Vec2) {
|
||||
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: cc.Vec2) {
|
||||
this._curStateMachine.setAnyStatePos(pos);
|
||||
}
|
||||
|
||||
@preloadEvent(EventName.UP_STATE_MACHINE_MOVE)
|
||||
private onEventUpStateMachineMove(pos: cc.Vec2) {
|
||||
this._curStateMachine.setUpStateMachinePos(pos);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "8366ea51-c189-47b4-ba38-2dd088175777",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
||||
52
animator-editor/assets/script/editor/fsm/NavBar.ts
Normal file
52
animator-editor/assets/script/editor/fsm/NavBar.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import Events, { EventName, preloadEvent } from "../../common/util/Events";
|
||||
import RecyclePool from "../../common/util/RecyclePool";
|
||||
import Res from "../../common/util/Res";
|
||||
import { ResUrl } from "../../constant/ResUrl";
|
||||
import StateMachine from "../data/StateMachine";
|
||||
import Editor from "../Editor";
|
||||
import BarItem from "./BarItem";
|
||||
|
||||
const { ccclass, property } = cc._decorator;
|
||||
|
||||
@ccclass
|
||||
export default class NavBar extends cc.Component {
|
||||
@property(cc.Node) Content: cc.Node = null;
|
||||
|
||||
private _widget: cc.Widget = null;
|
||||
private _contentWidget: cc.Widget = null;
|
||||
|
||||
protected onLoad() {
|
||||
this._widget = this.getComponent(cc.Widget);
|
||||
this._contentWidget = this.Content.getComponent(cc.Widget);
|
||||
Events.targetOn(this);
|
||||
}
|
||||
|
||||
protected onDestroy() {
|
||||
Events.targetOff(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新面包屑导航栏显示
|
||||
* @param stateMachines 按层级顺序排列的状态机数组
|
||||
*/
|
||||
public refreshBar(stateMachines: StateMachine[]) {
|
||||
for (let i = this.Content.childrenCount - 1; i >= 0; i--) {
|
||||
RecyclePool.put(BarItem, this.Content.children[i]);
|
||||
}
|
||||
|
||||
stateMachines.forEach((e, index) => {
|
||||
let node: cc.Node = RecyclePool.get(BarItem) || cc.instantiate(Res.getLoaded(ResUrl.PREFAB.BAR_ITEM));
|
||||
this.Content.addChild(node);
|
||||
let bar = node.getComponent(BarItem);
|
||||
bar.onInit(e, index === stateMachines.length - 1);
|
||||
});
|
||||
}
|
||||
|
||||
@preloadEvent(EventName.RESIZE)
|
||||
private onEventResize(node: cc.Node) {
|
||||
this._widget.left = Editor.Inst.ParamCtr.node.width;
|
||||
this._widget.right = Editor.Inst.Inspector.node.width;
|
||||
this._widget.updateAlignment();
|
||||
this._contentWidget.updateAlignment();
|
||||
}
|
||||
}
|
||||
9
animator-editor/assets/script/editor/fsm/NavBar.ts.meta
Normal file
9
animator-editor/assets/script/editor/fsm/NavBar.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "c7581de7-e34c-4d10-81a7-7cb05e82f531",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
||||
67
animator-editor/assets/script/editor/fsm/UnitBase.ts
Normal file
67
animator-editor/assets/script/editor/fsm/UnitBase.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import State from "../data/State";
|
||||
import Transition from "../data/Transition";
|
||||
|
||||
const { ccclass, property } = cc._decorator;
|
||||
|
||||
export const UnitColor = {
|
||||
NORMAL: cc.color(150, 150, 150),
|
||||
DEFAULT: cc.color(210, 120, 70),
|
||||
ANY_STATE: cc.color(92, 190, 199)
|
||||
}
|
||||
|
||||
/**
|
||||
* 状态节点或者状态机节点的基类
|
||||
*/
|
||||
@ccclass
|
||||
export default class UnitBase extends cc.Component {
|
||||
@property(cc.Node) SelectNode: cc.Node = null;
|
||||
@property(cc.Node) BgNode: cc.Node = null;
|
||||
@property(cc.Label) NameLabel: cc.Label = null;
|
||||
|
||||
protected _isDefault: boolean = false;
|
||||
/**
|
||||
* 是否为默认状态
|
||||
* @virtual
|
||||
*/
|
||||
public get isDefault() { return this._isDefault; }
|
||||
public set isDefault(v: boolean) {
|
||||
this._isDefault = v;
|
||||
this.BgNode.color = this._isDefault ? UnitColor.DEFAULT : UnitColor.NORMAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* 选中节点
|
||||
* @param value true:选中 false:取消选中
|
||||
*/
|
||||
public select(value: boolean) {
|
||||
this.SelectNode.active = value;
|
||||
this.node.setSiblingIndex(this.node.parent.childrenCount - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加Transition
|
||||
* @virtual
|
||||
*/
|
||||
public addTransition(toUnit: UnitBase, toState: State) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取此节点到目标节点的所有Transition
|
||||
* @virtual
|
||||
* @param toUnit 目标节点
|
||||
*/
|
||||
public getTransitions(toUnit: UnitBase = null): Transition[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置layer层坐标系下坐标
|
||||
* @virtual
|
||||
*/
|
||||
public setPos(x: number | cc.Vec2 | cc.Vec3, y: number = 0) {
|
||||
let pos: cc.Vec2 = cc.v2(x, y);
|
||||
pos = cc.v2(Math.round(pos.x / 30) * 30, Math.round(pos.y / 30) * 30);
|
||||
this.node.position = pos;
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "de0ee56a-435e-4d63-b773-c33f0739a9f5",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
||||
106
animator-editor/assets/script/editor/fsm/UnitState.ts
Normal file
106
animator-editor/assets/script/editor/fsm/UnitState.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import Events, { EventName, preloadEvent } from "../../common/util/Events";
|
||||
import State from "../data/State";
|
||||
import StateMachine from "../data/StateMachine";
|
||||
import Transition from "../data/Transition";
|
||||
import UnitBase, { UnitColor } from "./UnitBase";
|
||||
import UnitStateMachine from "./UnitStateMachine";
|
||||
|
||||
const { ccclass, property } = cc._decorator;
|
||||
|
||||
/**
|
||||
* 状态节点
|
||||
*/
|
||||
@ccclass
|
||||
export default class UnitState extends UnitBase {
|
||||
private _state: State = null;
|
||||
public get state() { return this._state; }
|
||||
|
||||
/** 是否为AnyState */
|
||||
public get isAnyState() { return this._state.isAnyState; }
|
||||
|
||||
/**
|
||||
* 是否为默认状态
|
||||
* @override
|
||||
*/
|
||||
public get isDefault() { return this._isDefault; }
|
||||
public set isDefault(v: boolean) {
|
||||
if (this.isAnyState) {
|
||||
return;
|
||||
}
|
||||
this._isDefault = v;
|
||||
this.BgNode.color = this._isDefault ? UnitColor.DEFAULT : UnitColor.NORMAL;
|
||||
}
|
||||
|
||||
public onInit(upStateMachine: StateMachine, isAnyState: boolean = false) {
|
||||
this._state = new State(upStateMachine, isAnyState);
|
||||
if (isAnyState) {
|
||||
this.node.scale *= 0.8;
|
||||
this.NameLabel.node.scale *= 1 / 0.8;
|
||||
this.BgNode.color = UnitColor.ANY_STATE;
|
||||
this.NameLabel.string = 'AnyState';
|
||||
} else {
|
||||
this.NameLabel.string = this._state.name;
|
||||
}
|
||||
}
|
||||
|
||||
public initByState(state: State) {
|
||||
this._state = state;
|
||||
this.NameLabel.string = this._state.name;
|
||||
this.node.position = state.position
|
||||
}
|
||||
|
||||
protected onLoad() {
|
||||
Events.targetOn(this);
|
||||
}
|
||||
|
||||
protected onDestroy() {
|
||||
Events.targetOff(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加Transition
|
||||
* @override
|
||||
*/
|
||||
public addTransition(toUnit: UnitBase, toState: State) {
|
||||
let transition = this.state.addTransition(toState);
|
||||
Events.emit(EventName.TRANSITION_ADD, this, toUnit, transition);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取此节点到目标节点的所有Transition,不传参则返回所有从此节点出发的Transition
|
||||
* @override
|
||||
* @param toUnit 目标节点
|
||||
*/
|
||||
public getTransitions(toUnit: UnitBase = null): Transition[] {
|
||||
if (toUnit instanceof UnitState) {
|
||||
return this.state.getTransitions(toUnit.state);
|
||||
} else if (toUnit instanceof UnitStateMachine) {
|
||||
return this.state.getTransitions(toUnit.stateMachine, this._state.upStateMachine);
|
||||
} else {
|
||||
return this.state.getTransitions();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置layer层坐标系下坐标
|
||||
* @override
|
||||
*/
|
||||
public setPos(x: number | cc.Vec2 | cc.Vec3, y: number = 0) {
|
||||
let pos: cc.Vec2 = super.setPos(x, y);
|
||||
if (!this.state.position.equals(pos)) {
|
||||
this.state.setPosition(pos);
|
||||
if (this.isAnyState) {
|
||||
Events.emit(EventName.ANY_STATE_MOVE, pos);
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
@preloadEvent(EventName.STATE_NAME_CHANGED)
|
||||
private onEventStateNameChanged(state: State) {
|
||||
if (this.state !== state) {
|
||||
return;
|
||||
}
|
||||
this.NameLabel.string = state.name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "930040b8-2275-47ce-b7e0-3161308cfc6f",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
||||
92
animator-editor/assets/script/editor/fsm/UnitStateMachine.ts
Normal file
92
animator-editor/assets/script/editor/fsm/UnitStateMachine.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import Events, { EventName, preloadEvent } from "../../common/util/Events";
|
||||
import StateMachine from "../data/StateMachine";
|
||||
import Transition from "../data/Transition";
|
||||
import UnitBase, { UnitColor } from "./UnitBase";
|
||||
import UnitState from "./UnitState";
|
||||
|
||||
const { ccclass, property } = cc._decorator;
|
||||
|
||||
/**
|
||||
* 状态机节点
|
||||
*/
|
||||
@ccclass
|
||||
export default class UnitStateMachine extends UnitBase {
|
||||
private _stateMachine: StateMachine = null;
|
||||
public get stateMachine() { return this._stateMachine; }
|
||||
|
||||
private _isUp: boolean = false;
|
||||
/** 是否为当前状态机视图的父状态机节点 */
|
||||
public get isUp() { return this._isUp; }
|
||||
public set isUp(v: boolean) {
|
||||
this._isUp = v;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为默认状态
|
||||
* @override
|
||||
*/
|
||||
public get isDefault() { return this._isDefault; }
|
||||
public set isDefault(v: boolean) {
|
||||
this._isDefault = v;
|
||||
this.BgNode.color = this._isDefault ? UnitColor.DEFAULT : UnitColor.NORMAL;
|
||||
}
|
||||
|
||||
public onInit(upStateMachine: StateMachine) {
|
||||
this._stateMachine = new StateMachine(upStateMachine);
|
||||
this.NameLabel.string = `${this.isUp ? '(up)' : ''}${this._stateMachine.name}`;
|
||||
}
|
||||
|
||||
public initByStateMachine(stateMachine: StateMachine, upPos: cc.Vec2 = null) {
|
||||
this._stateMachine = stateMachine;
|
||||
this.isUp = !!upPos;
|
||||
this.NameLabel.string = `${this.isUp ? '(up)' : ''}${this._stateMachine.name}`;
|
||||
this.node.position = this.isUp ? upPos : stateMachine.position;
|
||||
}
|
||||
|
||||
protected onLoad() {
|
||||
Events.targetOn(this);
|
||||
}
|
||||
|
||||
protected onDestroy() {
|
||||
Events.targetOff(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取此节点到目标节点的所有Transition
|
||||
* @override
|
||||
* @param toUnit 目标节点
|
||||
*/
|
||||
public getTransitions(toUnit: UnitBase = null): Transition[] {
|
||||
if (toUnit instanceof UnitState) {
|
||||
return this.stateMachine.getTransitions(toUnit.state);
|
||||
} else if (toUnit instanceof UnitStateMachine) {
|
||||
return this.stateMachine.getTransitions(toUnit.stateMachine);
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置layer层坐标系下坐标
|
||||
* @override
|
||||
*/
|
||||
public setPos(x: number | cc.Vec2 | cc.Vec3, y: number = 0) {
|
||||
let pos: cc.Vec2 = super.setPos(x, y);
|
||||
if (!this.stateMachine.position.equals(pos)) {
|
||||
if (this.isUp) {
|
||||
Events.emit(EventName.UP_STATE_MACHINE_MOVE, pos);
|
||||
} else {
|
||||
this.stateMachine.setPosition(pos);
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
@preloadEvent(EventName.STATE_MACHINE_NAME_CHANGED)
|
||||
private onEventStateNameChanged(stateMachine: StateMachine) {
|
||||
if (this.stateMachine !== stateMachine) {
|
||||
return;
|
||||
}
|
||||
this.NameLabel.string = `${this.isUp ? '(up)' : ''}${this.stateMachine.name}`;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "f37b5690-9da0-4141-ae3f-88548e459831",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
||||
Reference in New Issue
Block a user