2025-04-24 17:03:28 +08:00

527 lines
17 KiB
TypeScript

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 = <cc.Node>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 = <cc.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 = <cc.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 = <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及後的版本都是用的這個。
// 直接操作組件對象
(<any>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;
}
}