527 lines
17 KiB
TypeScript
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;
|
|
}
|
|
} |