import { borderInfo, HeadBorderUtil } from "../../appearance/HeadBorderUtil"; import ItemUtil from "../../core/ItemUtil"; import SkillUtil from "../../game/skill/core/SkillUtil"; import FGHUD from "../fgui/FGHUD"; import Report from "../net/Report"; import SKDataUtil from "./SKDataUtil"; import SKLogger from "./SKLogger"; export default class SKUIUtil { private static progressBlock: Function; private static loadedBlock: Function; static colorOfString(value: string): cc.Color { if (value == null || value.length != 7) { return null; } var color = value.toLowerCase(); if (color.charAt(0) != "#") { return; } color = color.slice(1); var r = parseInt(color[0] + color[1], 16); var g = parseInt(color[2] + color[3], 16); var b = parseInt(color[4] + color[5], 16); return new cc.Color(r, g, b, 255); } static limitRadius(target: cc.Vec2, raduis: number) { if (!target) { return; } let length = target.mag(); if (length > raduis) { let scale = 1 - (length - raduis) / length; target.mulSelf(scale); } } // 返回兩個節點之間的角度 static angleByNode(source: cc.Node, target: cc.Node): number { let result = Math.atan2(target.y - source.y, target.x - source.x); result = cc.misc.radiansToDegrees(result); return result; } // 獲得兩個向量之間的角度 static angleByVec2(start: cc.Vec2, end: cc.Vec2): number { let result = Math.atan2(end.y - start.y, end.x - start.x); result = cc.misc.radiansToDegrees(result); return result; } // 返回兩個向量之間的距離 static distanceByVec2(source: cc.Vec2, target: cc.Vec2): number { if (!source || !target) { return -1; } let temp = source.sub(target); let result = temp.mag(); return result; } // 返回兩個節點之間的距離 static distanceByNode(source: cc.Node, target: cc.Node): number { if (!source || !target) { return -1; } let temp = source.position.sub(target.position); let result = temp.mag(); return result; } // 返回兩個節點之間的距離的绝对值 static distance(source: cc.Node, target: cc.Node): number { if (!source || !target) { return -1; } let temp = source.position.sub(target.position); let result = Math.abs(temp.mag()); return result; } static add(source: cc.Vec2, target: cc.Vec2): cc.Vec2 { if (!source || !target) { return; } let result = source.add(target); return result; } // 返回兩個節點之間的弧度 static radiansByNode(source: cc.Node, target: cc.Node): number { let result = Math.atan2(target.y - source.y, target.x - source.x); return result; } // 返回兩個向量之間的弧度 static radiansByVec2(start: cc.Vec2, end: cc.Vec2): number { let result = Math.atan2(end.y - start.y, end.x - start.x); return result; } static addNode(name: string, parentNode: cc.Node): cc.Node { let node = new cc.Node(name); parentNode.addChild(node); return node; } // 加載場景 static loadScene(sceneName: string, progressBlock?: (completedCount: number, totalCount: number, item: any) => void, completeBlock?: (sceneName: string) => void) { let current = cc.director.getScene(); if (current && current.name == sceneName) { SKLogger.warn(`當前場景已經是:${sceneName}`); return; } cc.director.preloadScene(sceneName, progressBlock, (error: Error, asset: cc.SceneAsset) => { FGHUD.hideLoading(); cc.director.loadScene(sceneName, () => { SKLogger.debug(`進入場景:${sceneName}`); if (completeBlock) { completeBlock(sceneName); } }); }); } // 顯示龍骨動畫 static showDragonBone(target: cc.Node, url: string, animationName?: string, imageNode?: cc.Node, imageUrl?: string) { if (imageNode) { imageNode.active = false; } if (!target) { target.active = false; this.showImage(imageNode, imageUrl); return; } cc.loader.loadResDir(url, (error: Error, resources: any[], urls: string[]) => { if (error || resources.length == 0) { cc.warn(`加載龍骨錯誤:${url}`); this.showImage(imageNode, imageUrl); return; } let valid = SKUIUtil.isValid(target); if (!valid) { cc.warn(`$警告:龍骨挂件已釋放[${url}]`); return; } let dragonBone: any = {}; for (let item of resources) { if (item instanceof dragonBones.DragonBonesAsset) { dragonBone.asset = item; } else if (item instanceof dragonBones.DragonBonesAtlasAsset) { dragonBone.atlasAsset = item; } } let temp = target["_components"]; let display: dragonBones.ArmatureDisplay = null; if (temp) { display = target.getComponent(dragonBones.ArmatureDisplay); } let armatureName = "armatureName"; if (display) { if (!animationName) { animationName = display.animationName; } armatureName = display.armatureName; display.destroy(); display = target.addComponent(dragonBones.ArmatureDisplay); } else { if (animationName) { display = target.addComponent(dragonBones.ArmatureDisplay); } else { this.showImage(imageNode, imageUrl); return; } } display.dragonAsset = dragonBone.asset; display.dragonAtlasAsset = dragonBone.atlasAsset; display.armatureName = armatureName; let animationList = display.getAnimationNames(armatureName); if (animationList.indexOf(animationName) == -1) { return; } display.animationName = animationName; display.playAnimation(animationName, 0); target.active = true; }); } static showImage(target: cc.Node, url: string) { if (!target || !url) { return; } cc.loader.loadResDir(url, cc.SpriteFrame, (error: Error, result: any) => { if (error) { return; } if (!SKUIUtil.isValid(target)) { cc.warn(`$警告:圖片節點已釋放[${url}]`); return; } target.active = true; let sprite = target.getComponent(cc.Sprite); if (!sprite) { sprite = target.addComponent(cc.Sprite); } sprite.spriteFrame = result[0]; }) } // 釋放節點數組 static destroyList(value: cc.Node[]) { if (value == null || value.length < 1) { return; } for (let item of value) { let valid = SKUIUtil.isValid(item); if (!valid) { continue; } item.destroy(); } value.length = 0; } // 釋放節點字典 static destroyDict(value: any) { for (let key in value) { let item = value[key]; if (item) { let valid = SKUIUtil.isValid(item); if (!valid) { continue; } item.destroy(); } } value = {}; } // 節點是否有效 static isValid(value: any): boolean { if (value == null) { return false; } if (!(value instanceof cc.Node)) { cc.log(`$警告:不是cc.Node,${typeof value}`); return false; } let node = value; let result = cc.isValid(node, true); return result; } // FGUI節點是否有效 static isFGUIValid(value: any): boolean { if (value == null) { return false; } if (!value.node) { return false; } if (!(value.node instanceof cc.Node)) { return false; } let node = value.node; let result = cc.isValid(node, true); return result; } // 安全設置文本 static setLabel(node: cc.Node, name: string, text: string) { if (!SKUIUtil.isValid(node)) { return; } let child = node.getChildByName(name); if (!child) { return; } let label = child.getComponent(cc.Label); if (!label) { return; } label.string = text; } // 加載紋理圖集動畫 static loadAtlasAni(prefix: string, path: string, callback: (clip: cc.AnimationClip) => void) { let url = `${prefix}/${path}`; cc.loader.loadRes(url, cc.SpriteAtlas, (error: Error, atlas: cc.SpriteAtlas) => { if (error) { let info = `$警告:加載動畫圖集[${url}]錯誤:${error}`; SKLogger.warn(info); return; } let spriteFrames = []; for (let i = 1; i < 999; i++) { let frame = atlas.getSpriteFrame(String(i)); if (frame == null) { continue; } spriteFrames.push(frame); } if (spriteFrames.length == 0) spriteFrames = atlas.getSpriteFrames() if (spriteFrames.length < 1) { return; } let clip = cc.AnimationClip.createWithSpriteFrames(spriteFrames, 15); callback(clip); }); } // 返回節點是否可見 static isActive(value: any): boolean { if (value == null) { return false; } if (!(value instanceof cc.Node)) { return false; } let node: cc.Node = value; if (this.isValid(node)) { return node.active; } return false; } // 獲得滾動條 static getParentScroll(value: cc.Node): cc.ScrollView { if (value == null) { return null; } let result: cc.ScrollView = null; while (value.parent) { value = value.parent; result = value.getComponent(cc.ScrollView); if (result) { return result; } } return result; } // 置頂 static scrollToTop(value: cc.ScrollView) { if (value == null) { return; } value.scheduleOnce(() => { value.scrollToTop(); }, 0); } // 釋放節點 static destroy(value: cc.Node) { if (!SKUIUtil.isValid(value)) { return; } value.destroy(); } static addButtonClick(node: cc.Node, path: string, callback: () => void) { let button = this.getButton(node, path); if (button == null) { return; } button.node.on("click", callback); } static getButton(node: cc.Node, path: string): cc.Button { if (!this.isValid(node)) { return; } let target = cc.find(path, node); if (target == null) { return null; } let button = target.getComponent(cc.Button); return button; } static getLabelText(node: cc.Node, path: string): string { if (!this.isValid(node)) { return; } let target = cc.find(path, node); if (target == null) { return null; } let label = target.getComponent(cc.Label); if (label) { return label.string; } return ""; } static getEditBoxText(node: cc.Node, path: string): string { if (!this.isValid(node)) { return; } let target = cc.find(path, node); if (target == null) { return null; } let editBox = target.getComponent(cc.EditBox); if (editBox) { return editBox.string; } return ""; } // 銷毀節點 static destoryNode(target: cc.Node, name: string) { let node = target.getChildByName(name); if (node != null) { node.destroy(); } } static createSubNode(parent: cc.Node, position: cc.Vec2, prefab: cc.Prefab, name: string): cc.Node { if (prefab == null) { SKLogger.warn(`預製體不能為空!`); return null; } let result: cc.Node = cc.instantiate(prefab); if (result) { result.parent = parent; result.name = name; result.setPosition(position); } else { SKLogger.warn(`創建子節點錯誤:${name}`); } return result; } static setSpriteFrame(node: cc.Node, url: string, key: string) { if (!SKUIUtil.isValid(node)) { cc.warn(`$警告:無效節點:${url},${key}`); return; } let sprite = node.getComponent(cc.Sprite); if (!sprite) { cc.warn(`節點不是精靈:${url},${key}`); return; } cc.loader.loadRes(url, cc.SpriteAtlas, (error: any, atlas: cc.SpriteAtlas) => { if (error) { SKLogger.warn(`$警告:圖集資源加載錯誤:${url}`); return; } if (SKUIUtil.isValid(sprite.node)) { sprite.spriteFrame = atlas.getSpriteFrame(key); } }); } static setSpriteFrameFgui(node: cc.Node, key: string) { // console.log("setSpriteFrameFgui = ", key) let sprite = node.getComponent(cc.Sprite); if (SKUIUtil.isValid(sprite.node)) { sprite.spriteFrame = SkillUtil.getSkillIcon(key) } } // 獲得文本渲染寬度 static labelHeightBy(label: cc.Label): number { let h = label.node.height; // _forceUpdateRenderData(); 2.2及後的版本都是用的這個。 // 直接操作組件對象 (label)._forceUpdateRenderData(); let height = Math.ceil(label.node.getContentSize().height); return height; } // 呼吸效果 static breathe(value: cc.Node) { if (!this.isValid(value)) { return; } let zoom = cc.tween(value).to(0.2, { scale: 1.08 }); let restore = cc.tween(value).to(0.2, { scale: 1 }); cc.tween(value).delay(1).sequence(zoom, restore).repeatForever().start(); } static setHeadBorder(borderNode: cc.Node, borderId: number) { if (!this.isValid(borderNode)) { return; } // 頭像框信息 var borderInfo: borderInfo = HeadBorderUtil.getBorderData(borderId); var borderSP = borderNode.getComponent(cc.Sprite); if (borderSP) borderSP.spriteFrame = ItemUtil.getItemIcon(borderInfo.border); // 左上 var boderLTSP = SKUIUtil.getChildSpriteCom(borderNode, "hb_l_t"); if (boderLTSP) if (borderInfo.addLT != "") { boderLTSP.spriteFrame = ItemUtil.getItemIcon(borderInfo.addLT); boderLTSP.node.setPosition(borderInfo.LTPos.x, -borderInfo.LTPos.y); } else boderLTSP.spriteFrame = null; // 右上 var boderRTSP = SKUIUtil.getChildSpriteCom(borderNode, "hb_r_t"); if (boderRTSP) if (borderInfo.addRT != "") { boderRTSP.spriteFrame = ItemUtil.getItemIcon(borderInfo.addRT); boderRTSP.node.setPosition(borderInfo.RTPos.x, -borderInfo.RTPos.y); } else boderRTSP.spriteFrame = null; // 左下 var boderLBSP = SKUIUtil.getChildSpriteCom(borderNode, "hb_l_b"); if (boderLBSP) if (borderInfo.addLB != "") { boderLBSP.spriteFrame = ItemUtil.getItemIcon(borderInfo.addLB); boderLBSP.node.setPosition(borderInfo.LBPos.x, -borderInfo.LBPos.y); } else boderLBSP.spriteFrame = null; // 右下 var boderRBSP = SKUIUtil.getChildSpriteCom(borderNode, "hb_r_b"); if (boderRBSP) if (borderInfo.addRB != "") { boderRBSP.spriteFrame = ItemUtil.getItemIcon(borderInfo.addRB); boderRBSP.node.setPosition(borderInfo.RBPos.x, -borderInfo.RBPos.y); } else boderRBSP.spriteFrame = null; } static getChildSpriteCom(pNode: cc.Node, childName: string) { var child = pNode.getChildByName(childName); if (!child) return null; var sp = child.getComponent(cc.Sprite); if (sp) return sp; return null; } }