init
This commit is contained in:
7
animator-editor/assets/script/common/cmpt.meta
Normal file
7
animator-editor/assets/script/common/cmpt.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"ver": "1.0.1",
|
||||
"uuid": "4d50adb5-7ad5-496a-bfdc-4d59f1630bab",
|
||||
"isSubpackage": false,
|
||||
"subpackageName": "",
|
||||
"subMetas": {}
|
||||
}
|
24
animator-editor/assets/script/common/cmpt/CanvasAdapt.ts
Normal file
24
animator-editor/assets/script/common/cmpt/CanvasAdapt.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
const { ccclass, property } = cc._decorator;
|
||||
|
||||
@ccclass
|
||||
export default class CanvasAdapt extends cc.Component {
|
||||
protected onLoad() {
|
||||
this.adapt();
|
||||
// 仅web有效
|
||||
cc.view.setResizeCallback(() => {
|
||||
this.adapt();
|
||||
});
|
||||
}
|
||||
|
||||
private adapt() {
|
||||
let resolutionRatio = cc.Canvas.instance.designResolution.width / cc.Canvas.instance.designResolution.height;
|
||||
let ratio = cc.winSize.width / cc.winSize.height;
|
||||
if (ratio > resolutionRatio) {
|
||||
cc.Canvas.instance.fitHeight = true;
|
||||
cc.Canvas.instance.fitWidth = false;
|
||||
} else {
|
||||
cc.Canvas.instance.fitHeight = false;
|
||||
cc.Canvas.instance.fitWidth = true;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "75034da7-93d7-420e-b1e7-aabae21a607e",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
36
animator-editor/assets/script/common/cmpt/DragItem.ts
Normal file
36
animator-editor/assets/script/common/cmpt/DragItem.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
const { ccclass, property } = cc._decorator;
|
||||
|
||||
/** 移动速度 px/s */
|
||||
const MOVE_SPEED = 200;
|
||||
|
||||
/**
|
||||
* 用于拖拽排序的元素
|
||||
*/
|
||||
@ccclass
|
||||
export default class DragItem extends cc.Component {
|
||||
/** 触摸开始时的boundingbox */
|
||||
private _startRect: cc.Rect = null;
|
||||
public get startRect() { return this._startRect; }
|
||||
|
||||
/** 移动动画的目标下标 */
|
||||
private _toIdx: number = 0;
|
||||
|
||||
public onInit(idx: number) {
|
||||
this._toIdx = idx;
|
||||
this._startRect = this.node.getBoundingBox();
|
||||
}
|
||||
|
||||
public moveTo(toIdx: number, toY: number) {
|
||||
if (toIdx === this._toIdx) {
|
||||
return;
|
||||
}
|
||||
this._toIdx = toIdx;
|
||||
this.node.stopAllActions();
|
||||
let moveTo = cc.moveTo(Math.abs(this.node.y - toY) / MOVE_SPEED, cc.v2(0, toY));
|
||||
this.node.runAction(moveTo);
|
||||
}
|
||||
|
||||
public stop() {
|
||||
this.node.stopAllActions();
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "472003c1-2fb4-444f-a4cb-af3c1a70e9c1",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
184
animator-editor/assets/script/common/cmpt/DragList.ts
Normal file
184
animator-editor/assets/script/common/cmpt/DragList.ts
Normal file
@@ -0,0 +1,184 @@
|
||||
import Tool from "../util/Tool";
|
||||
import DragItem from "./DragItem";
|
||||
|
||||
const { ccclass, property } = cc._decorator;
|
||||
|
||||
/**
|
||||
* 拖拽排序列表
|
||||
*/
|
||||
@ccclass
|
||||
export default class DragList extends cc.Component {
|
||||
/** 进行拖拽操作的元素下标 */
|
||||
private _dragIdx: number = -1;
|
||||
/** 所有元素 */
|
||||
private _items: DragItem[] = [];
|
||||
|
||||
/**
|
||||
* 拖拽回调
|
||||
* @param dragIdx 拖拽元素初始下标
|
||||
* @param toIdx 拖拽元素完成拖拽后所在的下标
|
||||
*/
|
||||
private _dragCall: (dragIdx: number, toIdx: number) => void = null;
|
||||
/** 调用拖拽回调传入的this对象 */
|
||||
private _target: any = null;
|
||||
|
||||
private _layout: cc.Layout = null;
|
||||
/** 元素容器 */
|
||||
public get layout() {
|
||||
if (!this._layout) {
|
||||
this._layout = this.getComponent(cc.Layout);
|
||||
}
|
||||
return this._layout;
|
||||
}
|
||||
|
||||
/** 拖拽开关 */
|
||||
public canDrag: boolean = true;
|
||||
|
||||
protected onLoad() {
|
||||
this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
|
||||
this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
|
||||
this.node.on(cc.Node.EventType.TOUCH_END, this.onTouchEnd, this);
|
||||
this.node.on(cc.Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this);
|
||||
}
|
||||
|
||||
private onTouchStart(event: cc.Event.EventTouch) {
|
||||
if (!this.canDrag || this.node.childrenCount <= 1) {
|
||||
this._dragIdx = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
let pos = this.node.convertToNodeSpaceAR(event.getLocation());
|
||||
this._dragIdx = this.getItemIdx(pos);
|
||||
if (this._dragIdx < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.layout.enabled = false;
|
||||
this._items = [];
|
||||
this.node.children.forEach((e: cc.Node, idx: number) => {
|
||||
let item = e.getComponent(DragItem);
|
||||
if (!item) {
|
||||
item = e.addComponent(DragItem);
|
||||
}
|
||||
item.onInit(idx);
|
||||
this._items.push(item);
|
||||
});
|
||||
this._items[this._dragIdx].node.setSiblingIndex(this.node.childrenCount - 1);
|
||||
}
|
||||
|
||||
private onTouchMove(event: cc.Event.EventTouch) {
|
||||
if (this._dragIdx < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let pos = this.node.convertToNodeSpaceAR(event.getLocation());
|
||||
// 进行拖拽操作
|
||||
let yMax = this._items[0].startRect.center.y;
|
||||
let yMin = this._items[this._items.length - 1].startRect.center.y;
|
||||
this._items[this._dragIdx].node.y = cc.misc.clampf(pos.y, yMin, yMax);
|
||||
|
||||
let curIdx = this.getCurIdx(pos);
|
||||
if (curIdx < this._dragIdx) {
|
||||
this._items.forEach((item: DragItem, idx: number) => {
|
||||
if (idx === this._dragIdx) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Tool.inRange(curIdx, this._dragIdx - 1, idx)) {
|
||||
item.moveTo(idx + 1, this._items[idx + 1].startRect.center.y);
|
||||
} else {
|
||||
item.moveTo(idx, this._items[idx].startRect.center.y);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this._items.forEach((item: DragItem, idx: number) => {
|
||||
if (idx === this._dragIdx) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Tool.inRange(this._dragIdx + 1, curIdx, idx)) {
|
||||
item.moveTo(idx - 1, this._items[idx - 1].startRect.center.y);
|
||||
} else {
|
||||
item.moveTo(idx, this._items[idx].startRect.center.y);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private onTouchEnd(event: cc.Event.EventTouch) {
|
||||
if (this._dragIdx < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let pos = this.node.convertToNodeSpaceAR(event.getLocation());
|
||||
// 结束拖拽操作
|
||||
let curIdx = this.getCurIdx(pos);
|
||||
this._items[this._dragIdx].node.setSiblingIndex(curIdx);
|
||||
this._items.forEach((item: DragItem) => {
|
||||
item.stop();
|
||||
});
|
||||
|
||||
// 触发回调
|
||||
if (curIdx !== this._dragIdx && this._dragCall) {
|
||||
if (this._target)
|
||||
this._dragCall.call(this._target, this._dragIdx, curIdx);
|
||||
else
|
||||
this._dragCall(this._dragIdx, curIdx);
|
||||
}
|
||||
|
||||
// 重置
|
||||
this.layout.enabled = true;
|
||||
this.layout.updateLayout();
|
||||
this._dragIdx = -1;
|
||||
this._items = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取选中的元素下标
|
||||
*/
|
||||
private getItemIdx(pos: cc.Vec2) {
|
||||
for (let i = 0; i < this.node.childrenCount; i++) {
|
||||
let item = this.node.children[i];
|
||||
if (item.getBoundingBox().contains(pos)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据坐标获取当前移动到哪个下标的位置
|
||||
*/
|
||||
private getCurIdx(pos: cc.Vec2) {
|
||||
let yMax = this._items[0].startRect.center.y;
|
||||
let yMin = this._items[this._items.length - 1].startRect.center.y;
|
||||
if (pos.y >= yMax) {
|
||||
return 0;
|
||||
} else if (pos.y <= yMin) {
|
||||
return this._items.length - 1;
|
||||
}
|
||||
|
||||
let idx: number = 0;
|
||||
let minDis: number = Math.abs(this._items[0].startRect.center.y - pos.y);
|
||||
for (let i = 1; i < this._items.length; i++) {
|
||||
let item = this._items[i];
|
||||
let dis = Math.abs(item.startRect.center.y - pos.y);
|
||||
if (dis < minDis) {
|
||||
idx = i;
|
||||
minDis = dis;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册拖拽回调
|
||||
*/
|
||||
public setDragCall(call: (dragIdx: number, toIdx: number) => void, target: any) {
|
||||
this._dragCall = call;
|
||||
this._target = target;
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "5b5cd3c9-8509-4ab7-82d7-50cc0d99ffe2",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
72
animator-editor/assets/script/common/cmpt/ResizeArea.ts
Normal file
72
animator-editor/assets/script/common/cmpt/ResizeArea.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import Events, { EventName } from "../util/Events";
|
||||
|
||||
const { ccclass, property } = cc._decorator;
|
||||
|
||||
/**
|
||||
* 鼠标拉伸调节节点大小组件
|
||||
*/
|
||||
@ccclass
|
||||
export default class ResizeArea extends cc.Component {
|
||||
@property(cc.Widget) Target: cc.Widget = null;
|
||||
@property(cc.Vec2) Limit: cc.Vec2 = cc.v2();
|
||||
@property({ tooltip: CC_DEV && '节点对齐的是否为左侧' }) isLeft: boolean = true;
|
||||
|
||||
private _canvas: HTMLElement = null;
|
||||
private _startPos: cc.Vec2 = null;
|
||||
private _startWidth: number = 0;
|
||||
private _updateDirty: boolean = false;
|
||||
|
||||
protected onLoad() {
|
||||
this._canvas = document.getElementById('GameCanvas');
|
||||
|
||||
this.node.on(cc.Node.EventType.TOUCH_START, this.onTouchStart, this);
|
||||
this.node.on(cc.Node.EventType.TOUCH_MOVE, this.onTouchMove, this);
|
||||
|
||||
this.node.on(cc.Node.EventType.MOUSE_ENTER, this.onMouseEnter, this);
|
||||
this.node.on(cc.Node.EventType.MOUSE_LEAVE, this.onMouseLeave, this);
|
||||
}
|
||||
|
||||
protected lateUpdate() {
|
||||
if (!this._updateDirty) {
|
||||
return;
|
||||
}
|
||||
this._updateDirty = false;
|
||||
this.Target.left = 0;
|
||||
this.Target.right = 0;
|
||||
this.Target.updateAlignment();
|
||||
|
||||
Events.emit(EventName.RESIZE, this.Target.node);
|
||||
this.updateWidget(this.Target.node);
|
||||
}
|
||||
|
||||
private onTouchStart(event: cc.Event.EventTouch) {
|
||||
this._canvas.style.cursor = 'w-resize';
|
||||
this._startPos = event.getLocation();
|
||||
this._startWidth = this.Target.node.width;
|
||||
}
|
||||
|
||||
private onTouchMove(event: cc.Event.EventTouch) {
|
||||
let delt = event.getLocation().x - this._startPos.x;
|
||||
if (!this.isLeft) {
|
||||
delt = -delt;
|
||||
}
|
||||
this.Target.node.width = cc.misc.clampf(this._startWidth + delt, this.Limit.x, this.Limit.y);
|
||||
this._updateDirty = true;
|
||||
}
|
||||
|
||||
private onMouseEnter(event: cc.Event.EventMouse) {
|
||||
this._canvas.style.cursor = 'w-resize';
|
||||
}
|
||||
|
||||
private onMouseLeave(event: cc.Event.EventMouse) {
|
||||
this._canvas.style.cursor = 'default ';
|
||||
}
|
||||
|
||||
private updateWidget(node: cc.Node) {
|
||||
node.children.forEach((c) => {
|
||||
let widget = c.getComponent(cc.Widget);
|
||||
widget && widget.updateAlignment();
|
||||
this.updateWidget(c);
|
||||
});
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "ea7dfc04-311b-4106-ac76-07793dca50ae",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
7
animator-editor/assets/script/common/util.meta
Normal file
7
animator-editor/assets/script/common/util.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"ver": "1.0.1",
|
||||
"uuid": "98542223-77d4-420b-9a90-26bc5ab0b531",
|
||||
"isSubpackage": false,
|
||||
"subpackageName": "",
|
||||
"subMetas": {}
|
||||
}
|
242
animator-editor/assets/script/common/util/Events.ts
Normal file
242
animator-editor/assets/script/common/util/Events.ts
Normal file
@@ -0,0 +1,242 @@
|
||||
/**
|
||||
* 事件名
|
||||
*/
|
||||
export enum EventName {
|
||||
/** 调节节点大小 */
|
||||
RESIZE,
|
||||
|
||||
/** 删除参数 */
|
||||
PARAM_DELETE,
|
||||
/** 参数名更改 */
|
||||
PARAM_NAME_CHANGED,
|
||||
/** 选中ParamItem */
|
||||
PARAM_SELECT,
|
||||
|
||||
/** 设置状态机视图的显示 */
|
||||
SET_CUR_STATE_MACHINE,
|
||||
|
||||
/** 状态名更改 */
|
||||
STATE_NAME_CHANGED,
|
||||
/** AnyState改变坐标 */
|
||||
ANY_STATE_MOVE,
|
||||
/** 状态机名更改 */
|
||||
STATE_MACHINE_NAME_CHANGED,
|
||||
/** 父状态机节点改变坐标 */
|
||||
UP_STATE_MACHINE_MOVE,
|
||||
|
||||
/** 选择连线连向子状态机内部的状态 */
|
||||
LINE_TO_MACHINE_STATE,
|
||||
/** 删除line */
|
||||
LINE_DELETE,
|
||||
|
||||
/** 新增transition */
|
||||
TRANSITION_ADD,
|
||||
/** 删除transition */
|
||||
TRANSITION_DELETE,
|
||||
/** 点击按钮选中TransitionItem */
|
||||
TRANSITION_SELECT,
|
||||
/** 点击按钮选中ConditionItem */
|
||||
CONDITION_SELECT,
|
||||
/** 选中multiplier参数 */
|
||||
MULTIPLIER_SELECT,
|
||||
|
||||
/** 隐藏inspector显示的内容 */
|
||||
INSPECTOR_HIDE,
|
||||
/** 显示unit信息 */
|
||||
INSPECTOR_SHOW_UNIT,
|
||||
/** 显示line信息 */
|
||||
INSPECTOR_SHOW_LINE,
|
||||
|
||||
/** 关闭菜单层 */
|
||||
CLOSE_MENU,
|
||||
/** 显示状态机界面右键菜单 */
|
||||
SHOW_RIGHT_MENU,
|
||||
/** 显示连线目标状态机内部所有状态选择界面 */
|
||||
SHOW_LINE_TO_List,
|
||||
/** 显示添加参数时选择界面 */
|
||||
SHOW_PARAM_ADD,
|
||||
/** 显示condition的参数选择界面 */
|
||||
SHOW_PARAM_SELECT,
|
||||
/** 显示condition的logic选项 */
|
||||
SHOW_LOGIC,
|
||||
/** 显示multiplier选择界面 */
|
||||
SHOW_MULTIPLIER,
|
||||
};
|
||||
|
||||
/**
|
||||
* 非静态成员函数装饰器,用于预先载入待注册的事件,配合targetOn使用
|
||||
* @param event 事件名
|
||||
*/
|
||||
export function preloadEvent(event: EventName) {
|
||||
return function (target: any, funcName: string, desc: PropertyDescriptor) {
|
||||
let arr = Events.classMap.get(target.constructor);
|
||||
if (arr === undefined) {
|
||||
arr = [];
|
||||
Events.classMap.set(target.constructor, arr);
|
||||
} else {
|
||||
let find = arr.find((e) => {
|
||||
return e.event === event && e.funcName === funcName;
|
||||
});
|
||||
if (find) {
|
||||
cc.error(`event: ${EventName[event]} 重复载入`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
arr.push({
|
||||
event: event,
|
||||
funcName: funcName
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听函数类型
|
||||
*/
|
||||
type Listener = (arg: any) => void;
|
||||
|
||||
/**
|
||||
* 事件收发管理类
|
||||
*/
|
||||
export default class Events {
|
||||
/**
|
||||
* 存储监听事件、监听函数与监听对象
|
||||
*/
|
||||
private static _eventsMap: Map<EventName, Map<Object, Listener[]>> = new Map();
|
||||
|
||||
/**
|
||||
* 存储构造函数、监听事件、监听函数名,用于实例化时注册事件
|
||||
*/
|
||||
public static classMap: Map<Function, Array<{ event: EventName, funcName: string }>> = new Map();
|
||||
|
||||
/**
|
||||
* 注册与target构造函数预先绑定的所有事件
|
||||
* @param target 注册目标
|
||||
* @param onSuper 是否注册父类成员函数上绑定的事件
|
||||
*/
|
||||
public static targetOn(target: Object, onSuper: boolean = true) {
|
||||
if (onSuper) {
|
||||
this.classMap.forEach((value: Array<{ event: EventName, funcName: string }>, key: Function) => {
|
||||
if (target instanceof key) {
|
||||
value.forEach((e) => {
|
||||
this.on(e.event, target[e.funcName], target);
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
let arr = this.classMap.get(target.constructor);
|
||||
if (arr) {
|
||||
arr.forEach((e) => {
|
||||
this.on(e.event, target[e.funcName], target);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册事件
|
||||
* @param event 事件名
|
||||
* @param listener 处理事件的监听函数
|
||||
* @param target 注册目标
|
||||
*/
|
||||
public static on(event: EventName, listener: Listener, target: Object) {
|
||||
if (!listener || !target) {
|
||||
cc.error(`event: ${EventName[event]} listener或target不能为空`);
|
||||
return;
|
||||
}
|
||||
|
||||
let map: Map<Object, Listener[]> = this._eventsMap.get(event);
|
||||
let list: Listener[] = [];
|
||||
if (map === undefined) {
|
||||
map = new Map();
|
||||
map.set(target, list);
|
||||
this._eventsMap.set(event, map);
|
||||
} else {
|
||||
list = map.get(target);
|
||||
if (list === undefined) {
|
||||
list = [];
|
||||
map.set(target, list);
|
||||
} else {
|
||||
let result = list.find((e) => { return e === listener });
|
||||
if (result) {
|
||||
cc.error(`event: ${EventName[event]} 重复注册`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list.push(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除事件
|
||||
* @param event 事件名
|
||||
* @param listener 处理事件的监听函数
|
||||
* @param target 注册目标
|
||||
*/
|
||||
public static off(event: EventName, listener: Listener, target: Object) {
|
||||
if (!listener || !target) {
|
||||
cc.error(`event: ${EventName[event]} listener或target不能为空`);
|
||||
return;
|
||||
}
|
||||
|
||||
let map: Map<Object, Listener[]> = this._eventsMap.get(event);
|
||||
if (map === undefined) {
|
||||
cc.error(`event: ${EventName[event]} 未注册该事件`);
|
||||
return;
|
||||
}
|
||||
|
||||
let list: Listener[] = map.get(target);
|
||||
if (list === undefined) {
|
||||
cc.error(`event: ${EventName[event]} target上未注册该事件`);
|
||||
return;
|
||||
}
|
||||
|
||||
let index = list.findIndex((e) => { return e === listener; });
|
||||
if (index < 0) {
|
||||
cc.error(`event: ${EventName[event]} target上未以该listener注册该事件`);
|
||||
return;
|
||||
}
|
||||
|
||||
list.splice(index, 1);
|
||||
if (list.length <= 0) {
|
||||
map.delete(target);
|
||||
map.size <= 0 && this._eventsMap.delete(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除target上注册的所有事件
|
||||
* @param target 注册目标
|
||||
*/
|
||||
public static targetOff(target: Object) {
|
||||
if (!target) {
|
||||
cc.error(`event: ${target} target不能为空`);
|
||||
return;
|
||||
}
|
||||
|
||||
this._eventsMap.forEach((map, event) => {
|
||||
map.delete(target);
|
||||
map.size <= 0 && this._eventsMap.delete(event);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 派发事件
|
||||
* @param event 事件名
|
||||
* @param args 事件参数
|
||||
*/
|
||||
public static emit(event: EventName, ...args: any[]) {
|
||||
let map: Map<Object, Listener[]> = this._eventsMap.get(event);
|
||||
if (map === undefined) {
|
||||
cc.warn(`event: ${EventName[event]} 未注册该事件`);
|
||||
return;
|
||||
}
|
||||
|
||||
map.forEach((list, target) => {
|
||||
list.forEach((listener) => {
|
||||
listener.call(target, ...args);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
9
animator-editor/assets/script/common/util/Events.ts.meta
Normal file
9
animator-editor/assets/script/common/util/Events.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "438a264f-5181-4f14-8330-5b700ab8eac7",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
110
animator-editor/assets/script/common/util/RecyclePool.ts
Normal file
110
animator-editor/assets/script/common/util/RecyclePool.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* 用于使用节点池的节点所绑定脚本组件实现
|
||||
*/
|
||||
export interface RecycleNode {
|
||||
/**
|
||||
* 回收前调用
|
||||
*/
|
||||
unuse(): void;
|
||||
/**
|
||||
* 取出前调用
|
||||
*/
|
||||
reuse(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 节点池
|
||||
*/
|
||||
export default class RecyclePool {
|
||||
private static _poolMap: Map<{ prototype: cc.Component }, cc.Node[]> = new Map();
|
||||
|
||||
/**
|
||||
* 根据类型判断节点池中节点数量
|
||||
*/
|
||||
public static size(type: { prototype: cc.Component }): number {
|
||||
let list = this._poolMap.get(type);
|
||||
if (list === undefined) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return list.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据类型清空节点
|
||||
*/
|
||||
public static clear(type: { prototype: cc.Component }) {
|
||||
let list = this._poolMap.get(type);
|
||||
if (list === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
let count = list.length;
|
||||
for (let i = 0; i < count; ++i) {
|
||||
list[i].destroy();
|
||||
}
|
||||
list.length = 0;
|
||||
this._poolMap.delete(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空全部节点
|
||||
*/
|
||||
public static clearAll() {
|
||||
this._poolMap.forEach((list: cc.Node[]) => {
|
||||
list.forEach((node: cc.Node) => {
|
||||
node.destroy();
|
||||
});
|
||||
});
|
||||
this._poolMap.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据类型从节点池取出节点
|
||||
*/
|
||||
public static get(type: { prototype: cc.Component }): cc.Node {
|
||||
let list = this._poolMap.get(type);
|
||||
if (list === undefined || list.length <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let last = list.length - 1;
|
||||
let node = list[last];
|
||||
list.length = last;
|
||||
|
||||
// Invoke pool handler
|
||||
let handler: any = node.getComponent(type);
|
||||
if (handler && handler.reuse) {
|
||||
handler.reuse();
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据类型将节点放入节点池
|
||||
*/
|
||||
public static put(type: { prototype: cc.Component }, node: cc.Node) {
|
||||
if (!node) {
|
||||
cc.error(`[RecyclePool.put] error: 传入节点为空`);
|
||||
return;
|
||||
}
|
||||
|
||||
let list = this._poolMap.get(type);
|
||||
if (list === undefined) {
|
||||
list = [];
|
||||
this._poolMap.set(type, list);
|
||||
} else if (list.indexOf(node) !== -1) {
|
||||
cc.error(`[RecyclePool.put] error: 不可将节点重复放入节点池中`);
|
||||
return;
|
||||
}
|
||||
|
||||
node.removeFromParent(false);
|
||||
// Invoke pool handler
|
||||
let handler: any = node.getComponent(type);
|
||||
if (handler && handler.unuse) {
|
||||
handler.unuse();
|
||||
}
|
||||
|
||||
list.push(node);
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "2650e9f4-6f08-4845-bf8b-31afece7a66b",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
68
animator-editor/assets/script/common/util/Res.ts
Normal file
68
animator-editor/assets/script/common/util/Res.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 资源管理类
|
||||
*/
|
||||
export default class Res {
|
||||
/**
|
||||
* 资源缓存
|
||||
*/
|
||||
private static _cacheMap: Map<string, cc.Asset> = new Map();
|
||||
|
||||
/**
|
||||
* 获取已经预加载的资源。!!!调用前需确保资源已预加载
|
||||
* @param url 资源路径
|
||||
*/
|
||||
public static getLoaded(url: string): any {
|
||||
let asset = this._cacheMap.get(url);
|
||||
if (asset === undefined) {
|
||||
cc.error(`[Res.getLoaded] error: 资源未加载`);
|
||||
return null;
|
||||
}
|
||||
|
||||
return asset;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载resources文件夹下单个资源
|
||||
* @param url 资源路径
|
||||
* @param type 资源类型
|
||||
*/
|
||||
public static async load(url: string, type: typeof cc.Asset): Promise<any> {
|
||||
let asset = this._cacheMap.get(url);
|
||||
if (asset) {
|
||||
return asset;
|
||||
}
|
||||
|
||||
return await new Promise((resolve, reject) => {
|
||||
cc.loader.loadRes(url, type, (error: Error, resource: cc.Asset) => {
|
||||
if (error) {
|
||||
cc.error(`[Res.load] error: ${error}`);
|
||||
resolve(null);
|
||||
} else {
|
||||
this._cacheMap.set(url, resource);
|
||||
resolve(resource);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载resources文件夹下某个文件夹内全部资源
|
||||
* @param url 资源路径
|
||||
* @param type 资源类型
|
||||
*/
|
||||
public static async loadDir(url: string, type: typeof cc.Asset): Promise<any[]> {
|
||||
return await new Promise((resolve, reject) => {
|
||||
cc.loader.loadResDir(url, type, (error: Error, resource: any[], urls: string[]) => {
|
||||
if (error) {
|
||||
cc.error(`[Res.loadDir] error: ${error}`);
|
||||
resolve([]);
|
||||
} else {
|
||||
urls.forEach((v: string, i: number) => {
|
||||
this._cacheMap.set(v, resource[i]);
|
||||
});
|
||||
resolve(resource);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
9
animator-editor/assets/script/common/util/Res.ts.meta
Normal file
9
animator-editor/assets/script/common/util/Res.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "1d8423c7-71dd-417b-8df3-8b9c83e1496b",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
108
animator-editor/assets/script/common/util/Tool.ts
Normal file
108
animator-editor/assets/script/common/util/Tool.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* 工具类
|
||||
*/
|
||||
export default class Tool {
|
||||
/**
|
||||
* 随机返回数组中的某个元素
|
||||
* @param arr
|
||||
*/
|
||||
public static randArray<T>(arr: Array<T>): T {
|
||||
if (arr.length <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return arr[this.randInt(0, arr.length - 1)];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 [min, max] 区间的随机整数
|
||||
* @param min
|
||||
* @param max
|
||||
*/
|
||||
public static randInt(min: number, max: number) {
|
||||
min = Math.ceil(min);
|
||||
max = Math.floor(max);
|
||||
if (min >= max) {
|
||||
return max;
|
||||
}
|
||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 [min, max) 区间的随机浮点数
|
||||
* @param min
|
||||
* @param max
|
||||
*/
|
||||
public static randFloat(min: number, max: number) {
|
||||
if (min >= max) {
|
||||
return max;
|
||||
}
|
||||
return Math.random() * (max - min) + min;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回value是否在 [min, max] 区间内
|
||||
* @param min
|
||||
* @param max
|
||||
* @param value
|
||||
* @param includeEdge 是否包含边界值min和max,默认包含
|
||||
*/
|
||||
public static inRange(min: number, max: number, value: number, includeEdge: boolean = true) {
|
||||
return includeEdge ? value >= min && value <= max : value > min && value < max;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断数组中是否有某个元素
|
||||
*/
|
||||
public static arrayHas<T>(arr: T[], ele: T): boolean {
|
||||
let idx = arr.findIndex((e) => { return e === ele; });
|
||||
return idx >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据下标交换数组两个元素位置
|
||||
*/
|
||||
public static arraySwap<T>(arr: T[], idx1: number, idx2: number) {
|
||||
if (idx1 === idx2 || !this.inRange(0, arr.length - 1, idx1) || !this.inRange(0, arr.length - 1, idx2)) {
|
||||
return;
|
||||
}
|
||||
[arr[idx1], arr[idx2]] = [arr[idx2], arr[idx1]];
|
||||
}
|
||||
|
||||
/**
|
||||
* 将元素从fromIdx位置移到toIdx位置,其余元素相对位置不变
|
||||
*/
|
||||
public static arrayMove<T>(arr: T[], fromIdx: number, toIdx: number) {
|
||||
if (fromIdx === toIdx || !this.inRange(0, arr.length - 1, fromIdx) || !this.inRange(0, arr.length - 1, toIdx)) {
|
||||
return;
|
||||
}
|
||||
let from: T[] = arr.splice(fromIdx, 1);
|
||||
arr.splice(toIdx, 0, from[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加元素
|
||||
* @param canRepeat 是否可重复添加相同元素 默认false
|
||||
* @returns 是否确实执行了添加操作
|
||||
*/
|
||||
public static arrayAdd<T>(arr: T[], ele: T, canRepeat: boolean = false): boolean {
|
||||
if (!canRepeat && this.arrayHas(arr, ele)) {
|
||||
return false;
|
||||
}
|
||||
arr.push(ele);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除元素
|
||||
* @returns 是否确实执行了删除操作
|
||||
*/
|
||||
public static arrayDelete<T>(arr: T[], ele: T): boolean {
|
||||
let idx = arr.findIndex((e) => { return e === ele; });
|
||||
if (idx === -1) {
|
||||
return false;
|
||||
}
|
||||
arr.splice(idx, 1);
|
||||
return true
|
||||
}
|
||||
}
|
9
animator-editor/assets/script/common/util/Tool.ts.meta
Normal file
9
animator-editor/assets/script/common/util/Tool.ts.meta
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"ver": "1.0.5",
|
||||
"uuid": "8a83b733-dd4e-4b3d-aa1e-121f58ba4f88",
|
||||
"isPlugin": false,
|
||||
"loadPluginInWeb": true,
|
||||
"loadPluginInNative": true,
|
||||
"loadPluginInEditor": false,
|
||||
"subMetas": {}
|
||||
}
|
Reference in New Issue
Block a user