import { _decorator, BlockInputEvents, Component, EventTouch, Label, Layout, Node, ScrollView, tween, UITransform, v3, Vec2, Vec3 } from "cc"; import { EGlobalEvent } from "../MesEvent/EGlobalEvent"; import { CameraCon } from "../CComEx/CameraCon"; import MesMgr from "../MesEvent/MesMgr"; //#region 引导UI视图 // 该脚本主要处理 引导是遮罩移动与遮罩聚焦 设置按钮点击时的处理 //#endregion const { ccclass, property, menu } = _decorator; @ccclass @menu("引导/GuideUIView") export default class GuideUIView extends Component { @property(Node) mGuidNode: Node; @property(Node) mGuideMask: Node; @property(Node) mBlackMask: Node; @property(Node) mTounch: Node; @property(Node) mClickSpine: Node; @property(Node) mSay_tips: Node; @property(Label) mtips: Label; /**引导节点的原始父节点 */ private orgParent: Node = null; /**目标遮罩与 目标节点的间隙 */ readonly offw = 8; /**滑动组件列表 */ private mPrantScrollView: ScrollView[] = []; /**目标节点 */ private targetNode: Node; /**引导节点 事件屏蔽组件 */ private _GuidNodeBlockInputEvents: BlockInputEvents; /**引导节点 */ private _GuidNodeUITransform: UITransform; /*引导 遮罩节点 */ private _GuideMask: UITransform; /**辅助属性 */ private _pos: Vec3; /**点击次数 */ private _clickNum: number = 0; /**提示文本 */ private _des: string = null; /**节点宽度 */ private _GuideNodeWidth: number = 0; /**节点高度 */ private _GuideNodeHight: number = 0; /**按钮模式下的坐标偏移 */ private _btnOffset: Vec2 = new Vec2(0, 0); private static _ins: GuideUIView; public static get ins(): GuideUIView { if (!this._ins) { //director.getScene().addChild(ResLoad.GetRes(EResUrls.UIPrefabs("GuideCanvas"), EBundleName.Presets)); } return this._ins; } protected onLoad() { // MesMgr.on(EGlobalEvent.GUIDE_SHOW_FINGER, this.showFinger, this); MesMgr.on(EGlobalEvent.GUIDE_HIDE_FINGER, this.hideFinger, this); GuideUIView._ins = this.node.getComponent(GuideUIView); this.orgParent = this.mGuidNode.parent; this._init(); } protected onDestroy(): void { GuideUIView._ins = null; // MesMgr.off(EGlobalEvent.GUIDE_SHOW_FINGER, this.showFinger, this); MesMgr.off(EGlobalEvent.GUIDE_HIDE_FINGER, this.hideFinger, this); } /**初始化节点 */ private _init() { this._pos = new Vec3(); this._GuidNodeBlockInputEvents = this.mGuidNode.getComponent(BlockInputEvents); this._GuidNodeUITransform = this.mGuidNode.getComponent(UITransform); this._GuideMask = this.mGuideMask.getComponent(UITransform); let guidUITransform = this.mGuidNode.getComponent(UITransform); this._GuideNodeHight = guidUITransform.height; this._GuideNodeWidth = guidUITransform.width; this.mGuidNode.setSiblingIndex(100); this._hideGuideMask(); } /**强行显示手指 */ showFinger(parent:Node, tNode: Node, des:string = "", offsetx:number = 0, offsety:number = 0){ let pos = v3(); this._GuidNodeUITransform.convertToNodeSpaceAR(tNode.getWorldPosition(), pos); this.mClickSpine.setPosition(pos.x + offsetx, pos.y + offsety); this.mClickSpine.active = true; if(des.length > 0){ this._des = des; this.showDes(); } this.setGuideParent(parent); } /**强行隐藏手指 */ hideFinger(){ if(this.mClickSpine.active){ this.mClickSpine.active = false; this.mSay_tips.active = false; this.setGuideOrgParent(); } } /**设置引导节点的父节点,参数是兄弟节点 */ public setGuideParent(parent: Node) { // this.mGuidNode.removeFromParent(); parent.addChild(this.mGuidNode); } /**还原引导节点的父节点 */ public setGuideOrgParent() { // this.mGuidNode.removeFromParent(); this.orgParent.addChild(this.mGuidNode); } /**隐藏引导遮罩层级 */ private _hideGuideMask() { this.mSay_tips.active = false; this.mGuideMask.active = false; this._GuidNodeBlockInputEvents.enabled = false; this.mClickSpine.active = false; } /**显示引导遮罩层级 */ private _showGuideMask() { this.mGuideMask.active = true; this._GuidNodeBlockInputEvents.enabled = true; } /**移动并聚焦遮罩 */ private moveGuideMask(_pos: Vec3, time: number, width: number, height: number, callBack: Function) { tween(this.mBlackMask).to(time, { position: new Vec3(-this._pos.x, -this._pos.y, this._pos.z) }).start(); tween(this.mGuideMask).to(time, { position: this._pos }).call(() => { callBack(); }).start(); tween(this._GuideMask).to(time, { width: width, height: height }).start(); this.mClickSpine.setPosition(this._pos.x + this._btnOffset.x, this._pos.y + this._btnOffset.y); } /**移动遮罩结束 */ private moveEnd() { this.freeze_ScrollView(); this.showDes(); this.scheduleOnce(() => { this._GuidNodeBlockInputEvents.enabled = false; this.targetNode.on(Node.EventType.TOUCH_END, this.onClick_GuideNode, this); //this.targetNode.on('click',this.onClick_GuideNode,this); /**播放手指动画 */ this.mClickSpine.active = true; }); } /**显示文本提示 为聚焦目标点添加提示 */ private showDes() { if (this._des) { this.mSay_tips.active = true; CNodeUtils.switchText(this.mtips, this._des, true); this.mSay_tips.getComponent(Layout)?.updateLayout(); let tempPosY = -30; let sayUITransform = this.mSay_tips.getComponent(UITransform) let tY = this._pos.y - tempPosY - sayUITransform.height / 2; if (tY < (-this._GuideNodeHight / 2)) { tY = this._pos.y + tempPosY; } else { tY = this._pos.y - tempPosY; } let tX = this._pos.x; tX = Math.max(-(this._GuideNodeWidth / 2 - sayUITransform.width / 2) + 20, tX); tX = Math.min(this._GuideNodeWidth / 2 - sayUITransform.width / 2 - 20, tX); // this.mSay_tips.setPosition(tX, tY); } } /**触发了目标节点 点击事件*/ private onClick_GuideNode() { this._clickNum--; if (this._clickNum <= 0) { this.targetNode.off(Node.EventType.TOUCH_END, this.onClick_GuideNode, this); this.unfreeze_ScrollView(); this._hideGuideMask(); MesMgr.event(EGlobalEvent.E_GUIDE_TO_NEXT); } ConsoleEx.Log("点击目标节点"); } /**重置节点坐标与大小 */ private resetInitPos() { this.mBlackMask.setPosition(0, 0) this.mGuideMask.setPosition(0, 0); let tUITransform: UITransform = this.node.getComponent(UITransform) this._GuideMask.width = tUITransform.width; this._GuideMask.height = tUITransform.height; } /** * 设置引导目标节点 * @param tNode 目标节点 * @param clicknum 点击次数 * @param des 提示文本 * @param Opacity 设置遮罩的透明度 默认是 180 * @param time 遮罩聚焦时间 */ setGuideNode(tNode: Node, clicknum: number = 1, des: string = null, Opacity: number = 180, offsetx:number = 0, offsety:number = 0, time: number = 0.38) { this.targetNode = tNode; this._clickNum = clicknum; this._des = des; this._btnOffset.x = offsetx; this._btnOffset.y = offsety; /**重置坐标 */ this.resetInitPos(); /**显示遮罩 */ this._showGuideMask(); /**显示 */ this.mGuideMask.active = true; if (Opacity) { CNodeUtils.setOpacity(this.mBlackMask, Opacity); } else { CNodeUtils.setOpacity(this.mBlackMask, 180); } this.tryGetScrollViewList(tNode); this.scheduleOnce(() => { this._GuidNodeUITransform.convertToNodeSpaceAR(tNode.getWorldPosition(), this._pos); let tTransform: UITransform = tNode.getComponent(UITransform); this.moveGuideMask(this._pos, time, tTransform.width + this.offw, tTransform.height + this.offw, this.moveEnd.bind(this)); }, 0.3); } /** * 设置引导的目标世界坐标 请注意 目标一定要在屏幕内 * @param WordPos 世界坐标 * @param des 提示文本 */ setGuidePos(WordPos: Vec3, des: string = null) { this._des = des; /**重置坐标 */ this.resetInitPos(); /**显示遮罩 */ this._showGuideMask(); this.mPrantScrollView = []; /**显示 */ this.mGuideMask.active = true; CNodeUtils.setOpacity(this.mBlackMask, 180); this._pos = CameraCon.Ins.m_Camera.convertToUINode(WordPos, this.mGuidNode, this._pos); this.moveGuideMask(this._pos, 0.38, 100, 100, () => { this.showDes(); CNodeUtils.setActive(this.mTounch, true) this.mTounch.on(Node.EventType.TOUCH_END, this.onClickBlackMask, this); }); } /**触发了遮罩层点击事件 */ onClickBlackMask() { this.mTounch.off(Node.EventType.TOUCH_END, this.onClickBlackMask, this); CNodeUtils.setActive(this.mTounch, false) this.unfreeze_ScrollView(); this._hideGuideMask(); MesMgr.event(EGlobalEvent.E_GUIDE_TO_NEXT); } //#region 父节点组件处理 /**冻结滑动组件 */ private freeze_ScrollView() { this.mPrantScrollView.forEach((value, index) => { value["tmep_vertical"] = value.vertical; value["tmep_horizontal"] = value.horizontal; value.vertical = false; value.horizontal = false; }); } /**解冻滑动组件 */ private unfreeze_ScrollView() { this.mPrantScrollView.forEach((value, index) => { value.vertical = value["tmep_vertical"]; value.horizontal = value["tmep_horizontal"]; }); this.mPrantScrollView = []; } /**尝试获取目标节点上方 所有滑动列表 */ private tryGetScrollViewList(tNode: Node) { let list = this.findCom(tNode) as ScrollView[]; this.mPrantScrollView = list; } /**查找 滑动列表组件 */ private findCom(tNode: Node): ScrollView[] { let arr: ScrollView[] = []; let parent = tNode.parent; if (parent) { let com = parent.getComponent(ScrollView); if (com && parent.activeInHierarchy && (com.vertical || com.horizontal)) { arr.push(com) } arr = arr.concat(this.findCom(parent)); } return arr; } //#endregion }