mirror of
https://github.com/cocos/cocos-engine.git
synced 2026-09-07 00:02:53 +08:00
160 lines
5.9 KiB
TypeScript
160 lines
5.9 KiB
TypeScript
/**
|
|
* This method clones methods in minigame enviroment, sucb as `wx`, `swan` etc. to a module called minigame.
|
|
* @param targetObject Usually it's specified as the minigame module.
|
|
* @param originObj Original minigame environment such as `wx`, `swan` etc.
|
|
*/
|
|
export function cloneObject (targetObject: any, originObj: any) {
|
|
Object.keys(originObj).forEach((key) => {
|
|
if (typeof originObj[key] === 'function') {
|
|
targetObject[key] = originObj[key].bind(originObj);
|
|
return;
|
|
}
|
|
targetObject[key] = originObj[key];
|
|
});
|
|
}
|
|
|
|
type MiningameAudioCallbackName = 'onPlay' | 'onPause' | 'onStop' | 'onSeek';
|
|
type InnerAudioContextPolyfillConfig = {
|
|
[CallbackName in MiningameAudioCallbackName]: boolean;
|
|
};
|
|
/**
|
|
* This method is to create a polyfill on minigame platform when the innerAudioContext callback doesn't work.
|
|
* @param minigameEnv Specify the minigame enviroment such as `wx`, `swan` etc.
|
|
* @param polyfillConfig Specify the field, if it's true, the polyfill callback will be applied.
|
|
* @param isAsynchronous Specify whether the callback is called asynchronous.
|
|
* @returns A polyfilled createInnerAudioContext method.
|
|
*/
|
|
export function createInnerAudioContextPolyfill (minigameEnv: any, polyfillConfig: InnerAudioContextPolyfillConfig, isAsynchronous = false) {
|
|
return () => {
|
|
const audioContext: InnerAudioContext = minigameEnv.createInnerAudioContext();
|
|
|
|
// add polyfill if onPlay method doesn't work this platform
|
|
if (polyfillConfig.onPlay) {
|
|
const originalPlay = audioContext.play;
|
|
let _onPlayCB: (()=> void) | null = null;
|
|
Object.defineProperty(audioContext, 'onPlay', {
|
|
configurable: true,
|
|
value (cb: ()=> void) {
|
|
_onPlayCB = cb;
|
|
},
|
|
});
|
|
Object.defineProperty(audioContext, 'play', {
|
|
configurable: true,
|
|
value () {
|
|
originalPlay.call(audioContext);
|
|
if (_onPlayCB) {
|
|
if (isAsynchronous) {
|
|
setTimeout(_onPlayCB, 0);
|
|
} else {
|
|
_onPlayCB();
|
|
}
|
|
}
|
|
},
|
|
});
|
|
}
|
|
|
|
// add polyfill if onPause method doesn't work this platform
|
|
if (polyfillConfig.onPause) {
|
|
const originalPause = audioContext.pause;
|
|
let _onPauseCB: (()=> void) | null = null;
|
|
Object.defineProperty(audioContext, 'onPause', {
|
|
configurable: true,
|
|
value (cb: ()=> void) {
|
|
_onPauseCB = cb;
|
|
},
|
|
});
|
|
Object.defineProperty(audioContext, 'pause', {
|
|
configurable: true,
|
|
value () {
|
|
originalPause.call(audioContext);
|
|
if (_onPauseCB) {
|
|
if (isAsynchronous) {
|
|
setTimeout(_onPauseCB, 0);
|
|
} else {
|
|
_onPauseCB();
|
|
}
|
|
}
|
|
},
|
|
});
|
|
}
|
|
|
|
// add polyfill if onStop method doesn't work on this platform
|
|
if (polyfillConfig.onStop) {
|
|
const originalStop = audioContext.stop;
|
|
let _onStopCB: (()=> void) | null = null;
|
|
Object.defineProperty(audioContext, 'onStop', {
|
|
configurable: true,
|
|
value (cb: ()=> void) {
|
|
_onStopCB = cb;
|
|
},
|
|
});
|
|
Object.defineProperty(audioContext, 'stop', {
|
|
configurable: true,
|
|
value () {
|
|
originalStop.call(audioContext);
|
|
if (_onStopCB) {
|
|
if (isAsynchronous) {
|
|
setTimeout(_onStopCB, 0);
|
|
} else {
|
|
_onStopCB();
|
|
}
|
|
}
|
|
},
|
|
});
|
|
}
|
|
|
|
// add polyfill if onSeeked method doesn't work on this platform
|
|
if (polyfillConfig.onSeek) {
|
|
const originalSeek = audioContext.seek;
|
|
let _onSeekCB: (()=> void) | null = null;
|
|
Object.defineProperty(audioContext, 'onSeeked', {
|
|
configurable: true,
|
|
value (cb: ()=> void) {
|
|
_onSeekCB = cb;
|
|
},
|
|
});
|
|
Object.defineProperty(audioContext, 'seek', {
|
|
configurable: true,
|
|
value (time: number) {
|
|
originalSeek.call(audioContext, time);
|
|
if (_onSeekCB) {
|
|
if (isAsynchronous) {
|
|
setTimeout(_onSeekCB, 0);
|
|
} else {
|
|
_onSeekCB();
|
|
}
|
|
}
|
|
},
|
|
});
|
|
}
|
|
|
|
return audioContext;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Compare two version, version should in pattern like 3.0.0.
|
|
* If versionA > versionB, return number larger than 0.
|
|
* If versionA = versionB, return number euqal to 0.
|
|
* If versionA < versionB, return number smaller than 0.
|
|
* @param versionA
|
|
* @param versionB
|
|
*/
|
|
export function versionCompare (versionA: string, versionB: string): number {
|
|
const versionRegExp = /\d+\.\d+\.\d+/;
|
|
if (!(versionRegExp.test(versionA) && versionRegExp.test(versionB))) {
|
|
console.warn('wrong format of version when compare version');
|
|
return 0;
|
|
}
|
|
const versionNumbersA = versionA.split('.').map((num: string) => Number.parseInt(num));
|
|
const versionNumbersB = versionB.split('.').map((num: string) => Number.parseInt(num));
|
|
for (let i = 0; i < 3; ++i) {
|
|
const numberA = versionNumbersA[i];
|
|
const numberB = versionNumbersB[i];
|
|
if (numberA !== numberB) {
|
|
return numberA - numberB;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|