pubgv3/assets/scripts/gif/GIFSprite.ts
2022-05-26 11:46:36 +08:00

240 lines
6.0 KiB
TypeScript

import { GIF, FileType, GIFCache } from "./GIF";
const { ccclass, property, requireComponent, disallowMultiple, executeInEditMode } = cc._decorator;
@ccclass
@executeInEditMode
@disallowMultiple
@requireComponent(cc.Sprite)
export default class GIFSprite extends cc.Component {
@property({ visible: false })
private _path: cc.RawAsset = null;
@property({ type: cc.Asset })
get path() { return this._path; }
set path(path: cc.RawAsset) {
if (path == null) return;
this._path = path;
this.innerPath = path.toString()
this.clear();
this.applayChange();
}
public sprite: cc.Sprite = null;
public _inited: boolean;
private _length: number = 0;
private _action: cc.ActionInterval;
private _delays: Array<number>;
private _index: number = 0;
private _spriteFrames: Array<cc.SpriteFrame>;
_positions: Array<cc.Vec2>
private innerPath: string
@property(Number)
private maxWith = 0;
@property(Number)
private maxHeight = 0;
@property(Boolean)
private stayAtFirstFrame = false;
@property(Boolean)
private fitHeight = true;
@property(Boolean)
private fitWidth = true;
public setInnerPath(path: string) {
this.innerPath = path
this.clear();
this.applayChange();
}
protected onLoad() {
this.sprite = this.node.getComponent(cc.Sprite);
if (CC_EDITOR) {
if (this.maxWith == 0)
this.maxWith = this.node.width;
if (this.maxHeight == 0)
this.maxHeight = this.node.height;
}
}
protected start() {
if(this.path){
this.setInnerPath(this.path.toString())
}
}
// protected update(dt) {
// }
// onDestroy() {
// }
public setDefaultSpriteFrame(spriteFrame: cc.SpriteFrame) {
let size = spriteFrame.getOriginalSize()
var scale = 0
var width = 0
var height = 0
if (this.fitHeight && !this.fitWidth) {
scale = this.maxHeight / size.height
width = scale * size.width
height = this.maxHeight
} else if (!this.fitHeight && this.fitWidth) {
scale = this.maxWith / size.width
width = this.maxWith
height = scale * size.height
} else {
let defaultWidthHeightScale = this.maxWith / this.maxHeight
let newWidthHeightScale = size.width / size.height
if (defaultWidthHeightScale > newWidthHeightScale) {
scale = this.maxHeight / size.height
width = scale * size.width
height = this.maxHeight
} else {
scale = this.maxWith / size.width
width = this.maxWith
height = scale * size.height
}
}
this.node.setContentSize(cc.size(width, height))
this.sprite.spriteFrame = spriteFrame
}
inited() {
this._index++
if (this._index >= this._spriteFrames.length) {
this._index = 0
}
let sp = this._spriteFrames[this._index];
this.sprite.spriteFrame = sp;
let delay = this._delays[this._index]
if (!delay || delay < 0.01) {
delay = 0.06
} else {
delay = delay * 0.01
}
this.scheduleOnce(() => {
this.inited()
}, delay)
}
private getType(): FileType {
let format = FileType.UNKNOWN
if (CC_JSB) {
if(this.innerPath.indexOf("/") == 0){
let buffer = jsb.fileUtils.getDataFromFile(this.innerPath)
let hexString = GIF.bytes2HexString(buffer.slice(0, 50))
format = GIF.detectFormat(hexString)
}
}
return format
}
private applayChange() {
let gifCache = GIFCache.getInstance()
let callback = (error, data) => {
if (error) {
cc.error("gif load error")
return
}
if (data instanceof cc.Texture2D) {
this.setDefaultSpriteFrame(new cc.SpriteFrame(data))
} else {
this._delays = data.delays;
this._spriteFrames = data.spriteFrames;
this._spriteFrames = data.spriteFrames;
this._positions = data.positions
this.setDefaultSpriteFrame(data.spriteFrames[0])
if (!this.stayAtFirstFrame) {
this.scheduleOnce(() => {
this.inited()
}, 0.1)
}
this._inited = true;
gifCache.addItemFrame(this.innerPath, data)
}
}
let format = FileType.UNKNOWN
let item = gifCache.get(this.innerPath)
if (item) {
format = item.type
} else {
format = this.getType()
gifCache.addItemType(this.innerPath, format)
}
if (format == FileType.GIF) {
if (gifCache.hasFrame(this.innerPath)) {
callback(null, item.frameData)
} else {
cc.loader.load({ url: this.innerPath, type: 'gif' }, callback)
}
} else {
cc.loader.load(this.innerPath, callback)
}
}
private clear() {
this.node.stopAllActions();
this._index = 0;
this._inited = null;
this._delays = null;
this._spriteFrames = null;
this.unscheduleAllCallbacks()
}
}
/**
*/
export interface GIFMessage {
target: GIFSprite,
buffer: ArrayBuffer,
initOneSpriteFrameFunc: {
(
data: {
delays: Array<number>,
spriteFrames: Array<cc.SpriteFrame>,
length: number
}
)
},
initFinishedFunc: {
(
data: {
delays: Array<number>,
spriteFrames: Array<cc.SpriteFrame>,
length: number
}
)
}
}