240 lines
6.0 KiB
TypeScript
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
|
|
}
|
|
)
|
|
}
|
|
|
|
} |