import { _decorator, Animation, Button, Component, EditBox, editorExtrasTag, find, isValid, js, Label, Node, ProgressBar, Quat, Slider, sp, Sprite, SpriteFrame, tween, UIOpacity, UITransform, Vec3, } from "cc"; import { ScrollView } from "cc"; import { Prefab } from "cc"; import { instantiate } from "cc"; import BaseUI from "./BaseUI"; import AB from "./AB"; export default class UIUtils { static destroyNodeDelay(new_prop: Node, arg1: number) { setTimeout(() => { if (isValid(new_prop)) { new_prop.destroy(); } }, arg1); } // static async addEmptyNode(layout: Node) { // let p = await Utils.loadRes("v2/ui/items/EmptyNode", Prefab); // let emptyNode = instantiate(p as unknown as Prefab); // emptyNode.active = true; // emptyNode.name = "EmptyNode"; // emptyNode.parent = layout; // } static removeEmptyNode(content: Node) { let emptyNode = content.getChildByName("EmptyNode"); if (emptyNode) { emptyNode.destroy(); } } static moveToNewParentAndAnim(parent: Node, animNode: Node, cb: Function) { UIUtils.moveToNewParent(parent, animNode); UIUtils.AnimBezierMoveAndScale( animNode, new Vec3(0, 0, 0), 0.2, 0.8, () => { cb(); } ); } static hideAnim(node: Node, arg1: () => void) { tween(node) .to(0.2, { scale: new Vec3(0, 0, 0) }) .call(() => { node.active = false; node.setScale(new Vec3(1, 1, 1)); arg1(); }) .start(); } static closeUI(node: Node) { if (!isValid(node)) { return; } node.active = false; node.parent = null; node.destroy(); } public static DeepFindChildByName(parentNode: Node, name: string): Node { if (!isValid(parentNode)) { return null; } return UIUtils._findInChildren(parentNode, name); } // 将一个node节点移动到新的父节点 static moveToNewParent(parent: Node, child: Node) { // 先转换child的世界坐标位置 let cp = child.getWorldPosition(new Vec3()); // 更换父节点 child.setParent(parent, false); // 转换世界坐标到新父节点的本地坐标系 const parentUITrans = parent.getComponent(UITransform); // 设置新的本地坐标,使其屏幕位置不变 const newP = parentUITrans.convertToNodeSpaceAR(cp); child.setPosition(newP); } static AnimateLayoutItems( layout: Node, offsetX: number = -20, offsetY: number = -20, delayInterval: number = 0.1, duration: number = 0.3 ): void { const children = layout.children; children.forEach((child, index) => { // 记录原始位置并设置初始偏移位置 const originalPos = child.position.clone(); child.setPosition( originalPos.x + offsetX, originalPos.y + offsetY, originalPos.z ); // 设置透明度组件 let opacityComp = child.getComponent(UIOpacity); if (!opacityComp) { opacityComp = child.addComponent(UIOpacity); } opacityComp.opacity = 0; // 启动动画 tween(child) .delay(index * delayInterval) .parallel( tween(child).to( duration, { position: originalPos }, { easing: "sineOut" } ), tween(opacityComp).to(duration, { opacity: 255 }) ) .start(); }); } static AnimScaleShake( node: Node, scale: number = 1.2, duration: number = 0.6, repeatForever: boolean = true, callback?: () => void ) { const originalScale = node.getScale().clone(); const scaleUp = Vec3.multiplyScalar(new Vec3(), originalScale, scale); const animation = tween(node) .to( duration / 2, { scale: originalScale.clone().multiplyScalar(scale) }, { easing: "quadOut" } ) .to(duration / 2, { scale: originalScale }, { easing: "quadIn" }); if (repeatForever) { animation.repeatForever().start(); } else { animation .call(() => { if (callback) callback(); }) .start(); } } static async AnimShakeUpAndDownByTimes(node: Node, duration: number) { // 根据动画的次数,计算出动画的间隔时间 return new Promise((resolve, reject) => { tween(node) .to( duration / 2, { position: new Vec3(0, 30, 0) }, { easing: "quadOut" } ) .to( duration / 2, { position: new Vec3(0, 150, 0) }, { easing: "quadIn" } ) .call(() => { resolve(node); }) .start(); }); } static async AsyncBezierMoveAndScale( node: Node, targetPos: Vec3, scale: number, duration: number, rotate?: number ) { return new Promise((resolve, reject) => { this.AnimBezierMoveAndScale( node, targetPos, scale, duration, () => { resolve(node); }, rotate ); }); } static AnimBezierMoveAndTranslate( node: Node, targetPos: Vec3, scale: number, duration: number, callback?: Function ) { if (!isValid(node)) { return; } let opacityComp = node.getComponent(UIOpacity); if (!opacityComp) { opacityComp = node.addComponent(UIOpacity); } const startPos = node.getPosition(); const startScale = node.scale.clone(); const ctrl = new Vec3( (startPos.x + targetPos.x) / 2, Math.max(startPos.y, targetPos.y) + 150, (startPos.z + targetPos.z) / 2 ); const tempPos = new Vec3(); const tempScale = new Vec3(); tween({ t: 0 }) .to( duration, { t: 1 }, { easing: "quadInOut", onUpdate: (obj) => { if (!isValid(node)) { return; } const t = obj.t; const oneMinusT = 1 - t; // 贝塞尔曲线计算 tempPos.x = oneMinusT * oneMinusT * startPos.x + 2 * t * oneMinusT * ctrl.x + t * t * targetPos.x; tempPos.y = oneMinusT * oneMinusT * startPos.y + 2 * t * oneMinusT * ctrl.y + t * t * targetPos.y; tempPos.z = oneMinusT * oneMinusT * startPos.z + 2 * t * oneMinusT * ctrl.z + t * t * targetPos.z; node.setPosition(tempPos); // 缩放插值计算 tempScale.set( startScale.x + (scale - startScale.x) * t, startScale.y + (scale - startScale.y) * t, startScale.z + (scale - startScale.z) * t ); node.setScale(tempScale); //设置透明度,越来越透明 opacityComp.opacity = 255 * (1 - t); }, } ) .call(() => { if (callback) callback(); }) .start(); } // 贝塞尔曲线实现移动和缩放动画 static AnimBezierMoveAndScale( node: Node, targetPos: Vec3, scale: number, duration: number, callback?: Function, rotate?: number ) { if (!isValid(node)) { return; } const startPos = node.getPosition(); const startScale = node.scale.clone(); const ctrl = new Vec3( (startPos.x + targetPos.x) / 2, Math.max(startPos.y, targetPos.y) + 150, (startPos.z + targetPos.z) / 2 ); const tempPos = new Vec3(); const tempScale = new Vec3(); tween({ t: 0 }) .to( duration, { t: 1 }, { easing: "quadInOut", onUpdate: (obj) => { if (!isValid(node)) { return; } const t = obj.t; const oneMinusT = 1 - t; // 贝塞尔曲线计算 tempPos.x = oneMinusT * oneMinusT * startPos.x + 2 * t * oneMinusT * ctrl.x + t * t * targetPos.x; tempPos.y = oneMinusT * oneMinusT * startPos.y + 2 * t * oneMinusT * ctrl.y + t * t * targetPos.y; tempPos.z = oneMinusT * oneMinusT * startPos.z + 2 * t * oneMinusT * ctrl.z + t * t * targetPos.z; node.setPosition(tempPos); // 缩放插值计算 tempScale.set( startScale.x + (scale - startScale.x) * t, startScale.y + (scale - startScale.y) * t, startScale.z + (scale - startScale.z) * t ); node.setScale(tempScale); if (rotate) { node.setRotationFromEuler(new Vec3(0, 0, rotate * t)); } }, } ) .call(() => { if (callback) callback(); }) .start(); } public static _findInChildren(node: Node, name: string): Node { var x = node.getChildByName(name); if (x) return x; if (node.children.length == 0) return null; for (var i = 0; i < node.children.length; ++i) { var tmp = this._findInChildren(node.children[i], name); if (tmp) return tmp; } return null; } public static async SetSprite( sprite: Sprite, filepath: string, cb: Function ) { return new Promise((resolve, reject) => { if (sprite) { AB.ins .loadRes(filepath + "/spriteFrame", SpriteFrame) .then((ret: SpriteFrame) => { if (isValid(sprite.node)) { sprite.spriteFrame = ret; resolve(null); cb(); } else { } }) .catch((e) => { console.log(filepath); console.log(e); }); } }); } }