This commit is contained in:
YipLee
2021-01-19 22:30:12 +08:00
commit c4f716c8e9
165 changed files with 61216 additions and 0 deletions

View 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;
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "685739a3-7df5-4f61-99e1-efbf0175cf35",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View 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
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "323aebfe-14d1-4acd-8e95-b6085c8599dd",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View 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);
}
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "2aff73f9-2e11-422c-bcc4-c338379b1548",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View 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);
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "8366ea51-c189-47b4-ba38-2dd088175777",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View 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();
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "c7581de7-e34c-4d10-81a7-7cb05e82f531",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View 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;
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "de0ee56a-435e-4d63-b773-c33f0739a9f5",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View 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;
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "930040b8-2275-47ce-b7e0-3161308cfc6f",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}

View 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}`;
}
}

View File

@@ -0,0 +1,9 @@
{
"ver": "1.0.5",
"uuid": "f37b5690-9da0-4141-ae3f-88548e459831",
"isPlugin": false,
"loadPluginInWeb": true,
"loadPluginInNative": true,
"loadPluginInEditor": false,
"subMetas": {}
}