You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
646 lines
24 KiB
646 lines
24 KiB
import { _decorator, assetManager, builtinResMgr, Button, Component, error, EventHandler, EventTouch, ImageAsset, instantiate, isValid, IVec2Like, Label, Material, Node, RichText, screen, sp, Sprite, SpriteAtlas, SpriteFrame, Texture2D, Tween, tween, UIOpacity, UITransform, v3, Vec2, Vec3, view, warn, Widget } from "cc";
|
|
import StringUtils from "../ExUtils/StringUtils";
|
|
import ResLoad from "../ResUrl/ResLoad";
|
|
import Language from "../Language";
|
|
import { ESounds } from "../MesEvent/ESounds";
|
|
import { RichTextTypeData, RichText_Color, RichText_Size, RichText_Outline, RichText_b, RichText_i, RichText_u, IData, SoundType } from "../const/GameInterface";
|
|
import { Global } from "../Global";
|
|
import InstanceT from "../ExUtils/InstanceT";
|
|
import GDUtils from "./GDUtils";
|
|
import { EResUrls } from "../ResUrl/EResUrls";
|
|
|
|
@InstanceT.DecorateInstance()
|
|
class CNodeUtils {
|
|
/** 单例 */
|
|
public static readonly instance: CNodeUtils;
|
|
//#region 节点查找
|
|
getNodeEx(target: Node | Component, name: string, active: boolean) {
|
|
let tNode: Node = target instanceof Component ? target.node : target;
|
|
let arr: Node[] = [];
|
|
tNode.children.forEach(n => {
|
|
if (n.name == name && (!active || n.activeInHierarchy)) arr.push(n);
|
|
arr = arr.concat(this.getNodeEx(n, name, active));
|
|
})
|
|
return arr;
|
|
}
|
|
/**根据节点路径 寻找节点 */
|
|
getNode(target: Node | Component, ...url: any[]) {
|
|
let tNode: Node = target instanceof Component ? target.node : target;
|
|
for (let i in url) {
|
|
tNode = tNode.getChildByName(`${url[i]}`);
|
|
if (!tNode) {
|
|
ConsoleEx.Error(`查找错误,${url[i]}`)
|
|
return null;
|
|
}
|
|
}
|
|
return tNode;
|
|
}
|
|
//#endregion
|
|
|
|
//#region 节点组件查询
|
|
/**获取组件 不存在那么就添加 */
|
|
getOrAddComponent<T extends Component>(node: Node | Component, cla): any {
|
|
let temp = node.getComponent(cla);
|
|
if (!temp) {
|
|
temp = node.addComponent(cla);
|
|
}
|
|
return temp as T;
|
|
}
|
|
//#endregion
|
|
|
|
//#region 节点组件属性设置
|
|
|
|
/**设置节点透明度 */
|
|
public setOpacity(node: Node | Component, Opacity: number) {
|
|
const tClassPoxy: UIOpacity = this.getOrAddComponent(node, UIOpacity);
|
|
tClassPoxy.opacity = Opacity;
|
|
}
|
|
|
|
/**设置节点缩放 */
|
|
setScale(target: Node | Component, scale: number) {
|
|
const tNode: Node = target instanceof Component ? target.node : target;
|
|
tNode.setScale(scale, scale, scale);
|
|
}
|
|
|
|
/**设置节点显示 */
|
|
setActive(target: Node | Component, active: boolean, ADFlag: number = 0) {
|
|
const tNode: Node = target instanceof Component ? target.node : target;
|
|
if (tNode.active != active) {
|
|
tNode.active = active;
|
|
//ADFlag && active && TDAnalyticsMgr.ins.TrySendtrack(GEData.GEeventName.ad_show, { ad_id: ADFlag });
|
|
}
|
|
}
|
|
|
|
/**设置按钮是否禁用 */
|
|
setBtnInteractable(btn: Button, _interactable: boolean) {
|
|
btn.interactable = _interactable;
|
|
const tempSprite = btn.getComponent(Sprite)
|
|
if (tempSprite) {
|
|
tempSprite.grayscale = !_interactable;
|
|
}
|
|
}
|
|
|
|
/**缓动图片范围 */
|
|
TweenSpriteRange(node: Node | Sprite, fillRange: number, time: number = 0.2) {
|
|
const tSprite: Sprite = node instanceof Node ? node.getComponent(Sprite) : node;
|
|
if (time > 0) {
|
|
tween(tSprite).to(time, { fillRange: fillRange }).start();
|
|
} else {
|
|
tSprite.fillRange = fillRange;
|
|
}
|
|
}
|
|
|
|
/**设置数组节点 全部是否置灰 */
|
|
public setAllGray(node: Node[], isGray: boolean, exclude: Node[] = []) {
|
|
node.forEach(child => {
|
|
this.setChiladAllGray(child, isGray, exclude);
|
|
})
|
|
}
|
|
|
|
/**设置节点以及子节点 全部是否置灰 */
|
|
public setChiladAllGray(node: Node | Sprite, isGray: boolean, exclude: Node[] = []) {
|
|
const tNode: Node = node instanceof Sprite ? node.node : node;
|
|
const children = tNode.children;
|
|
children.forEach(child => {
|
|
if (!exclude.includes(child)) {
|
|
this.setChiladAllGray(child, isGray, exclude);
|
|
}
|
|
})
|
|
if (!exclude.includes(tNode)) {
|
|
this.setGray(tNode, isGray);
|
|
}
|
|
}
|
|
|
|
/**设置节点是否置灰 */
|
|
public setGray(node: Node | Sprite, isGray: boolean) {
|
|
const tSprite: Sprite = node instanceof Node ? node.getComponent(Sprite) : node;
|
|
if (tSprite) {
|
|
tSprite.grayscale = isGray;
|
|
} else {
|
|
const label = node.getComponent(Label);
|
|
if (label) {
|
|
if (!label["Org"]) { label["Org"] = label.material; }
|
|
if (isGray) {
|
|
label.material = builtinResMgr.get<Material>('ui-sprite-gray-material')
|
|
} else {
|
|
label.material = label["Org"];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* 更新label文字
|
|
* **/
|
|
public switchText(node: Node | Label, str: any, forceUpdate = false, isNum = false) {
|
|
if (!isValid(node)) {
|
|
warn('要更新的节点为空,str=' + str);
|
|
return;
|
|
}
|
|
const label: Label = node instanceof Node ? node.getComponent(Label) : node;
|
|
if (!label) { return; }
|
|
label.node.attr({ original: str });
|
|
label.string = isNum ? str : Language.getValue(str);
|
|
|
|
// if (label.useSystemFont) {
|
|
// label.font = AppLanguage.getFont()
|
|
// }
|
|
|
|
forceUpdate && label.updateRenderData();
|
|
}
|
|
|
|
/**
|
|
* 更新RichText文字
|
|
* **/
|
|
public switchRichText(node: Node | RichText, str: any, forceUpdate = false, isNum = false) {
|
|
if (!isValid(node)) {
|
|
warn('要更新的节点为空,str=' + str);
|
|
return;
|
|
}
|
|
const label: RichText = node instanceof Node ? node.getComponent(RichText) : node;
|
|
if (!label) { return; }
|
|
label.node.attr({ original: str });
|
|
label.string = isNum ? str : Language.getValue(str);
|
|
if (label.useSystemFont) {
|
|
//@ts-ignore
|
|
//label.font = AppLanguage.getFont()
|
|
}
|
|
forceUpdate && label["_updateRichTextStatus"]();
|
|
}
|
|
|
|
/**
|
|
* 更新label文字,文字颜色与品质相关
|
|
* **/
|
|
public switchTextByQuality(node: Node | Label, str: any, quality: number, forceUpdate = false, isNum = false) {
|
|
if (!isValid(node)) {
|
|
warn('要更新的节点为空,str=' + str);
|
|
return;
|
|
}
|
|
const label: Label = node instanceof Node ? node.getComponent(Label) : node;
|
|
if (!label) { return; }
|
|
label.color = label.color.fromHEX(GDUtils.GetQualityColorHEX(quality));
|
|
label.node.attr({ original: str });
|
|
label.string = isNum ? str : Language.getValue(str);
|
|
|
|
forceUpdate && label.updateRenderData();
|
|
}
|
|
|
|
// /**
|
|
// * 更新label文字,文字颜色与品质相关
|
|
// * **/
|
|
// public switchRichTextByQuality(node: Node | RichText, str: any, quality: number, forceUpdate = false, isNum = false) {
|
|
// if (!isValid(node)) {
|
|
// warn('要更新的节点为空,str=' + str);
|
|
// return;
|
|
// }
|
|
// const label: RichText = node instanceof Node ? node.getComponent(RichText) : node;
|
|
// if (!label) { return; }
|
|
// label.node.attr({ original: str });
|
|
// label.string = isNum ? str : Language.getValue(str);
|
|
// if (label.useSystemFont) {
|
|
// //@ts-ignore
|
|
// //label.font = AppLanguage.getFont()
|
|
// }
|
|
// forceUpdate && label["_updateRichTextStatus"]();
|
|
// }
|
|
|
|
/**数字文本缓动 */
|
|
TweenNumText(target: Node | Label, toNum: number, isConvert: boolean = true) {
|
|
if (!isValid(target)) {
|
|
warn('要更新的节点为空');
|
|
return;
|
|
}
|
|
const tNode: Node = target instanceof Node ? target : target.node;
|
|
Tween.stopAllByTarget(tNode);
|
|
if (tNode["CurNum"] != 0 && !tNode["CurNum"]) {
|
|
tNode["TargetNum"] = toNum;
|
|
tNode["CurNum"] = toNum;
|
|
}
|
|
tNode["CurNum"] = tNode["TargetNum"];
|
|
tNode["TargetNum"] = toNum;
|
|
let offsetNum = tNode["TargetNum"] - tNode["CurNum"];
|
|
if (offsetNum != 0) {
|
|
tween(tNode).update(0.3, (node: Node, ratio: number) => {
|
|
let tNum = tNode["CurNum"] + offsetNum * ratio;
|
|
this.switchText(node, isConvert ? StringUtils.HurtConvert(Math.floor(tNum)) : Math.floor(tNum));
|
|
}).start();
|
|
} else {
|
|
this.switchText(target, isConvert ? StringUtils.HurtConvert(Math.floor(tNode["CurNum"])) : Math.floor(tNode["CurNum"]));
|
|
}
|
|
}
|
|
|
|
addBtnLister(node: Node, callback: Function, target?: any, audio: SoundType = ESounds.So_click) {
|
|
node.off('click');
|
|
node.on('click', () => {
|
|
if (audio == ESounds.So_click) {
|
|
Global.Audio.playEffect(ESounds.So_click);
|
|
} else {
|
|
Global.Audio.playEffect(audio);
|
|
}
|
|
callback.call(target, node)
|
|
})
|
|
}
|
|
|
|
addEventHandler<T extends EventHandler>(node: Node, calssname = '', callFunc = '', customData = '') {
|
|
let event_handler = new Component.EventHandler();
|
|
event_handler.target = node;
|
|
event_handler.component = calssname;
|
|
event_handler.handler = callFunc;
|
|
event_handler.customEventData = customData;
|
|
return event_handler;
|
|
}
|
|
|
|
/**
|
|
* 添加button事件
|
|
* @param node
|
|
* @param callback
|
|
* @param target
|
|
* @param isAudio
|
|
*/
|
|
addBtnComponent(node: Node, callback: Function, target?: any, isAudio: SoundType = ESounds.So_click) {
|
|
if (!node.getComponent(Button)) {
|
|
let btn: Button = node.addComponent(Button);
|
|
btn.transition = Button.Transition.SCALE;
|
|
btn.duration = 0.1;
|
|
btn.target = node;
|
|
btn.zoomScale = 0.93;
|
|
}
|
|
this.addBtnLister(node, callback, target, isAudio);
|
|
}
|
|
addNoScaleBtnComponent(node: Node, callback: Function, target?: any, isAudio: SoundType = ESounds.So_click) {
|
|
if (!node.getComponent(Button)) {
|
|
let btn: Button = node.addComponent(Button);
|
|
btn.transition = Button.Transition.NONE;
|
|
btn.duration = 0.1;
|
|
btn.target = node;
|
|
btn.zoomScale = 0.93;
|
|
}
|
|
this.addBtnLister(node, callback, target, isAudio);
|
|
}
|
|
|
|
ClearBtnCommontEffect(node: Node) {
|
|
node.off('click');
|
|
}
|
|
|
|
/**添加按钮长按 */
|
|
addBtnLongpress(node: Node | Button, downCallBack: Function, upCallback: Function) {
|
|
let tNode = null;
|
|
if (node instanceof Node) {
|
|
tNode = node;
|
|
} else {
|
|
tNode = node.node;
|
|
}
|
|
tNode.off(Node.EventType.TOUCH_START);
|
|
tNode.off(Node.EventType.TOUCH_MOVE);
|
|
tNode.off(Node.EventType.TOUCH_END);
|
|
tNode.off(Node.EventType.TOUCH_CANCEL);
|
|
|
|
let isDown = false;
|
|
tNode.on(Node.EventType.TOUCH_START, (event: EventTouch) => {
|
|
isDown = true;
|
|
downCallBack && downCallBack(event);
|
|
}, this)
|
|
|
|
tNode.on(Node.EventType.TOUCH_END, (event: EventTouch) => {
|
|
isDown = false;
|
|
upCallback && upCallback(event);
|
|
}, this)
|
|
|
|
tNode.on(Node.EventType.TOUCH_CANCEL, (event: EventTouch) => {
|
|
isDown = false;
|
|
upCallback && upCallback(event);
|
|
}, this)
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
* @param node
|
|
* @param callback
|
|
* @param target
|
|
*/
|
|
addMoveComponent(node: Node, callback: Function, target?: any, TiggerFuntion?: Function) {
|
|
node.off(Node.EventType.TOUCH_START);
|
|
node.off(Node.EventType.TOUCH_MOVE);
|
|
node.off(Node.EventType.TOUCH_END);
|
|
let isMove = false;
|
|
node.on(Node.EventType.TOUCH_START, (event: EventTouch) => {
|
|
isMove = false;
|
|
TiggerFuntion && TiggerFuntion(true);
|
|
}, this)
|
|
node.on(Node.EventType.TOUCH_MOVE, (event) => {
|
|
let touch = event.touch;
|
|
let deltaMove = touch.getLocation().sub(touch.getStartLocation());
|
|
if (deltaMove.mag() > 10) {
|
|
isMove = true;
|
|
}
|
|
}, this)
|
|
node.on(Node.EventType.TOUCH_END, (event) => {
|
|
TiggerFuntion && TiggerFuntion(false);
|
|
!isMove && callback.call(target, node, event);
|
|
}, this)
|
|
}
|
|
|
|
/**富文本处理 列表*/
|
|
ContainRichtTextByList(value: string, list: RichTextTypeData[]): string {
|
|
let tVa: string = value;
|
|
for (let i = 0; i < list.length; i++) {
|
|
const tData = list[i];
|
|
tVa = this.ContainRichtText(tVa, tData);
|
|
}
|
|
return tVa;
|
|
}
|
|
|
|
/**富文本处理 */
|
|
ContainRichtText(value: string, data: RichTextTypeData): string {
|
|
if (data instanceof RichText_Color) {
|
|
return `<color=${data.color}>${value}</color>`;
|
|
} else if (data instanceof RichText_Size) {
|
|
return `<size=${data.size}>${value}</size>`
|
|
} else if (data instanceof RichText_Outline) {
|
|
return `<outline color=${data.oColor} width=${data.oSize}>${value}</outline>`
|
|
} else if (data instanceof RichText_b) {
|
|
return `<b>${value}</b>`;
|
|
} else if (data instanceof RichText_i) {
|
|
return `<i>${value}c</i>`;
|
|
}
|
|
else if (data instanceof RichText_u) {
|
|
return `<u>${value}</u>`;
|
|
}
|
|
}
|
|
|
|
/**添加富文本点击事件 */
|
|
AddRichTextClick(tagetNode: Node | RichText, CallBack: Function, functionName?: string) {
|
|
let tRichText: RichText = null;
|
|
if (tagetNode instanceof RichText) {
|
|
tRichText = tagetNode;
|
|
} else {
|
|
tRichText = tagetNode.getComponent(RichText)
|
|
}
|
|
if (!tRichText) {
|
|
error("添加富文本点击失败 该节点没有富文本组件");
|
|
return;
|
|
}
|
|
functionName = functionName ? functionName : CallBack.name;
|
|
functionName = functionName.replace("bound", "");
|
|
functionName = functionName.replace(" ", "");
|
|
tRichText[functionName] = CallBack;
|
|
}
|
|
|
|
SwitchSpine(node: Node | sp.Skeleton, file: string, bundleName: string,
|
|
animation: string | string[] = 'idle', isLoop: boolean = true, skin: string = 'default', back: Function = null) {
|
|
const spine: sp.Skeleton = node instanceof Node ? node.getComponent(sp.Skeleton) : node;
|
|
// const url = EResUrls.Spine(file);
|
|
ResLoad.Ins.Spine(file, bundleName, (err, skeletonData: sp.SkeletonData) => {
|
|
if (!isValid(spine)) {
|
|
warn('spine 被移除')
|
|
return;
|
|
}
|
|
if (err || !skeletonData) {
|
|
error('加载资源出错: ' + file);
|
|
return;
|
|
}
|
|
spine.skeletonData = skeletonData;
|
|
if (Array.isArray(animation)) {
|
|
spine.setAnimation(0, animation[0], animation.length == 1);
|
|
animation.length > 1 && spine.addAnimation(0, animation[1], isLoop);
|
|
} else {
|
|
spine.setAnimation(0, animation, isLoop);
|
|
}
|
|
skin && spine.setSkin(skin);
|
|
back && back();
|
|
})
|
|
}
|
|
|
|
SwitchTexture(file: string, node: Node | Sprite, bundleName: string, width: number = 0, back: Function = null) {
|
|
const spr: Sprite = node instanceof Node ? node.getComponent(Sprite) : node;
|
|
if (!bundleName) { ConsoleEx.Error("路径错误",) }
|
|
ResLoad.Ins.Sprite(file, bundleName, (err, spriteFrame: SpriteFrame) => {
|
|
if (!isValid(spr)) {
|
|
warn('Sprite 被移除')
|
|
return;
|
|
}
|
|
|
|
if (err || !spriteFrame) {
|
|
error('加载资源出错: ' + file);
|
|
return;
|
|
}
|
|
|
|
if (spr["MY_ADD"] && spr.spriteFrame) {
|
|
spr.spriteFrame.decRef()
|
|
}
|
|
spr.spriteFrame = spriteFrame;
|
|
if (!spr.spriteFrame) {
|
|
error('加载资源出错: ' + file);
|
|
}
|
|
spr.spriteFrame.addRef();
|
|
spr["MY_ADD"] = 1;
|
|
width && this.scaleNode(spr.node, width);
|
|
back && back();
|
|
})
|
|
}
|
|
|
|
SwitchTextureByAutoAtlas(file: string, atlas: string, node: Node | Sprite, bundleName: string, width: number = 0, back: Function = null) {
|
|
const spr: Sprite = node instanceof Node ? node.getComponent(Sprite) : node;
|
|
ResLoad.Ins.AutoAtlas(atlas, bundleName, (err, spriteFrame) => {
|
|
if (!isValid(spr)) {
|
|
warn('Sprite 被移除')
|
|
return;
|
|
}
|
|
if (err) {
|
|
error('加载资源出错: ' + atlas);
|
|
return;
|
|
}
|
|
file = file.replace("Texture/", "");
|
|
spr.spriteFrame = spriteFrame.getSpriteFrame(file);
|
|
width && this.scaleNode(spr.node, width);
|
|
back && back();
|
|
})
|
|
}
|
|
|
|
SwitchTextureByData(node: Node | Sprite, data: IData, width: number = 0, back: Function = null) {
|
|
const url = GDUtils.getUrl(data);
|
|
const bundle = GDUtils.getUBundle(data.type, data.id);
|
|
const Atlas = GDUtils.getAtlas(data.type);
|
|
if (Atlas) {
|
|
this.SwitchTextureByAutoAtlas(url, Atlas, node, bundle, width, back)
|
|
} else {
|
|
this.SwitchTexture(url, node, bundle, width, back);
|
|
}
|
|
}
|
|
/**加载远程图片 */
|
|
SwitchRomateTexture(file: string, node: Node | Sprite, width: number = 0, back: Function = null) {
|
|
if (!file.includes("http")) {
|
|
back && back();
|
|
ConsoleEx.Error("请检查链接:", file)
|
|
return;
|
|
}
|
|
let isHaveExt: boolean = file.includes(".png") || file.includes(".jpg");
|
|
const spr: Sprite = node instanceof Node ? node.getComponent(Sprite) : node;
|
|
let lamuda = (err, res: ImageAsset) => {
|
|
if (!isValid(spr)) {
|
|
warn('Sprite 被移除')
|
|
return;
|
|
}
|
|
if (err) {
|
|
error('加载资源出错: ' + file);
|
|
return;
|
|
}
|
|
const spriteFrame = new SpriteFrame();
|
|
const texture = new Texture2D();
|
|
texture.image = res;
|
|
spriteFrame.texture = texture;
|
|
spr.spriteFrame = spriteFrame;
|
|
width && this.scaleNode(spr.node, width);
|
|
back && back();
|
|
}
|
|
if (isHaveExt) {
|
|
assetManager.loadRemote<ImageAsset>(file, lamuda)
|
|
} else {
|
|
assetManager.loadRemote<ImageAsset>(file, { ext: '.png' }, lamuda)
|
|
}
|
|
}
|
|
|
|
|
|
scaleNode(target: Node | Component, width: number, height = 0) {
|
|
const tNode = target instanceof Node ? target : target.node;
|
|
if (isValid(tNode)) {
|
|
if (!height) {
|
|
height = width;
|
|
}
|
|
const wScale = width / tNode.getComponent(UITransform).width;
|
|
const hScale = height / tNode.getComponent(UITransform).height;
|
|
const sc = Math.min(wScale, hScale);
|
|
tNode.setScale(v3(sc, sc, sc))
|
|
}
|
|
}
|
|
|
|
scaleNodeW(target: Node | Component, width: number) {
|
|
const tNode = target instanceof Node ? target : target.node;
|
|
if (isValid(tNode)) {
|
|
const wScale = width / tNode.getComponent(UITransform).width;
|
|
tNode.setScale(v3(wScale, wScale, wScale))
|
|
}
|
|
}
|
|
|
|
scaleNodeH(target: Node | Component, height) {
|
|
const tNode = target instanceof Node ? target : target.node;
|
|
if (isValid(tNode)) {
|
|
const wScale = height / tNode.getComponent(UITransform).height;
|
|
tNode.setScale(v3(wScale, wScale, wScale))
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 二阶贝塞尔曲线 运动
|
|
* @param target
|
|
* @param {number} duration
|
|
* @param {} c1 起点坐标
|
|
* @param {} c2 控制点
|
|
* @param {Vec3} to 终点坐标
|
|
* @param opts
|
|
* @returns {any}
|
|
*/
|
|
bezierTo(target: Node, duration: number, c1: Vec2, c2: Vec2, to: Vec3, opts: any, Callback?: Function) {
|
|
opts = opts || Object.create(null);
|
|
/**
|
|
* @desc 二阶贝塞尔
|
|
* @param {number} t 当前百分比
|
|
* @param {} p1 起点坐标
|
|
* @param {} cp 控制点
|
|
* @param {} p2 终点坐标
|
|
* @returns {any}
|
|
*/
|
|
let twoBezier = (t: number, p1: Vec2, cp: Vec2, p2: Vec3) => {
|
|
let x = (1 - t) * (1 - t) * p1.x + 2 * t * (1 - t) * cp.x + t * t * p2.x;
|
|
let y = (1 - t) * (1 - t) * p1.y + 2 * t * (1 - t) * cp.y + t * t * p2.y;
|
|
return v3(x, y, 0);
|
|
};
|
|
opts.onUpdate = (arg: Vec3, ratio: number) => {
|
|
target.setPosition(twoBezier(ratio, c1, c2, to))
|
|
Callback && Callback();
|
|
};
|
|
return tween(target).to(duration, {}, opts);
|
|
}
|
|
|
|
/**
|
|
* 添加button事件
|
|
* @param node
|
|
* @param callback
|
|
* @param target
|
|
* @param isAudio
|
|
*/
|
|
addNodeTounch(node: Node, onMouseUp: Function, target?: any, onMouseEnter?: Function, onMouseMove?: Function, onMouseLeave?: Function, OnMoveDir?: Function) {
|
|
this.clearNodeTounch(node);
|
|
let isMove: boolean = false;
|
|
node.on(Node.EventType.TOUCH_START, (event: EventTouch) => {
|
|
onMouseEnter && onMouseEnter(event);
|
|
}, target);
|
|
node.on(Node.EventType.TOUCH_MOVE, (event: EventTouch) => {
|
|
let tempX = event.getStartLocation().x - event.getLocationX();
|
|
let tempY = event.getStartLocation().y - event.getLocationY();
|
|
let dirX = Math.abs(tempX);
|
|
let dirY = Math.abs(tempY);
|
|
if (dirX > 14 || dirY > 14) {
|
|
isMove = true;
|
|
OnMoveDir && OnMoveDir(event, tempX, tempY);
|
|
}
|
|
onMouseMove && onMouseMove(event);
|
|
}, target);
|
|
node.on(Node.EventType.TOUCH_END, (event) => {
|
|
onMouseUp && !isMove && onMouseUp(event);
|
|
isMove = false;
|
|
onMouseLeave && onMouseLeave(event);
|
|
}, target);
|
|
onMouseLeave && node.on(Node.EventType.TOUCH_CANCEL, onMouseLeave, target);
|
|
}
|
|
clearNodeTounch(node: Node) {
|
|
node.off(Node.EventType.TOUCH_START);
|
|
node.off(Node.EventType.TOUCH_MOVE);
|
|
node.off(Node.EventType.TOUCH_END);
|
|
node.off(Node.EventType.TOUCH_CANCEL);
|
|
}
|
|
|
|
//#endregion
|
|
|
|
setADWaitShow(btn_Reward: Node | Component) {
|
|
if (!window["tt"]) {
|
|
// this.SetNodeActive(btn_Reward, true)
|
|
// setTimeout(() => {
|
|
// if (isValid(btn_Reward)) {
|
|
// this.SetNodeActive(btn_Reward, true)
|
|
// }
|
|
// }, 1000)
|
|
}
|
|
}
|
|
|
|
GetPosRange(pos: Vec3, org: Node, Traget: Node, offset: IVec2Like) {
|
|
let tNode: Node = Traget instanceof Component ? Traget.node : Traget;
|
|
let tY = pos.y - offset.y - org.getComponent(UITransform).height / 2;
|
|
if (tY < (-tNode.getComponent(UITransform).height / 2)) {
|
|
tY = pos.y + offset.y;
|
|
} else {
|
|
tY = pos.y - offset.y;
|
|
}
|
|
let tX = pos.x;
|
|
tX = Math.max(-(tNode.getComponent(UITransform).width / 2 - org.getComponent(UITransform).width / 2) + 20, tX);
|
|
tX = Math.min(tNode.getComponent(UITransform).width / 2 - org.getComponent(UITransform).width / 2 - 20, tX);
|
|
return new Vec3(tX, tY, 0)
|
|
}
|
|
|
|
GetNodeInScreenRect(node: Node): { left: number, top: number, width: number, height: number } {
|
|
const rect = node.getComponent(UITransform)!.getBoundingBoxToWorld();
|
|
const dpi = screen.devicePixelRatio;
|
|
const scaleX = view.getScaleX();
|
|
const scaleY = view.getScaleY();
|
|
const left = (rect.x * scaleX) / dpi;
|
|
const top = (screen.windowSize.height - (rect.y + rect.height) * scaleY) / dpi;
|
|
const width = (rect.width * scaleX) / dpi;
|
|
const height = (rect.height * scaleY) / dpi;
|
|
return { left, top, width, height };
|
|
}
|
|
}
|
|
export default CNodeUtils.instance;
|
|
window["CNodeUtils"] = CNodeUtils.instance;
|