mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2025-10-09 13:25:23 +00:00
[adapters] 增加小游戏适配部分源码
This commit is contained in:
18
adapters/platforms/taobao-minigame/index.js
Normal file
18
adapters/platforms/taobao-minigame/index.js
Normal file
@@ -0,0 +1,18 @@
|
||||
const _global = window;
|
||||
const adapter = _global.__globalAdapter = _global.__globalAdapter || {};
|
||||
|
||||
Object.assign(adapter, {
|
||||
init () {
|
||||
require('./wrapper/builtin');
|
||||
_global.DOMParser = require('../../common/xmldom/dom-parser').DOMParser;
|
||||
require('./wrapper/unify');
|
||||
require('./wrapper/fs-utils');
|
||||
require('../../common/engine/globalAdapter');
|
||||
require('./wrapper/systemInfo');
|
||||
},
|
||||
|
||||
adaptEngine () {
|
||||
require('../../common/engine');
|
||||
require('./wrapper/engine');
|
||||
},
|
||||
});
|
11
adapters/platforms/taobao-minigame/res/ccRequire.js
Normal file
11
adapters/platforms/taobao-minigame/res/ccRequire.js
Normal file
@@ -0,0 +1,11 @@
|
||||
let moduleMap = {
|
||||
// tail
|
||||
};
|
||||
|
||||
window.__cocos_require__ = function (moduleName) {
|
||||
let func = moduleMap[moduleName];
|
||||
if (!func) {
|
||||
throw new Error(`cannot find module ${moduleName}`);
|
||||
}
|
||||
return func();
|
||||
};
|
3
adapters/platforms/taobao-minigame/res/cocos/plugin.json
Normal file
3
adapters/platforms/taobao-minigame/res/cocos/plugin.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"main": "cocos2d-js-min.js"
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"pluginId": "3000000085619513",
|
||||
"signature": [
|
||||
{
|
||||
"path": "cocos2d-js-min.js",
|
||||
"md5": ""
|
||||
}
|
||||
]
|
||||
}
|
20
adapters/platforms/taobao-minigame/res/game.js
Normal file
20
adapters/platforms/taobao-minigame/res/game.js
Normal file
@@ -0,0 +1,20 @@
|
||||
require('./ccRequire');
|
||||
require('adapter-js-path');
|
||||
__globalAdapter.init();
|
||||
require('cocos2d-js-path');
|
||||
require('physics-js-path');
|
||||
__globalAdapter.adaptEngine();
|
||||
|
||||
require('./src/settings');
|
||||
// Introduce Cocos Service here
|
||||
require('./main'); // TODO: move to common
|
||||
|
||||
// Adjust devicePixelRatio
|
||||
cc.view._maxPixelRatio = 4;
|
||||
|
||||
// Release Image objects after uploaded gl texture
|
||||
cc.macro.CLEANUP_IMAGE_CACHE = true;
|
||||
|
||||
window.boot();
|
||||
|
||||
|
16
adapters/platforms/taobao-minigame/res/game.json
Normal file
16
adapters/platforms/taobao-minigame/res/game.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"deviceOrientation": "portrait",
|
||||
"window": {
|
||||
"allowsBounceVertical": "NO",
|
||||
"transparentTitle": "always",
|
||||
"enableAudioAlign": true,
|
||||
"enableMultiAudio": true
|
||||
},
|
||||
"plugins": {
|
||||
"cocos": {
|
||||
"pluginId": "3000000085619513",
|
||||
"pluginVersion": "",
|
||||
"path": "cocos"
|
||||
}
|
||||
}
|
||||
}
|
39
adapters/platforms/taobao-minigame/res/global-variables.js
Normal file
39
adapters/platforms/taobao-minigame/res/global-variables.js
Normal file
@@ -0,0 +1,39 @@
|
||||
var window = $global;
|
||||
var cc = window.cc = window.cc || {};
|
||||
var b2 = window.b2 = window.b2 || {};
|
||||
var sp = window.sp = window.sp || {};
|
||||
var dragonBones = window.dragonBones = window.dragonBones || {};
|
||||
var __globalAdapter = window.__globalAdapter = window.__globalAdapter || {};
|
||||
var __cocos_require__ = window.__cocos_require__;
|
||||
var Image = window.Image;
|
||||
var HTMLCanvasElement = window.HTMLCanvasElement;
|
||||
var HTMLImageElement = window.HTMLImageElement;
|
||||
var ImageBitmap = window.ImageBitmap;
|
||||
var document = window.document;
|
||||
var DOMParser = window.DOMParser;
|
||||
var performance = window.performance;
|
||||
var XMLHttpRequest = window.XMLHttpRequest;
|
||||
var WebSocket = window.WebSocket;
|
||||
var __extends = window.__extends;
|
||||
var __assign = window.__assign;
|
||||
var __rest = window.__rest;
|
||||
var __decorate = window.__decorate;
|
||||
var __param = window.__param;
|
||||
var __metadata = window.__metadata;
|
||||
var __awaiter = window.__awaiter;
|
||||
var __generator = window.__generator;
|
||||
var __exportStar = window.__exportStar;
|
||||
var __createBinding = window.__createBinding;
|
||||
var __values = window.__values;
|
||||
var __read = window.__read;
|
||||
var __spread = window.__spread;
|
||||
var __spreadArrays = window.__spreadArrays;
|
||||
var __await = window.__await;
|
||||
var __asyncGenerator = window.__asyncGenerator;
|
||||
var __asyncDelegator = window.__asyncDelegator;
|
||||
var __asyncValues = window.__asyncValues;
|
||||
var __makeTemplateObject = window.__makeTemplateObject;
|
||||
var __importStar = window.__importStar;
|
||||
var __importDefault = window.__importDefault;
|
||||
var __classPrivateFieldGet = window.__classPrivateFieldGet;
|
||||
var __classPrivateFieldSet = window.__classPrivateFieldSet;
|
64
adapters/platforms/taobao-minigame/res/main.js
Normal file
64
adapters/platforms/taobao-minigame/res/main.js
Normal file
@@ -0,0 +1,64 @@
|
||||
window.boot = function () {
|
||||
var settings = window._CCSettings;
|
||||
window._CCSettings = undefined;
|
||||
|
||||
var onStart = function () {
|
||||
|
||||
cc.view.enableRetina(true);
|
||||
cc.view.resizeWithBrowserSize(true);
|
||||
|
||||
var launchScene = settings.launchScene;
|
||||
|
||||
// load scene
|
||||
cc.director.loadScene(launchScene, null,
|
||||
function () {
|
||||
console.log('Success to load scene: ' + launchScene);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
var option = {
|
||||
id: 'GameCanvas',
|
||||
debugMode: settings.debug ? cc.debug.DebugMode.INFO : cc.debug.DebugMode.ERROR,
|
||||
showFPS: settings.debug,
|
||||
frameRate: 60,
|
||||
groupList: settings.groupList,
|
||||
collisionMatrix: settings.collisionMatrix,
|
||||
}
|
||||
|
||||
cc.assetManager.init({
|
||||
bundleVers: settings.bundleVers,
|
||||
subpackages: settings.subpackages,
|
||||
remoteBundles: settings.remoteBundles,
|
||||
server: settings.server
|
||||
});
|
||||
|
||||
var RESOURCES = cc.AssetManager.BuiltinBundleName.RESOURCES;
|
||||
var INTERNAL = cc.AssetManager.BuiltinBundleName.INTERNAL;
|
||||
var MAIN = cc.AssetManager.BuiltinBundleName.MAIN;
|
||||
var START_SCENE = cc.AssetManager.BuiltinBundleName.START_SCENE;
|
||||
var bundleRoot = [INTERNAL];
|
||||
settings.hasResourcesBundle && bundleRoot.push(RESOURCES);
|
||||
settings.hasStartSceneBundle && bundleRoot.push(MAIN);
|
||||
|
||||
var count = 0;
|
||||
function cb (err) {
|
||||
if (err) return console.error(err.message, err.stack);
|
||||
count++;
|
||||
if (count === bundleRoot.length + 1) {
|
||||
// if there is start-scene bundle. should load start-scene bundle in the last stage.
|
||||
// Otherwise the main bundle should be the last
|
||||
cc.assetManager.loadBundle(settings.hasStartSceneBundle ? START_SCENE : MAIN, function (err) {
|
||||
if (!err) cc.game.run(option, onStart);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// load plugins
|
||||
cc.assetManager.loadScript(settings.jsList.map(function (x) { return 'src/' + x;}), cb);
|
||||
|
||||
// load bundles
|
||||
for (var i = 0; i < bundleRoot.length; i++) {
|
||||
cc.assetManager.loadBundle(bundleRoot[i], cb);
|
||||
}
|
||||
};
|
1
adapters/platforms/taobao-minigame/res/mini.project.json
Normal file
1
adapters/platforms/taobao-minigame/res/mini.project.json
Normal file
@@ -0,0 +1 @@
|
||||
{"miniprogramRoot":"client","pluginRoot":"widget","compileType":"minigame","enableAppxNg":true,"widgetRuntimeVersion":"3.0-vue"}
|
205
adapters/platforms/taobao-minigame/wrapper/builtin/Audio.js
Normal file
205
adapters/platforms/taobao-minigame/wrapper/builtin/Audio.js
Normal file
@@ -0,0 +1,205 @@
|
||||
import HTMLAudioElement from './HTMLAudioElement'
|
||||
|
||||
const HAVE_NOTHING = 0
|
||||
const HAVE_METADATA = 1
|
||||
const HAVE_CURRENT_DATA = 2
|
||||
const HAVE_FUTURE_DATA = 3
|
||||
const HAVE_ENOUGH_DATA = 4
|
||||
|
||||
let SN_SEED = 1
|
||||
|
||||
const _innerAudioContextMap = {}
|
||||
|
||||
export default class Audio extends HTMLAudioElement {
|
||||
|
||||
constructor(url) {
|
||||
super()
|
||||
|
||||
this._$sn = SN_SEED++;
|
||||
|
||||
this.HAVE_NOTHING = HAVE_NOTHING
|
||||
this.HAVE_METADATA = HAVE_METADATA
|
||||
this.HAVE_CURRENT_DATA = HAVE_CURRENT_DATA
|
||||
this.HAVE_FUTURE_DATA = HAVE_FUTURE_DATA
|
||||
this.HAVE_ENOUGH_DATA = HAVE_ENOUGH_DATA
|
||||
|
||||
this.readyState = HAVE_NOTHING
|
||||
|
||||
const innerAudioContext = my.createInnerAudioContext()
|
||||
|
||||
_innerAudioContextMap[this._$sn] = innerAudioContext
|
||||
|
||||
this._canplayEvents = [
|
||||
'load',
|
||||
'loadend',
|
||||
'canplay',
|
||||
'canplaythrough',
|
||||
'loadedmetadata'
|
||||
]
|
||||
|
||||
innerAudioContext.onCanplay(() => {
|
||||
this._loaded = true
|
||||
this.readyState = this.HAVE_CURRENT_DATA
|
||||
this._canplayEvents.forEach((type) => {
|
||||
this.dispatchEvent({ type: type })
|
||||
})
|
||||
})
|
||||
innerAudioContext.onPlay(() => {
|
||||
this._paused = _innerAudioContextMap[this._$sn].paused
|
||||
this.dispatchEvent({ type: 'play' })
|
||||
})
|
||||
innerAudioContext.onPause(() => {
|
||||
this._paused = _innerAudioContextMap[this._$sn].paused
|
||||
this.dispatchEvent({ type: 'pause' })
|
||||
})
|
||||
innerAudioContext.onEnded(() => {
|
||||
this._paused = _innerAudioContextMap[this._$sn].paused
|
||||
if (_innerAudioContextMap[this._$sn].loop === false) {
|
||||
this.dispatchEvent({ type: 'ended' })
|
||||
}
|
||||
this.readyState = HAVE_ENOUGH_DATA
|
||||
})
|
||||
innerAudioContext.onError(() => {
|
||||
this._paused = _innerAudioContextMap[this._$sn].paused
|
||||
this.dispatchEvent({ type: 'error' })
|
||||
})
|
||||
|
||||
if (url) {
|
||||
this.src = url
|
||||
} else {
|
||||
this._src = ''
|
||||
}
|
||||
|
||||
this._loop = innerAudioContext.loop
|
||||
this._autoplay = innerAudioContext.autoplay
|
||||
this._paused = innerAudioContext.paused
|
||||
this._volume = innerAudioContext.volume
|
||||
this._muted = false;
|
||||
}
|
||||
|
||||
addEventListener(type, listener, options = {}) {
|
||||
super.addEventListener(type, listener, options)
|
||||
|
||||
type = String(type).toLowerCase()
|
||||
|
||||
if (this._loaded && this._canplayEvents.indexOf(type) !== -1) {
|
||||
this.dispatchEvent({ type: type })
|
||||
}
|
||||
}
|
||||
|
||||
load() {
|
||||
// console.warn('HTMLAudioElement.load() is not implemented.')
|
||||
// weixin doesn't need call load() manually
|
||||
}
|
||||
|
||||
play() {
|
||||
_innerAudioContextMap[this._$sn].play()
|
||||
}
|
||||
|
||||
resume() {
|
||||
_innerAudioContextMap[this._$sn].resume()
|
||||
}
|
||||
|
||||
pause() {
|
||||
_innerAudioContextMap[this._$sn].pause()
|
||||
}
|
||||
|
||||
stop() {
|
||||
_innerAudioContextMap[this._$sn].stop()
|
||||
}
|
||||
|
||||
destroy() {
|
||||
_innerAudioContextMap[this._$sn].destroy()
|
||||
}
|
||||
|
||||
canPlayType(mediaType = '') {
|
||||
if (typeof mediaType !== 'string') {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (mediaType.indexOf('audio/mpeg') > -1 || mediaType.indexOf('audio/mp4')) {
|
||||
return 'probably'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
get currentTime() {
|
||||
return _innerAudioContextMap[this._$sn].currentTime
|
||||
}
|
||||
|
||||
set currentTime(value) {
|
||||
_innerAudioContextMap[this._$sn].seek(value)
|
||||
}
|
||||
|
||||
get duration () {
|
||||
return _innerAudioContextMap[this._$sn].duration
|
||||
}
|
||||
|
||||
get src() {
|
||||
return this._src
|
||||
}
|
||||
|
||||
set src(value) {
|
||||
this._src = value
|
||||
this._loaded = false
|
||||
this.readyState = this.HAVE_NOTHING
|
||||
|
||||
const innerAudioContext = _innerAudioContextMap[this._$sn]
|
||||
|
||||
innerAudioContext.src = value
|
||||
}
|
||||
|
||||
get loop() {
|
||||
return this._loop
|
||||
}
|
||||
|
||||
set loop(value) {
|
||||
this._loop = value
|
||||
_innerAudioContextMap[this._$sn].loop = value
|
||||
}
|
||||
|
||||
get autoplay() {
|
||||
return this.autoplay
|
||||
}
|
||||
|
||||
set autoplay(value) {
|
||||
this._autoplay = value
|
||||
_innerAudioContextMap[this._$sn].autoplay = value
|
||||
}
|
||||
|
||||
get paused() {
|
||||
return this._paused;
|
||||
}
|
||||
|
||||
get volume() {
|
||||
return this._volume;
|
||||
}
|
||||
|
||||
set volume(value) {
|
||||
this._volume = value;
|
||||
if (!this._muted) {
|
||||
_innerAudioContextMap[this._$sn].volume = value;
|
||||
}
|
||||
}
|
||||
|
||||
get muted() {
|
||||
return this._muted;
|
||||
}
|
||||
|
||||
set muted(value) {
|
||||
this._muted = value;
|
||||
if (value) {
|
||||
_innerAudioContextMap[this._$sn].volume = 0;
|
||||
} else {
|
||||
_innerAudioContextMap[this._$sn].volume = this._volume;
|
||||
}
|
||||
}
|
||||
|
||||
cloneNode() {
|
||||
const newAudio = new Audio()
|
||||
newAudio.loop = this.loop
|
||||
newAudio.autoplay = this.autoplay
|
||||
newAudio.src = this.src
|
||||
return newAudio
|
||||
}
|
||||
}
|
77
adapters/platforms/taobao-minigame/wrapper/builtin/Canvas.js
Normal file
77
adapters/platforms/taobao-minigame/wrapper/builtin/Canvas.js
Normal file
@@ -0,0 +1,77 @@
|
||||
import { innerWidth, innerHeight } from './WindowProperties'
|
||||
|
||||
function Canvas () {}
|
||||
|
||||
let CanvasProxy = new Proxy(Canvas, {
|
||||
construct () {
|
||||
|
||||
const canvas = my.createCanvas()
|
||||
|
||||
canvas.type = 'canvas'
|
||||
|
||||
// canvas.__proto__.__proto__.__proto__ = new HTMLCanvasElement()
|
||||
|
||||
const _getContext = canvas.getContext
|
||||
|
||||
canvas.getBoundingClientRect = () => {
|
||||
const ret = {
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
canvas.style = {
|
||||
top: '0px',
|
||||
left: '0px',
|
||||
width: innerWidth + 'px',
|
||||
height: innerHeight + 'px',
|
||||
}
|
||||
|
||||
canvas.addEventListener = function (type, listener, options = {}) {
|
||||
// console.log('canvas.addEventListener', type);
|
||||
if (my.isIDE) {
|
||||
$global.document.addEventListener(type, listener, options);
|
||||
}
|
||||
}
|
||||
|
||||
canvas.removeEventListener = function (type, listener) {
|
||||
// console.log('canvas.removeEventListener', type);
|
||||
if (my.isIDE) {
|
||||
$global.document.removeEventListener(type, listener);
|
||||
}
|
||||
}
|
||||
|
||||
canvas.dispatchEvent = function (event = {}) {
|
||||
// console.log('canvas.dispatchEvent' , event.type, event);
|
||||
if (my.isIDE) {
|
||||
$global.document.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(canvas, 'clientWidth', {
|
||||
enumerable: true,
|
||||
get: function get() {
|
||||
return innerWidth
|
||||
}
|
||||
})
|
||||
|
||||
Object.defineProperty(canvas, 'clientHeight', {
|
||||
enumerable: true,
|
||||
get: function get() {
|
||||
return innerHeight
|
||||
}
|
||||
})
|
||||
|
||||
return canvas
|
||||
},
|
||||
});
|
||||
|
||||
// Expose the global canvas
|
||||
$global.screencanvas = $global.screencanvas || new CanvasProxy();
|
||||
// NOTE: this is a hack operation
|
||||
// let canvas = new window.Canvas()
|
||||
// console.error(canvas instanceof window.Canvas) => false
|
||||
export default CanvasProxy;
|
@@ -0,0 +1,10 @@
|
||||
import Node from './Node'
|
||||
|
||||
export default class Element extends Node {
|
||||
className = ''
|
||||
children = []
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
}
|
||||
}
|
14
adapters/platforms/taobao-minigame/wrapper/builtin/Event.js
Normal file
14
adapters/platforms/taobao-minigame/wrapper/builtin/Event.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import {noop} from './util'
|
||||
|
||||
export default class Event {
|
||||
cancelBubble = false
|
||||
cancelable = false
|
||||
target = null
|
||||
timestampe = Date.now()
|
||||
preventDefault = noop
|
||||
stopPropagation = noop
|
||||
|
||||
constructor(type) {
|
||||
this.type = type
|
||||
}
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
const _events = new WeakMap()
|
||||
|
||||
export default class EventTarget {
|
||||
constructor() {
|
||||
_events.set(this, {})
|
||||
}
|
||||
|
||||
addEventListener(type, listener, options = {}) {
|
||||
let events = _events.get(this)
|
||||
|
||||
if (!events) {
|
||||
events = {}
|
||||
_events.set(this, events)
|
||||
}
|
||||
if (!events[type]) {
|
||||
events[type] = []
|
||||
}
|
||||
events[type].push(listener)
|
||||
|
||||
if (options.capture) {
|
||||
// console.warn('EventTarget.addEventListener: options.capture is not implemented.')
|
||||
}
|
||||
if (options.once) {
|
||||
// console.warn('EventTarget.addEventListener: options.once is not implemented.')
|
||||
}
|
||||
if (options.passive) {
|
||||
// console.warn('EventTarget.addEventListener: options.passive is not implemented.')
|
||||
}
|
||||
}
|
||||
|
||||
removeEventListener(type, listener) {
|
||||
const events = _events.get(this)
|
||||
|
||||
if (events) {
|
||||
const listeners = events[type]
|
||||
|
||||
if (listeners && listeners.length > 0) {
|
||||
for (let i = listeners.length; i--; i > 0) {
|
||||
if (listeners[i] === listener) {
|
||||
listeners.splice(i, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dispatchEvent(event = {}) {
|
||||
const listeners = _events.get(this)[event.type]
|
||||
|
||||
if (listeners) {
|
||||
for (let i = 0; i < listeners.length; i++) {
|
||||
listeners[i](event)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
import HTMLElement from './HTMLElement'
|
||||
|
||||
export default class HTMLAudioElement extends HTMLElement {
|
||||
constructor() {
|
||||
super('audio')
|
||||
}
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
import "./Canvas"
|
||||
let HTMLCanvasElement = $global.screencanvas.constructor;
|
||||
|
||||
export default HTMLCanvasElement;
|
@@ -0,0 +1,54 @@
|
||||
import Element from './Element'
|
||||
import { noop } from './util/index.js'
|
||||
import { innerWidth, innerHeight } from './WindowProperties'
|
||||
|
||||
export default class HTMLElement extends Element {
|
||||
className = ''
|
||||
childern = []
|
||||
style = {
|
||||
width: `${innerWidth}px`,
|
||||
height: `${innerHeight}px`
|
||||
}
|
||||
|
||||
insertBefore = noop
|
||||
|
||||
innerHTML = ''
|
||||
|
||||
constructor(tagName = '') {
|
||||
super()
|
||||
this.tagName = tagName.toUpperCase()
|
||||
}
|
||||
|
||||
setAttribute(name, value) {
|
||||
this[name] = value
|
||||
}
|
||||
|
||||
getAttribute(name) {
|
||||
return this[name]
|
||||
}
|
||||
|
||||
get clientWidth() {
|
||||
const ret = parseInt(this.style.fontSize, 10) * this.innerHTML.length
|
||||
|
||||
return Number.isNaN(ret) ? 0 : ret
|
||||
}
|
||||
|
||||
get clientHeight() {
|
||||
const ret = parseInt(this.style.fontSize, 10)
|
||||
|
||||
return Number.isNaN(ret) ? 0 : ret
|
||||
}
|
||||
|
||||
getBoundingClientRect() {
|
||||
return {
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: innerWidth,
|
||||
height: innerHeight
|
||||
}
|
||||
}
|
||||
|
||||
focus() {
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
var screencanvas = $global.screencanvas;
|
||||
let HTMLImageElement = screencanvas.createImage().constructor;
|
||||
|
||||
export default HTMLImageElement;
|
@@ -0,0 +1,7 @@
|
||||
import './Canvas'
|
||||
|
||||
function Image () {
|
||||
return $global.screencanvas.createImage();
|
||||
}
|
||||
|
||||
export default Image;
|
@@ -0,0 +1,5 @@
|
||||
export default class ImageBitmap {
|
||||
constructor() {
|
||||
// TODO
|
||||
}
|
||||
}
|
34
adapters/platforms/taobao-minigame/wrapper/builtin/Node.js
Normal file
34
adapters/platforms/taobao-minigame/wrapper/builtin/Node.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import EventTarget from './EventTarget.js'
|
||||
|
||||
export default class Node extends EventTarget {
|
||||
constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
childNodes = []
|
||||
|
||||
appendChild(node) {
|
||||
this.childNodes.push(node)
|
||||
// if (node instanceof Node) {
|
||||
// this.childNodes.push(node)
|
||||
// } else {
|
||||
// throw new TypeError('Failed to executed \'appendChild\' on \'Node\': parameter 1 is not of type \'Node\'.')
|
||||
// }
|
||||
}
|
||||
|
||||
cloneNode() {
|
||||
const copyNode = Object.create(this)
|
||||
|
||||
Object.assign(copyNode, this)
|
||||
return copyNode
|
||||
}
|
||||
|
||||
removeChild(node) {
|
||||
const index = this.childNodes.findIndex((child) => child === node)
|
||||
|
||||
if (index > -1) {
|
||||
return this.childNodes.splice(index, 1)
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
export default class WebGLRenderingContext {
|
||||
constructor() {
|
||||
// TODO
|
||||
}
|
||||
}
|
139
adapters/platforms/taobao-minigame/wrapper/builtin/WebSocket.js
Normal file
139
adapters/platforms/taobao-minigame/wrapper/builtin/WebSocket.js
Normal file
@@ -0,0 +1,139 @@
|
||||
const _utils = require('../../../../common/utils');
|
||||
|
||||
const MAX_AMOUNT_WEBSOCKET = 1 // The maximum number of WEBSOCKET
|
||||
let CURR_AMOUNT_WEBSOCKET = 0 // The current number of WEBSOCKET
|
||||
|
||||
export default class WebSocket {
|
||||
static CONNECTING = 0 // The connection is not yet open.
|
||||
static OPEN = 1 // The connection is open and ready to communicate.
|
||||
static CLOSING = 2 // The connection is in the process of closing.
|
||||
static CLOSED = 3 // The connection is closed or couldn't be opened.
|
||||
|
||||
binaryType = '' // TODO 更新 binaryType
|
||||
bufferedAmount = 0 // TODO 更新 bufferedAmount
|
||||
extensions = ''
|
||||
|
||||
onopen = null
|
||||
onmessage = null
|
||||
onerror = null
|
||||
onclose = null
|
||||
|
||||
_onMessage = null
|
||||
_onOpen = null
|
||||
_onError = null
|
||||
_onClose = null
|
||||
_isReduced = false
|
||||
|
||||
protocol = '' // TODO 小程序内目前获取不到,实际上需要根据服务器选择的 sub-protocol 返回
|
||||
readyState = 3
|
||||
|
||||
constructor(url, protocols = []) {
|
||||
if(this._isMaxCount()){
|
||||
console.warn(`Failed to construct 'WebSocket': Only ${CURR_AMOUNT_WEBSOCKET} WebSocket can be created at the same time on TaoBao.`);
|
||||
return this;
|
||||
}
|
||||
|
||||
if (typeof url !== 'string' || !(/(^ws:\/\/)|(^wss:\/\/)/).test(url)) {
|
||||
throw new TypeError(`Failed to construct 'WebSocket': The URL '${url}' is invalid`)
|
||||
}
|
||||
|
||||
this.url = url
|
||||
this.readyState = WebSocket.CONNECTING
|
||||
this._increaseCount();
|
||||
|
||||
my.connectSocket({
|
||||
url,
|
||||
fail: function fail(res) {
|
||||
this._triggerEvent('error', res)
|
||||
}
|
||||
})
|
||||
|
||||
this._onOpen = (res) => {
|
||||
this.readyState = WebSocket.OPEN
|
||||
this._triggerEvent('open')
|
||||
}
|
||||
my.onSocketOpen(this._onOpen)
|
||||
|
||||
this._onMessage = (res) => {
|
||||
if (res && res.data && res.isBuffer) {
|
||||
res.data = _utils.base64ToArrayBuffer(res.data)
|
||||
}
|
||||
this._triggerEvent('message', res)
|
||||
}
|
||||
my.onSocketMessage(this._onMessage)
|
||||
|
||||
this._onError = (res) => {
|
||||
this._triggerEvent('error', res)
|
||||
this._decreaseCount();
|
||||
}
|
||||
my.onSocketError(this._onError)
|
||||
|
||||
this._onClose = (res) => {
|
||||
this.readyState = WebSocket.CLOSED
|
||||
this._triggerEvent('close')
|
||||
this._removeAllSocketListenr()
|
||||
this._decreaseCount();
|
||||
}
|
||||
my.onSocketClose(this._onClose)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
close() {
|
||||
this.readyState = WebSocket.CLOSING
|
||||
my.closeSocket()
|
||||
}
|
||||
|
||||
send(data) {
|
||||
if (typeof data !== 'string' && !(data instanceof ArrayBuffer) && !ArrayBuffer.isView(data)) {
|
||||
throw new TypeError(`Failed to send message: The data ${data} is invalid`)
|
||||
}else{
|
||||
var isBuffer = false;
|
||||
if (data instanceof ArrayBuffer) {
|
||||
data = _utils.arrayBufferToBase64(data)
|
||||
isBuffer = true
|
||||
}
|
||||
|
||||
my.sendSocketMessage({
|
||||
data,
|
||||
isBuffer,
|
||||
fail: function (res) {
|
||||
this._triggerEvent('error', res)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_triggerEvent(type, ...args) {
|
||||
if (typeof this[`on${type}`] === 'function') {
|
||||
this[`on${type}`].apply(this, args)
|
||||
}
|
||||
}
|
||||
|
||||
_removeAllSocketListenr(){
|
||||
my.offSocketOpen(this._onOpen)
|
||||
my.offSocketMessage(this._onMessage)
|
||||
my.offSocketError(this._onError)
|
||||
my.offSocketClose(this._onClose)
|
||||
|
||||
this._onOpen = null
|
||||
this._onMessage = null
|
||||
this._onError = null
|
||||
this._onClose = null
|
||||
}
|
||||
|
||||
_increaseCount(){
|
||||
CURR_AMOUNT_WEBSOCKET += 1
|
||||
}
|
||||
|
||||
_decreaseCount(){
|
||||
if(!this._isReduced){
|
||||
CURR_AMOUNT_WEBSOCKET -= 1
|
||||
this._isReduced = true
|
||||
}
|
||||
}
|
||||
|
||||
_isMaxCount(){
|
||||
return CURR_AMOUNT_WEBSOCKET >= MAX_AMOUNT_WEBSOCKET
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
const { pixelRatio, windowWidth, windowHeight } = my.getSystemInfoSync()
|
||||
const devicePixelRatio = pixelRatio;
|
||||
|
||||
let width, height;
|
||||
{
|
||||
width = windowWidth;
|
||||
height = windowHeight;
|
||||
}
|
||||
export const innerWidth = width;
|
||||
export const innerHeight = height;
|
||||
export { devicePixelRatio }
|
||||
export const screen = {
|
||||
width,
|
||||
height,
|
||||
availWidth: innerWidth,
|
||||
availHeight: innerHeight,
|
||||
availLeft: 0,
|
||||
availTop: 0,
|
||||
}
|
||||
|
||||
export const performance = {
|
||||
now: Date.now
|
||||
};
|
||||
|
||||
export const ontouchstart = null;
|
||||
export const ontouchmove = null;
|
||||
export const ontouchend = null;
|
@@ -0,0 +1,136 @@
|
||||
import EventTarget from './EventTarget.js'
|
||||
|
||||
const _url = new WeakMap()
|
||||
const _method = new WeakMap()
|
||||
const _requestHeader = new WeakMap()
|
||||
const _responseHeader = new WeakMap()
|
||||
const _requestTask = new WeakMap()
|
||||
|
||||
function _triggerEvent(type, ...args) {
|
||||
if (typeof this[`on${type}`] === 'function') {
|
||||
this[`on${type}`].apply(this, args)
|
||||
}
|
||||
}
|
||||
|
||||
function _changeReadyState(readyState) {
|
||||
this.readyState = readyState
|
||||
_triggerEvent.call(this, 'readystatechange')
|
||||
}
|
||||
|
||||
export default class XMLHttpRequest extends EventTarget {
|
||||
// TODO 没法模拟 HEADERS_RECEIVED 和 LOADING 两个状态
|
||||
static UNSEND = 0
|
||||
static OPENED = 1
|
||||
static HEADERS_RECEIVED = 2
|
||||
static LOADING = 3
|
||||
static DONE = 4
|
||||
|
||||
timeout = 0;
|
||||
/*
|
||||
* TODO 这一批事件应该是在 XMLHttpRequestEventTarget.prototype 上面的
|
||||
*/
|
||||
onabort = null
|
||||
onerror = null
|
||||
onload = null
|
||||
onloadstart = null
|
||||
onprogress = null
|
||||
ontimeout = null
|
||||
onloadend = null
|
||||
|
||||
onreadystatechange = null
|
||||
readyState = 0
|
||||
response = null
|
||||
responseText = null
|
||||
responseType = ''
|
||||
responseXML = null
|
||||
status = 0
|
||||
statusText = ''
|
||||
upload = {}
|
||||
withCredentials = false
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
_requestHeader.set(this, {
|
||||
'content-type': 'application/json'
|
||||
})
|
||||
_responseHeader.set(this, {})
|
||||
}
|
||||
|
||||
abort() {
|
||||
const myRequestTask = _requestTask.get(this)
|
||||
|
||||
if (myRequestTask) {
|
||||
myRequestTask.abort()
|
||||
}
|
||||
}
|
||||
|
||||
getAllResponseHeaders() {
|
||||
const responseHeader = _responseHeader.get(this)
|
||||
|
||||
return Object.keys(responseHeader).map((header) => {
|
||||
return `${header}: ${responseHeader[header]}`
|
||||
}).join('\n')
|
||||
}
|
||||
|
||||
getResponseHeader(header) {
|
||||
return _responseHeader.get(this)[header]
|
||||
}
|
||||
|
||||
open(method, url/* async, user, password 这几个参数在小程序内不支持*/) {
|
||||
_method.set(this, method)
|
||||
_url.set(this, url)
|
||||
_changeReadyState.call(this, XMLHttpRequest.OPENED)
|
||||
}
|
||||
|
||||
overrideMimeType() {
|
||||
}
|
||||
|
||||
send(data = '') {
|
||||
if (this.readyState !== XMLHttpRequest.OPENED) {
|
||||
throw new Error("Failed to execute 'send' on 'XMLHttpRequest': The object's state must be OPENED.")
|
||||
} else {
|
||||
let myRequestTask = my.tb.request({
|
||||
body: JSON.stringify(data),
|
||||
url: _url.get(this),
|
||||
method: _method.get(this),
|
||||
headers: _requestHeader.get(this),
|
||||
options: {timeout: this.timeout, enableSystemParams: true},
|
||||
success: (res) => {
|
||||
this.status = res.code;
|
||||
this.responseText = this.response = res.content;
|
||||
_responseHeader.set(this, _requestHeader.get(this))
|
||||
_triggerEvent.call(this, 'loadstart')
|
||||
_changeReadyState.call(this, XMLHttpRequest.HEADERS_RECEIVED)
|
||||
_changeReadyState.call(this, XMLHttpRequest.LOADING)
|
||||
_changeReadyState.call(this, XMLHttpRequest.DONE)
|
||||
_triggerEvent.call(this, 'load')
|
||||
_triggerEvent.call(this, 'loadend')
|
||||
},
|
||||
fail: (res) => {
|
||||
_triggerEvent.call(this, 'error', res)
|
||||
_triggerEvent.call(this, 'loadend')
|
||||
}
|
||||
})
|
||||
|
||||
_requestTask.set(this, myRequestTask);
|
||||
}
|
||||
}
|
||||
|
||||
setRequestHeader(header, value) {
|
||||
const myHeader = _requestHeader.get(this)
|
||||
|
||||
myHeader[header] = value
|
||||
_requestHeader.set(this, myHeader)
|
||||
}
|
||||
|
||||
addEventListener(type, listener) {
|
||||
if (typeof listener === 'function') {
|
||||
let _this = this
|
||||
let event = { target: _this }
|
||||
this['on' + type] = function (event) {
|
||||
listener.call(_this, event)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
let screencanvas = $global.screencanvas;
|
||||
let cancelAnimationFrame = screencanvas.cancelAnimationFrame.bind(screencanvas);
|
||||
|
||||
export default cancelAnimationFrame;
|
124
adapters/platforms/taobao-minigame/wrapper/builtin/document.js
Normal file
124
adapters/platforms/taobao-minigame/wrapper/builtin/document.js
Normal file
@@ -0,0 +1,124 @@
|
||||
import * as _window from './window'
|
||||
import HTMLElement from './HTMLElement'
|
||||
import Image from './Image'
|
||||
import * as Canvas from './Canvas'
|
||||
import Audio from './Audio'
|
||||
|
||||
const events = {}
|
||||
|
||||
var document = {
|
||||
readyState: 'complete',
|
||||
visibilityState: 'visible',
|
||||
documentElement: _window,
|
||||
hidden: false,
|
||||
style: {},
|
||||
location: _window.location,
|
||||
ontouchstart: null,
|
||||
ontouchmove: null,
|
||||
ontouchend: null,
|
||||
|
||||
head: new HTMLElement('head'),
|
||||
body: new HTMLElement('body'),
|
||||
|
||||
createElement(tagName) {
|
||||
tagName = tagName.toLowerCase();
|
||||
if (tagName === 'canvas') {
|
||||
return new Canvas()
|
||||
} else if (tagName === 'audio') {
|
||||
return new Audio()
|
||||
} else if (tagName === 'img') {
|
||||
return new Image()
|
||||
}
|
||||
|
||||
return new HTMLElement(tagName)
|
||||
},
|
||||
|
||||
createElementNS(nameSpace, tagName) {
|
||||
return this.createElement(tagName);
|
||||
},
|
||||
|
||||
getElementById(id) {
|
||||
if (id === _window.canvas.id) {
|
||||
return _window.canvas
|
||||
}
|
||||
return null
|
||||
},
|
||||
|
||||
getElementsByTagName(tagName) {
|
||||
if (tagName === 'head') {
|
||||
return [document.head]
|
||||
} else if (tagName === 'body') {
|
||||
return [document.body]
|
||||
} else if (tagName === 'canvas') {
|
||||
return [_window.canvas]
|
||||
}
|
||||
return []
|
||||
},
|
||||
|
||||
getElementsByName(tagName) {
|
||||
if (tagName === 'head') {
|
||||
return [document.head]
|
||||
} else if (tagName === 'body') {
|
||||
return [document.body]
|
||||
} else if (tagName === 'canvas') {
|
||||
return [_window.canvas]
|
||||
}
|
||||
return []
|
||||
},
|
||||
|
||||
querySelector(query) {
|
||||
if (query === 'head') {
|
||||
return document.head
|
||||
} else if (query === 'body') {
|
||||
return document.body
|
||||
} else if (query === 'canvas') {
|
||||
return _window.canvas
|
||||
} else if (query === `#${_window.canvas.id}`) {
|
||||
return _window.canvas
|
||||
}
|
||||
return null
|
||||
},
|
||||
|
||||
querySelectorAll(query) {
|
||||
if (query === 'head') {
|
||||
return [document.head]
|
||||
} else if (query === 'body') {
|
||||
return [document.body]
|
||||
} else if (query === 'canvas') {
|
||||
return [_window.canvas]
|
||||
}
|
||||
return []
|
||||
},
|
||||
|
||||
addEventListener(type, listener) {
|
||||
if (!events[type]) {
|
||||
events[type] = []
|
||||
}
|
||||
events[type].push(listener)
|
||||
},
|
||||
|
||||
removeEventListener(type, listener) {
|
||||
const listeners = events[type]
|
||||
|
||||
if (listeners && listeners.length > 0) {
|
||||
for (let i = listeners.length; i--; i > 0) {
|
||||
if (listeners[i] === listener) {
|
||||
listeners.splice(i, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
dispatchEvent(event) {
|
||||
const listeners = events[event.type]
|
||||
|
||||
if (listeners) {
|
||||
for (let i = 0; i < listeners.length; i++) {
|
||||
listeners[i](event)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default document
|
61
adapters/platforms/taobao-minigame/wrapper/builtin/index.js
Normal file
61
adapters/platforms/taobao-minigame/wrapper/builtin/index.js
Normal file
@@ -0,0 +1,61 @@
|
||||
import * as _window from './window'
|
||||
import * as _document from './document'
|
||||
|
||||
var global = $global;
|
||||
|
||||
function inject () {
|
||||
// 暴露全局的 canvas
|
||||
_window.canvas = $global.screencanvas;
|
||||
_window.document = _document;
|
||||
|
||||
_window.addEventListener = (type, listener) => {
|
||||
_window.document.addEventListener(type, listener)
|
||||
}
|
||||
_window.removeEventListener = (type, listener) => {
|
||||
_window.document.removeEventListener(type, listener)
|
||||
}
|
||||
_window.dispatchEvent = _window.document.dispatchEvent;
|
||||
|
||||
const { platform } = my.getSystemInfoSync()
|
||||
|
||||
// 开发者工具无法重定义 window
|
||||
if (typeof __devtoolssubcontext === 'undefined' && platform === 'devtools') {
|
||||
for (const key in _window) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(global, key)
|
||||
|
||||
if (!descriptor || descriptor.configurable === true) {
|
||||
Object.defineProperty(window, key, {
|
||||
value: _window[key]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for (const key in _window.document) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(global.document, key)
|
||||
|
||||
if (!descriptor || descriptor.configurable === true) {
|
||||
Object.defineProperty(global.document, key, {
|
||||
value: _window.document[key]
|
||||
})
|
||||
}
|
||||
}
|
||||
window.parent = window
|
||||
} else {
|
||||
for (const key in _window) {
|
||||
global[key] = _window[key]
|
||||
}
|
||||
global.window = _window
|
||||
window = global
|
||||
window.top = window.parent = window
|
||||
}
|
||||
|
||||
global.setTimeout = setTimeout;
|
||||
global.clearTimeout = clearTimeout;
|
||||
global.setInterval = setInterval;
|
||||
global.clearInterval = clearInterval;
|
||||
}
|
||||
|
||||
if (!global.__isAdapterInjected) {
|
||||
global.__isAdapterInjected = true
|
||||
inject()
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
const localStorage = {
|
||||
get length() {
|
||||
const { keys } = my.getStorageInfoSync()
|
||||
|
||||
return keys.length
|
||||
},
|
||||
|
||||
key(n) {
|
||||
const { keys } = my.getStorageInfoSync()
|
||||
|
||||
return keys[n]
|
||||
},
|
||||
|
||||
getItem(key) {
|
||||
let ret = my.getStorageSync({
|
||||
key,
|
||||
});
|
||||
return ret && ret.data;
|
||||
},
|
||||
|
||||
setItem(key, data) {
|
||||
return my.setStorageSync({
|
||||
key,
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
removeItem(key) {
|
||||
my.removeStorageSync(key)
|
||||
},
|
||||
|
||||
clear() {
|
||||
my.clearStorageSync()
|
||||
}
|
||||
}
|
||||
|
||||
export default localStorage
|
@@ -0,0 +1,7 @@
|
||||
var location = {
|
||||
href: 'game.js',
|
||||
reload() {
|
||||
}
|
||||
}
|
||||
|
||||
export default location
|
@@ -0,0 +1,38 @@
|
||||
import { noop } from './util/index.js'
|
||||
|
||||
// TODO 需要 my.getSystemInfo 获取更详细信息
|
||||
const systemInfo = my.getSystemInfoSync()
|
||||
console.log(systemInfo)
|
||||
|
||||
const system = systemInfo.system;
|
||||
const platform = systemInfo.platform;
|
||||
const language = systemInfo.language;
|
||||
const version = systemInfo.version;
|
||||
|
||||
const android = system ? system.toLowerCase().indexOf('android') !== -1 : false;
|
||||
|
||||
const uaDesc = android ? `Android; CPU ${system}` : `iPhone; CPU iPhone OS ${system} like Mac OS X`;
|
||||
const ua = `Mozilla/5.0 (${uaDesc}) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E8301 MicroMessenger/${version} MiniGame NetType/WIFI Language/${language}`;
|
||||
|
||||
const navigator = {
|
||||
platform,
|
||||
language: language,
|
||||
appVersion: `5.0 (${uaDesc}) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1`,
|
||||
userAgent: ua,
|
||||
onLine: true, // TODO 用 my.getNetworkStateChange 和 my.onNetworkStateChange 来返回真实的状态
|
||||
|
||||
// TODO 用 my.getLocation 来封装 geolocation
|
||||
geolocation: {
|
||||
getCurrentPosition: noop,
|
||||
watchPosition: noop,
|
||||
clearWatch: noop
|
||||
}
|
||||
}
|
||||
|
||||
if (my.onNetworkStatusChange) {
|
||||
my.onNetworkStatusChange(function(event){
|
||||
navigator.onLine = event.isConnected;
|
||||
});
|
||||
}
|
||||
|
||||
export default navigator
|
@@ -0,0 +1,4 @@
|
||||
let screencanvas = $global.screencanvas;
|
||||
let requestAnimationFrame = screencanvas.requestAnimationFrame.bind(screencanvas);
|
||||
|
||||
export default requestAnimationFrame;
|
@@ -0,0 +1 @@
|
||||
export function noop() {}
|
15
adapters/platforms/taobao-minigame/wrapper/builtin/window.js
Normal file
15
adapters/platforms/taobao-minigame/wrapper/builtin/window.js
Normal file
@@ -0,0 +1,15 @@
|
||||
export navigator from './navigator'
|
||||
export XMLHttpRequest from './XMLHttpRequest'
|
||||
export WebSocket from './WebSocket'
|
||||
export Image from './Image'
|
||||
export ImageBitmap from './ImageBitmap'
|
||||
export HTMLElement from './HTMLElement'
|
||||
export HTMLCanvasElement from './HTMLCanvasElement'
|
||||
export HTMLImageElement from './HTMLImageElement'
|
||||
export WebGLRenderingContext from './WebGLRenderingContext'
|
||||
export localStorage from './localStorage'
|
||||
export location from './location'
|
||||
export requestAnimationFrame from './requestAnimationFrame'
|
||||
export cancelAnimationFrame from './cancelAnimationFrame'
|
||||
export * from './WindowProperties'
|
||||
|
@@ -0,0 +1,108 @@
|
||||
const screencanvas = $global.screencanvas;
|
||||
const parser = cc.assetManager.parser;
|
||||
const downloader = cc.assetManager.downloader;
|
||||
|
||||
function parseParameters (options, onProgress, onComplete) {
|
||||
if (onComplete === undefined) {
|
||||
var isCallback = typeof options === 'function';
|
||||
if (onProgress) {
|
||||
onComplete = onProgress;
|
||||
if (!isCallback) {
|
||||
onProgress = null;
|
||||
}
|
||||
}
|
||||
else if (onProgress === undefined && isCallback) {
|
||||
onComplete = options;
|
||||
options = null;
|
||||
onProgress = null;
|
||||
}
|
||||
if (onProgress !== undefined && isCallback) {
|
||||
onProgress = options;
|
||||
options = null;
|
||||
}
|
||||
}
|
||||
options = options || Object.create(null);
|
||||
return { options, onProgress, onComplete };
|
||||
}
|
||||
|
||||
function doNothing (url, options, onComplete) {
|
||||
onComplete(null, url);
|
||||
}
|
||||
|
||||
downloader.downloadDomAudio = doNothing;
|
||||
|
||||
function downloadImage (url, options, onComplete) {
|
||||
const parameters = parseParameters(options, undefined, onComplete);
|
||||
options = parameters.options;
|
||||
onComplete = parameters.onComplete;
|
||||
|
||||
const img = screencanvas.createImage();
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
clearEvent();
|
||||
onComplete && onComplete(new Error(cc.debug.getError(4930, url)));
|
||||
}, 8000);
|
||||
function clearEvent () {
|
||||
img.onload = null;
|
||||
// img.onerror = null;
|
||||
}
|
||||
function loadCallback () {
|
||||
clearEvent();
|
||||
clearTimeout(timer);
|
||||
onComplete && onComplete(null, img);
|
||||
}
|
||||
|
||||
function errorCallback () {
|
||||
clearEvent();
|
||||
clearTimeout(timer);
|
||||
onComplete && onComplete(new Error(cc.debug.getError(4930, url)));
|
||||
}
|
||||
|
||||
img.onload = loadCallback;
|
||||
// NOTE: crash when registering error callback
|
||||
// img.onerror = errorCallback;
|
||||
img.src = url;
|
||||
return img;
|
||||
}
|
||||
downloader.downloadDomImage = downloadImage;
|
||||
|
||||
downloader.register({
|
||||
// Audio
|
||||
'.mp3' : doNothing,
|
||||
'.ogg' : doNothing,
|
||||
'.wav' : doNothing,
|
||||
'.m4a' : doNothing,
|
||||
|
||||
// Image
|
||||
'.png' : doNothing,
|
||||
'.jpg' : doNothing,
|
||||
'.bmp' : doNothing,
|
||||
'.jpeg' : doNothing,
|
||||
'.gif' : doNothing,
|
||||
'.ico' : doNothing,
|
||||
'.tiff' : doNothing,
|
||||
'.image' : doNothing,
|
||||
'.webp' : doNothing,
|
||||
'.pvr': doNothing,
|
||||
'.pkm': doNothing,
|
||||
'.astc': doNothing,
|
||||
});
|
||||
|
||||
parser.register({
|
||||
// Audio
|
||||
'.mp3' : doNothing,
|
||||
'.ogg' : doNothing,
|
||||
'.wav' : doNothing,
|
||||
'.m4a' : doNothing,
|
||||
|
||||
// Image
|
||||
'.png' : downloadImage,
|
||||
'.jpg' : downloadImage,
|
||||
'.bmp' : downloadImage,
|
||||
'.jpeg' : downloadImage,
|
||||
'.gif' : downloadImage,
|
||||
'.ico' : downloadImage,
|
||||
'.tiff' : downloadImage,
|
||||
'.image' : downloadImage,
|
||||
'.webp' : downloadImage,
|
||||
});
|
171
adapters/platforms/taobao-minigame/wrapper/engine/Audio.js
Normal file
171
adapters/platforms/taobao-minigame/wrapper/engine/Audio.js
Normal file
@@ -0,0 +1,171 @@
|
||||
const game = cc.game;
|
||||
const EventTarget = cc.EventTarget;
|
||||
|
||||
const State = {
|
||||
ERROR: -1,
|
||||
INITIALZING: 0,
|
||||
PLAYING: 1,
|
||||
PAUSED: 2,
|
||||
STOPPED: 3,
|
||||
}
|
||||
|
||||
function Audio (url, serializedDuration) {
|
||||
this._nativeAudio = my.createInnerAudioContext();
|
||||
this._et = new EventTarget();
|
||||
this.reset();
|
||||
this._setSrc(url);
|
||||
const nativeAudio = this._nativeAudio;
|
||||
this._serializedDuration = serializedDuration;
|
||||
this._ensureLoaded(() => {
|
||||
this._duration = nativeAudio.duration;
|
||||
});
|
||||
this._duration = 1;
|
||||
this._onShow = () => {
|
||||
if (this._blocked) {
|
||||
this._nativeAudio.play();
|
||||
}
|
||||
this._blocked = false;
|
||||
};
|
||||
this._onHide = () => {
|
||||
if (this.getState() === State.PLAYING) {
|
||||
this._nativeAudio.pause();
|
||||
this._blocked = true;
|
||||
}
|
||||
};
|
||||
nativeAudio.onCanplay(() => { this._et.emit('load'); });
|
||||
nativeAudio.onError((err) => { this._et.emit('error', err); });
|
||||
nativeAudio.onEnded(() => {
|
||||
this.finishCB && this.finishCB();
|
||||
this._state = State.INITIALZING;
|
||||
this._et.emit('ended');
|
||||
});
|
||||
nativeAudio.onStop(() => { this._et.emit('stop'); });
|
||||
nativeAudio.onTimeUpdate(() => { this._currentTime = nativeAudio.currentTime; });
|
||||
game.on(game.EVENT_SHOW, this._onShow);
|
||||
game.on(game.EVENT_HIDE, this._onHide);
|
||||
this.onError((err) => { cc.error(err); });
|
||||
}
|
||||
|
||||
Audio.State = State;
|
||||
|
||||
Object.assign(Audio.prototype, {
|
||||
|
||||
reset () {
|
||||
this.id = -1;
|
||||
this.finishCB = null; // For audioEngine custom ended callback.
|
||||
this._state = State.INITIALZING;
|
||||
this._loop = false;
|
||||
this._currentTime = 0;
|
||||
this._volume = 1;
|
||||
this._blocked = false;
|
||||
this._loaded = false;
|
||||
|
||||
this.offLoad();
|
||||
this.offError();
|
||||
this.offEnded();
|
||||
this.offStop();
|
||||
},
|
||||
|
||||
destroy () {
|
||||
this.reset();
|
||||
game.off(game.EVENT_SHOW, this._onShow);
|
||||
game.off(game.EVENT_HIDE, this._onHide);
|
||||
// offCanplay offOnError offStop offEnded is not supported for now.
|
||||
|
||||
this._nativeAudio.destroy();
|
||||
this._nativeAudio = null;
|
||||
},
|
||||
|
||||
getSrc () { return this._src; },
|
||||
// NOTE: don't set src twice, which is not supported on TAOBAO
|
||||
_setSrc (path) {
|
||||
if (this._src === path) {
|
||||
return;
|
||||
}
|
||||
const nativeAudio = this._nativeAudio;
|
||||
this._loaded = false;
|
||||
nativeAudio.src = path;
|
||||
this._src = path;
|
||||
},
|
||||
getState () { return this._state; },
|
||||
getDuration () { return this._serializedDuration ? this._serializedDuration : this._duration; },
|
||||
getCurrentTime () { return this._currentTime; },
|
||||
seek (val) {
|
||||
if (this._currentTime === val) {
|
||||
return;
|
||||
}
|
||||
this._ensureLoaded(() => {
|
||||
this._nativeAudio.seek(val);
|
||||
this._currentTime = val;
|
||||
});
|
||||
},
|
||||
getLoop () { return this._loop; },
|
||||
setLoop (val) {
|
||||
if (this._loop === val) {
|
||||
return;
|
||||
}
|
||||
this._ensureLoaded(() => {
|
||||
this._nativeAudio.loop = val;
|
||||
this._loop = val;
|
||||
});
|
||||
},
|
||||
getVolume () { return this._volume; },
|
||||
setVolume (val) {
|
||||
if (this._volume === val) {
|
||||
return;
|
||||
}
|
||||
this._ensureLoaded(() => {
|
||||
this._nativeAudio.volume = val;
|
||||
this._volume = val;
|
||||
});
|
||||
},
|
||||
|
||||
play () {
|
||||
if (this.getState() !== State.PLAYING) {
|
||||
this._nativeAudio.play();
|
||||
this._state = State.PLAYING;
|
||||
}
|
||||
},
|
||||
resume () {
|
||||
if (this.getState() === State.PAUSED) {
|
||||
this._nativeAudio.play();
|
||||
this._state = State.PLAYING;
|
||||
}
|
||||
},
|
||||
pause () {
|
||||
if (this.getState() === State.PLAYING) {
|
||||
this._nativeAudio.pause();
|
||||
this._state = State.PAUSED;
|
||||
}
|
||||
},
|
||||
stop () {
|
||||
// NOTE: On taobao, it is designed that audio is useless after stopping.
|
||||
// this._nativeAudio.stop();
|
||||
this._nativeAudio.pause();
|
||||
this._nativeAudio.seek(0);
|
||||
this._state = State.STOPPED;
|
||||
},
|
||||
|
||||
onceLoad (cb) { this._et.once('load', cb); },
|
||||
onLoad (cb) { this._et.on('load', cb); },
|
||||
offLoad (cb = undefined) { this._et.off('load', cb); },
|
||||
onError (cb) { this._et.on('error', cb); },
|
||||
offError (cb = undefined) { this._et.off('error', cb); },
|
||||
onEnded (cb) { this._et.on('ended', cb); },
|
||||
offEnded (cb = undefined) { this._et.off('ended', cb); },
|
||||
onStop (cb) { this._et.on('stop', cb); },
|
||||
offStop (cb = undefined) { this._et.off('stop', cb); },
|
||||
|
||||
_ensureLoaded (cb) {
|
||||
if (this._loaded) {
|
||||
cb();
|
||||
} else {
|
||||
this.onceLoad(() => {
|
||||
this._loaded = true;
|
||||
cb();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Audio;
|
389
adapters/platforms/taobao-minigame/wrapper/engine/AudioEngine.js
Normal file
389
adapters/platforms/taobao-minigame/wrapper/engine/AudioEngine.js
Normal file
@@ -0,0 +1,389 @@
|
||||
const Audio = require('./Audio');
|
||||
|
||||
let _instanceId = 0;
|
||||
const _id2audio = {};
|
||||
const _audioPool = [];
|
||||
const _maxPoolSize = 32;
|
||||
|
||||
function handleVolume (volume) {
|
||||
if (volume === undefined) {
|
||||
// set default volume as 1
|
||||
volume = 1;
|
||||
}
|
||||
else if (typeof volume === 'string') {
|
||||
volume = Number.parseFloat(volume);
|
||||
}
|
||||
return volume;
|
||||
};
|
||||
|
||||
function getOrCreateAudio (path, serializedDuration) {
|
||||
let audio;
|
||||
_audioPool.some((item, index) => {
|
||||
if (item.getSrc() === path) {
|
||||
audio = item;
|
||||
_audioPool.splice(index, 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (!audio) {
|
||||
audio = new Audio(path, serializedDuration);
|
||||
}
|
||||
audio.id = ++_instanceId;
|
||||
audio.onEnded(() => {
|
||||
putOrDestroyAudio(audio);
|
||||
});
|
||||
return audio;
|
||||
}
|
||||
|
||||
function putOrDestroyAudio (audio) {
|
||||
if (_audioPool.includes(audio)) {
|
||||
return;
|
||||
}
|
||||
delete _id2audio[audio.id];
|
||||
audio.reset();
|
||||
if (_audioPool.length < _maxPoolSize) {
|
||||
_audioPool.push(audio);
|
||||
} else {
|
||||
audio.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
const _maxPlayingAudio = 10;
|
||||
|
||||
|
||||
cc.audioEngine = {
|
||||
|
||||
AudioState: Audio.State,
|
||||
|
||||
_maxPoolSize: 32,
|
||||
|
||||
_id2audio,
|
||||
|
||||
_pauseIDCache: [],
|
||||
|
||||
_play (clip, loop, volume) {
|
||||
let path;
|
||||
if (typeof clip === 'string') {
|
||||
path = clip;
|
||||
} else {
|
||||
path = clip.nativeUrl;
|
||||
}
|
||||
let audio = getOrCreateAudio(path, clip.duration);
|
||||
|
||||
volume = handleVolume(volume);
|
||||
audio.setLoop(loop || false);
|
||||
audio.setVolume(volume);
|
||||
|
||||
audio.play();
|
||||
|
||||
return audio;
|
||||
},
|
||||
|
||||
play: function (clip, loop, volume) {
|
||||
const audio = this._play(clip, loop, volume);
|
||||
this._id2audio[audio.id] = audio;
|
||||
return audio.id;
|
||||
},
|
||||
|
||||
setLoop: function (id, loop) {
|
||||
const audio = this._id2audio[id];
|
||||
if (audio) {
|
||||
audio.setLoop(loop);
|
||||
}
|
||||
},
|
||||
|
||||
isLoop: function (id) {
|
||||
const audio = this._id2audio[id];
|
||||
if (audio) {
|
||||
return audio.getLoop();
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
setVolume: function (id, volume) {
|
||||
volume = handleVolume(volume);
|
||||
const audio = this._id2audio[id];
|
||||
if (audio) {
|
||||
return audio.setVolume(volume);
|
||||
}
|
||||
},
|
||||
|
||||
getVolume: function (id) {
|
||||
const audio = this._id2audio[id];
|
||||
if (audio) {
|
||||
return audio.getVolume();
|
||||
}
|
||||
return 1;
|
||||
},
|
||||
|
||||
setCurrentTime: function (id, sec) {
|
||||
const audio = this._id2audio[id];
|
||||
if (audio) {
|
||||
return audio.seek(sec);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
getCurrentTime: function (id) {
|
||||
const audio = this._id2audio[id];
|
||||
if (audio) {
|
||||
return audio.getCurrentTime();
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
|
||||
getDuration: function (id) {
|
||||
const audio = this._id2audio[id];
|
||||
if (audio) {
|
||||
return audio.getDuration();
|
||||
}
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
||||
getState: function (id) {
|
||||
const audio = this._id2audio[id];
|
||||
if (audio) {
|
||||
return audio.getState();
|
||||
}
|
||||
return Audio.State.INITIALZING;
|
||||
|
||||
},
|
||||
|
||||
|
||||
isPlaying: function(id) {
|
||||
const audio = this._id2audio[id];
|
||||
if (audio) {
|
||||
return audio.getState() === Audio.State.PLAYING;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
setFinishCallback: function (id, callback) {
|
||||
const audio = this._id2audio[id];
|
||||
if (audio) {
|
||||
return audio.finishCB = callback;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
pause: function (id) {
|
||||
const audio = this._id2audio[id];
|
||||
if (audio) {
|
||||
audio.pause();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
pauseAll: function () {
|
||||
for (let id in this._id2audio) {
|
||||
const audio = this._id2audio[id];
|
||||
if (audio) {
|
||||
audio.pause();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
resume: function (id) {
|
||||
const audio = this._id2audio[id];
|
||||
if (audio) {
|
||||
audio.resume();
|
||||
}
|
||||
},
|
||||
|
||||
resumeAll: function () {
|
||||
for (let id in this._id2audio) {
|
||||
const audio = this._id2audio[id];
|
||||
if (audio) {
|
||||
audio.resume();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
stop: function (id) {
|
||||
const audio = this._id2audio[id];
|
||||
if (audio) {
|
||||
audio.stop();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
stopAll: function () {
|
||||
for (let id in this._id2audio) {
|
||||
const audio = this._id2audio[id];
|
||||
if (audio) {
|
||||
audio.stop();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
setMaxAudioInstance: function (num) {
|
||||
// NOT SUPPPORTED
|
||||
},
|
||||
|
||||
getMaxAudioInstance: function () {
|
||||
return _maxPlayingAudio;
|
||||
},
|
||||
|
||||
uncache: function (clip) {
|
||||
var filePath = clip;
|
||||
if (typeof clip === 'string') {
|
||||
// backward compatibility since 1.10
|
||||
cc.warnID(8401, 'cc.audioEngine', 'cc.AudioClip', 'AudioClip', 'cc.AudioClip', 'audio');
|
||||
filePath = clip;
|
||||
}
|
||||
else {
|
||||
if (!clip) {
|
||||
return;
|
||||
}
|
||||
filePath = clip.nativeUrl;
|
||||
}
|
||||
|
||||
for (let id in _id2audio) {
|
||||
const audio = this._id2audio[id];
|
||||
if (audio && audio.getSrc() === filePath) {
|
||||
audio.stop();
|
||||
putOrDestroyAudio(audio);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
uncacheAll: function () {
|
||||
this.stopAll();
|
||||
for (let id in _id2audio) {
|
||||
const audio = _id2audio[id];
|
||||
if (audio) {
|
||||
audio.stop();
|
||||
putOrDestroyAudio(audio);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_break: function () {
|
||||
// DO NOTHING
|
||||
},
|
||||
|
||||
_restore: function () {
|
||||
// DO NOTHING
|
||||
},
|
||||
|
||||
///////////////////////////////
|
||||
// Classification of interface
|
||||
|
||||
_music: null,
|
||||
|
||||
_effectVolume: 1,
|
||||
|
||||
playMusic: function (clip, loop) {
|
||||
if (this._music) {
|
||||
if (this._music.getSrc() !== clip.nativeUrl) {
|
||||
this._music.stop();
|
||||
putOrDestroyAudio(this._music);
|
||||
const audio = this._play(clip, loop);
|
||||
this._music = audio;
|
||||
} else {
|
||||
this._music.stop();
|
||||
this._music.play();
|
||||
}
|
||||
} else {
|
||||
const audio = this._play(clip, loop);
|
||||
this._music = audio;
|
||||
}
|
||||
return this._music.id;
|
||||
},
|
||||
|
||||
|
||||
stopMusic: function () {
|
||||
this._music.stop();
|
||||
},
|
||||
|
||||
|
||||
pauseMusic: function () {
|
||||
this._music.pause();
|
||||
},
|
||||
|
||||
|
||||
resumeMusic: function () {
|
||||
this._music.resume();
|
||||
},
|
||||
|
||||
getMusicVolume: function () {
|
||||
if (this._music) {
|
||||
return this._music.getVolume();
|
||||
}
|
||||
return 1;
|
||||
},
|
||||
|
||||
setMusicVolume: function (volume) {
|
||||
volume = handleVolume(volume);
|
||||
if (this._music) {
|
||||
this._music.setVolume(volume);
|
||||
}
|
||||
},
|
||||
|
||||
isMusicPlaying: function () {
|
||||
return this._music.getState() === Audio.State.PLAYING;
|
||||
},
|
||||
|
||||
playEffect: function (clip, loop) {
|
||||
return this.play(clip, loop, this._effectVolume);
|
||||
},
|
||||
|
||||
setEffectsVolume: function (volume) {
|
||||
volume = handleVolume(volume);
|
||||
var musicId = this._music.id;
|
||||
this._effectVolume = volume;
|
||||
for (var id in _id2audio) {
|
||||
var audio = _id2audio[id];
|
||||
if (!audio || audio.id === musicId) continue;
|
||||
audio.setVolume(volume);
|
||||
}
|
||||
},
|
||||
|
||||
getEffectsVolume: function () {
|
||||
return this._effectVolume;
|
||||
},
|
||||
|
||||
pauseEffect: function (id) {
|
||||
return this.pause(id);
|
||||
},
|
||||
|
||||
pauseAllEffects: function () {
|
||||
var musicId = this._music.id;
|
||||
for (var id in _id2audio) {
|
||||
var audio = _id2audio[id];
|
||||
if (!audio || audio.id === musicId) continue;
|
||||
audio.pause();
|
||||
}
|
||||
},
|
||||
|
||||
resumeEffect: function (id) {
|
||||
this.resume(id);
|
||||
},
|
||||
|
||||
resumeAllEffects: function () {
|
||||
var musicId = this._music.id;
|
||||
for (var id in _id2audio) {
|
||||
var audio = _id2audio[id];
|
||||
if (!audio || audio.id === musicId) continue;
|
||||
audio.resume();
|
||||
}
|
||||
},
|
||||
|
||||
stopEffect: function (id) {
|
||||
return this.stop(id);
|
||||
},
|
||||
|
||||
stopAllEffects: function () {
|
||||
var musicId = this._music.id;
|
||||
for (var id in _id2audio) {
|
||||
var audio = _id2audio[id];
|
||||
if (!audio || audio.id === musicId) continue;
|
||||
audio.stop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
139
adapters/platforms/taobao-minigame/wrapper/engine/AudioSource.js
Normal file
139
adapters/platforms/taobao-minigame/wrapper/engine/AudioSource.js
Normal file
@@ -0,0 +1,139 @@
|
||||
|
||||
(function(){
|
||||
if (!(cc && cc.AudioClip && cc.AudioSource)) {
|
||||
return;
|
||||
}
|
||||
const Audio = require('./Audio');
|
||||
const AudioClip = cc.AudioClip;
|
||||
const proto = cc.AudioSource.prototype;
|
||||
|
||||
Object.defineProperties(proto, {
|
||||
isPlaying: {
|
||||
get () {
|
||||
var state = this.audio.getState();
|
||||
return state === cc._Audio.State.PLAYING;
|
||||
}
|
||||
},
|
||||
clip: {
|
||||
get: function () {
|
||||
return this._clip;
|
||||
},
|
||||
set: function (value) {
|
||||
if (value === this._clip) {
|
||||
return;
|
||||
}
|
||||
if (!(value instanceof AudioClip)) {
|
||||
return cc.error('Wrong type of AudioClip.');
|
||||
}
|
||||
this._clip = value;
|
||||
this.audio.stop();
|
||||
this.audio.destroy();
|
||||
this.audio = new Audio(value.nativeUrl, value.duration);
|
||||
},
|
||||
},
|
||||
|
||||
volume: {
|
||||
get: function () {
|
||||
return this._volume;
|
||||
},
|
||||
set: function (value) {
|
||||
value = misc.clamp01(value);
|
||||
this._volume = value;
|
||||
if (!this._mute) {
|
||||
this.audio.setVolume(value);
|
||||
}
|
||||
return value;
|
||||
},
|
||||
},
|
||||
|
||||
mute: {
|
||||
get: function () {
|
||||
return this._mute;
|
||||
},
|
||||
set: function (value) {
|
||||
if (this._mute === value) {
|
||||
return;
|
||||
}
|
||||
this._mute = value;
|
||||
this.audio.setVolume(value ? 0 : this._volume);
|
||||
return value;
|
||||
},
|
||||
},
|
||||
|
||||
loop: {
|
||||
get: function () {
|
||||
return this._loop;
|
||||
},
|
||||
set: function (value) {
|
||||
this._loop = value;
|
||||
this.audio.setLoop(value);
|
||||
return value;
|
||||
}
|
||||
},
|
||||
})
|
||||
Object.assign(proto, {
|
||||
onLoad: function () {
|
||||
if(this.audio && this.audio instanceof Audio)
|
||||
return;
|
||||
|
||||
if (this._clip) {
|
||||
this.audio = new Audio(this._clip.nativeUrl, this._clip.duration);
|
||||
}
|
||||
},
|
||||
|
||||
onEnable: function () {
|
||||
if (this.playOnLoad && this._firstlyEnabled) {
|
||||
this._firstlyEnabled = false;
|
||||
this.play();
|
||||
}
|
||||
},
|
||||
|
||||
onDisable: function () {
|
||||
this.stop();
|
||||
},
|
||||
|
||||
onDestroy: function () {
|
||||
this.audio.destroy();
|
||||
},
|
||||
|
||||
play: function () {
|
||||
if ( !this._clip ) return;
|
||||
|
||||
var audio = this.audio;
|
||||
audio.setVolume(this._mute ? 0 : this._volume);
|
||||
audio.setLoop(this._loop);
|
||||
audio.seek(0);
|
||||
audio.play();
|
||||
},
|
||||
|
||||
stop: function () {
|
||||
this.audio.stop();
|
||||
},
|
||||
|
||||
pause: function () {
|
||||
this.audio.pause();
|
||||
},
|
||||
|
||||
resume: function () {
|
||||
this.audio.resume();
|
||||
},
|
||||
|
||||
rewind: function(){
|
||||
this.audio.seek(0);
|
||||
},
|
||||
|
||||
getCurrentTime: function () {
|
||||
return this.audio.getCurrentTime();
|
||||
},
|
||||
|
||||
setCurrentTime: function (time) {
|
||||
this.audio.seek(time);
|
||||
return time;
|
||||
},
|
||||
|
||||
getDuration: function () {
|
||||
return this.audio.getDuration();
|
||||
}
|
||||
});
|
||||
|
||||
})();
|
92
adapters/platforms/taobao-minigame/wrapper/engine/Editbox.js
Normal file
92
adapters/platforms/taobao-minigame/wrapper/engine/Editbox.js
Normal file
@@ -0,0 +1,92 @@
|
||||
(function () {
|
||||
if (!(cc && cc.EditBox)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const EditBox = cc.EditBox;
|
||||
const js = cc.js;
|
||||
const KeyboardReturnType = EditBox.KeyboardReturnType;
|
||||
const MAX_VALUE = 65535;
|
||||
|
||||
function getKeyboardReturnType (type) {
|
||||
switch (type) {
|
||||
case KeyboardReturnType.DEFAULT:
|
||||
case KeyboardReturnType.DONE:
|
||||
return 'done';
|
||||
case KeyboardReturnType.SEND:
|
||||
return 'send';
|
||||
case KeyboardReturnType.SEARCH:
|
||||
return 'search';
|
||||
case KeyboardReturnType.GO:
|
||||
return 'go';
|
||||
case KeyboardReturnType.NEXT:
|
||||
return 'next';
|
||||
}
|
||||
return 'done';
|
||||
}
|
||||
|
||||
const BaseClass = EditBox._ImplClass;
|
||||
function MiniGameEditBoxImpl () {
|
||||
BaseClass.call(this);
|
||||
}
|
||||
|
||||
js.extend(MiniGameEditBoxImpl, BaseClass);
|
||||
EditBox._ImplClass = MiniGameEditBoxImpl;
|
||||
|
||||
Object.assign(MiniGameEditBoxImpl.prototype, {
|
||||
init (delegate) {
|
||||
if (!delegate) {
|
||||
cc.error('EditBox init failed');
|
||||
return;
|
||||
}
|
||||
this._delegate = delegate;
|
||||
},
|
||||
|
||||
beginEditing () {
|
||||
// In case multiply register events
|
||||
if (this._editing) {
|
||||
return;
|
||||
}
|
||||
let delegate = this._delegate;
|
||||
this._showPrompt();
|
||||
this._editing = true;
|
||||
delegate.editBoxEditingDidBegan();
|
||||
},
|
||||
|
||||
endEditing () {
|
||||
cc.warn(`Can't support to end editing.`);
|
||||
},
|
||||
|
||||
_showPrompt () {
|
||||
let self = this;
|
||||
let delegate = this._delegate;
|
||||
let multiline = (delegate.inputMode === EditBox.InputMode.ANY);
|
||||
let maxLength = (delegate.maxLength < 0 ? MAX_VALUE : delegate.maxLength);
|
||||
|
||||
if (multiline) {
|
||||
cc.warn(`Multiline editing is not supported`);
|
||||
}
|
||||
|
||||
my.prompt({
|
||||
title: '',
|
||||
message: delegate.placeholder,
|
||||
// placeholder: delegate.placeholder,
|
||||
okButtonText: getKeyboardReturnType(delegate.returnType),
|
||||
cancelButtonText: 'cancel',
|
||||
success: (result) => {
|
||||
if (result.ok) {
|
||||
let inputValue = result.inputValue;
|
||||
inputValue = (maxLength <= inputValue.length) ? inputValue.substring(0, maxLength) : inputValue;
|
||||
if (delegate._string !== inputValue) {
|
||||
delegate.editBoxTextChanged(inputValue);
|
||||
}
|
||||
delegate.editBoxEditingReturn();
|
||||
}
|
||||
self._editing = false;
|
||||
delegate.editBoxEditingDidEnded();
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
55
adapters/platforms/taobao-minigame/wrapper/engine/Label.js
Normal file
55
adapters/platforms/taobao-minigame/wrapper/engine/Label.js
Normal file
@@ -0,0 +1,55 @@
|
||||
if (cc && cc.Label) {
|
||||
const gfx = cc.gfx;
|
||||
const Label = cc.Label;
|
||||
|
||||
// shared label canvas
|
||||
let _sharedLabelCanvas = my.createCanvas();
|
||||
let _sharedLabelCanvasCtx = _sharedLabelCanvas.getContext('2d');
|
||||
let canvasData = {
|
||||
canvas: _sharedLabelCanvas,
|
||||
context: _sharedLabelCanvasCtx,
|
||||
};
|
||||
cc.game.on(cc.game.EVENT_ENGINE_INITED, function () {
|
||||
Object.assign(Label._canvasPool, {
|
||||
get() {
|
||||
return canvasData;
|
||||
},
|
||||
|
||||
put() {
|
||||
// do nothing
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let _originUpdateMaterial = Label.prototype._updateMaterialWebgl;
|
||||
// fix ttf font black border
|
||||
Object.assign(Label.prototype, {
|
||||
_updateMaterialWebgl () {
|
||||
_originUpdateMaterial.call(this);
|
||||
|
||||
// init blend factor
|
||||
let material = this._materials[0];
|
||||
if (!this._frame || !material) {
|
||||
return;
|
||||
}
|
||||
let dstBlendFactor = cc.macro.BlendFactor.ONE_MINUS_SRC_ALPHA;
|
||||
let srcBlendFactor;
|
||||
if (!(__globalAdapter.isDevTool || this.font instanceof cc.BitmapFont)) {
|
||||
// Premultiplied alpha on runtime
|
||||
srcBlendFactor = cc.macro.BlendFactor.ONE;
|
||||
}
|
||||
else {
|
||||
srcBlendFactor = cc.macro.BlendFactor.SRC_ALPHA;
|
||||
}
|
||||
|
||||
// set blend func
|
||||
material.effect.setBlend(
|
||||
true,
|
||||
gfx.BLEND_FUNC_ADD,
|
||||
srcBlendFactor, dstBlendFactor,
|
||||
gfx.BLEND_FUNC_ADD,
|
||||
srcBlendFactor, dstBlendFactor,
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
@@ -0,0 +1,2 @@
|
||||
// NOTE: can't cache file on Taobao iOS end
|
||||
cc.assetManager.cacheManager.cacheEnabled = cc.sys.os !== cc.sys.OS_IOS;
|
@@ -0,0 +1,6 @@
|
||||
require('./AudioEngine');
|
||||
require('./AudioSource');
|
||||
require('./AssetManager');
|
||||
require('./cache-manager');
|
||||
require('./Label');
|
||||
require('./Editbox');
|
273
adapters/platforms/taobao-minigame/wrapper/fs-utils.js
Normal file
273
adapters/platforms/taobao-minigame/wrapper/fs-utils.js
Normal file
@@ -0,0 +1,273 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2017-2019 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
// TODO: verify the my API
|
||||
var fs = my.getFileSystemManager ? my.getFileSystemManager() : null;
|
||||
var outOfStorageRegExp = /the maximum size of the file storage/; // not exactly right
|
||||
|
||||
var fsUtils = {
|
||||
|
||||
fs,
|
||||
|
||||
isOutOfStorage (errMsg) {
|
||||
return outOfStorageRegExp.test(errMsg);
|
||||
},
|
||||
|
||||
getUserDataPath () {
|
||||
return my.env.USER_DATA_PATH;
|
||||
},
|
||||
|
||||
checkFsValid () {
|
||||
if (!fs) {
|
||||
console.warn('Can not get the file system!');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
deleteFile (filePath, onComplete) {
|
||||
fs.unlink({
|
||||
filePath: filePath,
|
||||
success: function () {
|
||||
onComplete && onComplete(null);
|
||||
},
|
||||
fail: function (res) {
|
||||
console.warn(`Delete file failed: path: ${filePath} message: ${res.errorMessage}`);
|
||||
onComplete && onComplete(new Error(res.errorMessage));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
downloadFile (remoteUrl, filePath, header, onProgress, onComplete) {
|
||||
var options = {
|
||||
url: remoteUrl,
|
||||
success: function (res) {
|
||||
if (!filePath) {
|
||||
onComplete && onComplete(null, res.apFilePath);
|
||||
}
|
||||
else {
|
||||
fsUtils.copyFile(res.apFilePath, filePath, onComplete);
|
||||
}
|
||||
},
|
||||
fail: function (res) {
|
||||
console.warn(`Download file failed: path: ${remoteUrl} message: ${res.errorMessage}`);
|
||||
onComplete && onComplete(new Error(res.errorMessage), null);
|
||||
}
|
||||
}
|
||||
if (header) options.header = header;
|
||||
var task = my.downloadFile(options);
|
||||
onProgress && task.onProgressUpdate(onProgress);
|
||||
},
|
||||
|
||||
saveFile (srcPath, destPath, onComplete) {
|
||||
// Hack, seems like my.saveFile dose not work
|
||||
fsUtils.copyFile(srcPath, destPath, onComplete);
|
||||
},
|
||||
|
||||
copyFile (srcPath, destPath, onComplete) {
|
||||
fs.copyFile({
|
||||
srcPath: srcPath,
|
||||
destPath: destPath,
|
||||
success: function () {
|
||||
onComplete && onComplete(null);
|
||||
},
|
||||
fail: function (res) {
|
||||
console.warn(`Copy file failed: path: ${srcPath} message: ${res.errorMessage}`);
|
||||
onComplete && onComplete(new Error(res.errorMessage));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
writeFile (path, data, encoding, onComplete) {
|
||||
fs.writeFile({
|
||||
filePath: path,
|
||||
encoding: encoding,
|
||||
data: data,
|
||||
success: function () {
|
||||
onComplete && onComplete(null);
|
||||
},
|
||||
fail: function (res) {
|
||||
console.warn(`Write file failed: path: ${path} message: ${res.errorMessage}`);
|
||||
onComplete && onComplete(new Error(res.errorMessage));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
writeFileSync (path, data, encoding) {
|
||||
try {
|
||||
fs.writeFileSync({
|
||||
filePath: path,
|
||||
data: data,
|
||||
encoding: encoding,
|
||||
});
|
||||
return null;
|
||||
}
|
||||
catch (e) {
|
||||
console.warn(`Write file failed: path: ${path} message: ${e.message}`);
|
||||
return new Error(e.message);
|
||||
}
|
||||
},
|
||||
|
||||
readFile (filePath, encoding, onComplete) {
|
||||
fs.readFile({
|
||||
filePath: filePath,
|
||||
encoding: encoding,
|
||||
success: function (res) {
|
||||
onComplete && onComplete(null, res.data);
|
||||
},
|
||||
fail: function (res) {
|
||||
console.warn(`Read file failed: path: ${filePath} message: ${res.errorMessage}`);
|
||||
onComplete && onComplete (new Error(res.errorMessage), null);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
readDir (filePath, onComplete) {
|
||||
fs.readdir({
|
||||
dirPath: filePath,
|
||||
success: function (res) {
|
||||
onComplete && onComplete(null, res.files);
|
||||
},
|
||||
fail: function (res) {
|
||||
console.warn(`Read directory failed: path: ${filePath} message: ${res.errorMessage}`);
|
||||
onComplete && onComplete(new Error(res.errorMessage), null);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
readText (filePath, onComplete) {
|
||||
fsUtils.readFile(filePath, 'utf8', onComplete);
|
||||
},
|
||||
|
||||
readArrayBuffer (filePath, onComplete) {
|
||||
fsUtils.readFile(filePath, '', onComplete);
|
||||
},
|
||||
|
||||
readJson (filePath, onComplete) {
|
||||
fsUtils.readFile(filePath, 'utf8', function (err, text) {
|
||||
var out = null;
|
||||
if (!err) {
|
||||
try {
|
||||
out = JSON.parse(text);
|
||||
}
|
||||
catch (e) {
|
||||
console.warn(`Read json failed: path: ${filePath} message: ${e.message}`);
|
||||
err = new Error(e.message);
|
||||
}
|
||||
}
|
||||
onComplete && onComplete(err, out);
|
||||
});
|
||||
},
|
||||
|
||||
readJsonSync (path) {
|
||||
try {
|
||||
var res = fs.readFileSync({
|
||||
filePath: path,
|
||||
encoding: 'utf8',
|
||||
});
|
||||
return JSON.parse(res.data);
|
||||
}
|
||||
catch (e) {
|
||||
console.warn(`Read json failed: path: ${path} message: ${e.message}`);
|
||||
return new Error(e.message);
|
||||
}
|
||||
},
|
||||
|
||||
makeDirSync (path, recursive) {
|
||||
try {
|
||||
fs.mkdirSync({
|
||||
dirPath: path,
|
||||
recursive: recursive,
|
||||
});
|
||||
return null;
|
||||
}
|
||||
catch (e) {
|
||||
console.warn(`Make directory failed: path: ${path} message: ${e.message}`);
|
||||
return new Error(e.message);
|
||||
}
|
||||
},
|
||||
|
||||
rmdirSync (dirPath, recursive) {
|
||||
try {
|
||||
fs.rmdirSync({ dirPath, recursive });
|
||||
}
|
||||
catch (e) {
|
||||
console.warn(`rm directory failed: path: ${dirPath} message: ${e.message}`);
|
||||
return new Error(e.message);
|
||||
}
|
||||
},
|
||||
|
||||
exists (filePath, onComplete) {
|
||||
// fs.access is not supported.
|
||||
// fs.access({
|
||||
// path: filePath,
|
||||
// success: function () {
|
||||
// onComplete && onComplete(true);
|
||||
// },
|
||||
// fail: function () {
|
||||
// onComplete && onComplete(false);
|
||||
// }
|
||||
// });
|
||||
fs.readFile({
|
||||
filePath: filePath,
|
||||
success () {
|
||||
onComplete && onComplete(true);
|
||||
},
|
||||
fail () {
|
||||
onComplete && onComplete (false);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
loadSubpackage (name, onProgress, onComplete) {
|
||||
const task = my.loadSubPackage({
|
||||
name,
|
||||
success () {
|
||||
onComplete && onComplete();
|
||||
},
|
||||
fail (res) {
|
||||
console.warn(`Load Subpackage failed: path: ${name} message: ${res.errorMessage}`);
|
||||
onComplete && onComplete(new Error(`Failed to load subpackage ${name}: ${res.errorMessage}`));
|
||||
},
|
||||
});
|
||||
// onProgress && task.onProgressUpdate(onProgress);
|
||||
return {};
|
||||
},
|
||||
|
||||
unzip (zipFilePath, targetPath, onComplete) {
|
||||
fs.unzip({
|
||||
zipFilePath,
|
||||
targetPath,
|
||||
success () {
|
||||
onComplete && onComplete(null);
|
||||
},
|
||||
fail (res) {
|
||||
console.warn(`unzip failed: path: ${zipFilePath} message: ${res.errorMessage}`);
|
||||
onComplete && onComplete(new Error('unzip failed: ' + res.errorMessage));
|
||||
},
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
window.fsUtils = module.exports = fsUtils;
|
19
adapters/platforms/taobao-minigame/wrapper/systemInfo.js
Normal file
19
adapters/platforms/taobao-minigame/wrapper/systemInfo.js
Normal file
@@ -0,0 +1,19 @@
|
||||
const adapter = window.__globalAdapter;
|
||||
let adaptSysFunc = adapter.adaptSys;
|
||||
|
||||
//taobao IDE language ("Chinese")
|
||||
//taobao phone language (Andrond: "cn", iPad: 'zh_CN')
|
||||
const languageMap = {
|
||||
Ch: "zh",
|
||||
cn: "zh",
|
||||
zh: "zh",
|
||||
};
|
||||
|
||||
Object.assign(adapter, {
|
||||
// Extend adaptSys interface
|
||||
adaptSys (sys) {
|
||||
adaptSysFunc.call(this, sys);
|
||||
sys.platform = sys.TAOBAO_MINIGAME;
|
||||
sys.language = languageMap[sys.language] || sys.language;
|
||||
},
|
||||
});
|
108
adapters/platforms/taobao-minigame/wrapper/unify.js
Normal file
108
adapters/platforms/taobao-minigame/wrapper/unify.js
Normal file
@@ -0,0 +1,108 @@
|
||||
const utils = require('../../../common/utils');
|
||||
|
||||
if (window.__globalAdapter) {
|
||||
let globalAdapter = window.__globalAdapter;
|
||||
// SystemInfo
|
||||
globalAdapter.isSubContext = false; // sub context not supported
|
||||
globalAdapter.isDevTool = my.isIDE;
|
||||
utils.cloneMethod(globalAdapter, my, 'getSystemInfoSync');
|
||||
// TouchEvent
|
||||
utils.cloneMethod(globalAdapter, my, 'onTouchStart');
|
||||
utils.cloneMethod(globalAdapter, my, 'onTouchMove');
|
||||
utils.cloneMethod(globalAdapter, my, 'onTouchEnd');
|
||||
utils.cloneMethod(globalAdapter, my, 'onTouchCancel');
|
||||
|
||||
// Audio
|
||||
globalAdapter.createInnerAudioContext = function () {
|
||||
let audio = my.createInnerAudioContext();
|
||||
if (my.getSystemInfoSync().platform === 'iOS') {
|
||||
let currentTime = 0;
|
||||
let originalSeek = audio.seek;
|
||||
audio.seek = function (time) {
|
||||
// need to access audio.paused in the next tick
|
||||
setTimeout(() => {
|
||||
if (audio.paused) {
|
||||
currentTime = time;
|
||||
} else {
|
||||
originalSeek.call(audio, time);
|
||||
}
|
||||
}, 50);
|
||||
};
|
||||
|
||||
let originalPlay = audio.play;
|
||||
audio.play = function () {
|
||||
if (currentTime !== 0) {
|
||||
audio.seek(currentTime);
|
||||
currentTime = 0; // clear cached currentTime
|
||||
}
|
||||
originalPlay.call(audio);
|
||||
};
|
||||
}
|
||||
return audio;
|
||||
};
|
||||
|
||||
// FrameRate
|
||||
// utils.cloneMethod(globalAdapter, my, 'setPreferredFramesPerSecond');
|
||||
|
||||
// Keyboard
|
||||
globalAdapter.showKeyboard = () => console.warn('showKeyboard not supported.');
|
||||
globalAdapter.hideKeyboard = () => console.warn('hideKeyboard not supported.');
|
||||
globalAdapter.updateKeyboard = () => console.warn('updateKeyboard not supported.');
|
||||
globalAdapter.onKeyboardInput = () => console.warn('onKeyboardInput not supported.');
|
||||
globalAdapter.onKeyboardConfirm = () => console.warn('onKeyboardConfirm not supported.');
|
||||
globalAdapter.onKeyboardComplete = () => console.warn('onKeyboardComplete not supported.');
|
||||
globalAdapter.offKeyboardInput = () => console.warn('offKeyboardInput not supported.');
|
||||
globalAdapter.offKeyboardConfirm = () => console.warn('offKeyboardConfirm not supported.');
|
||||
globalAdapter.offKeyboardComplete = () => console.warn('offKeyboardComplete not supported.');
|
||||
|
||||
// Message
|
||||
utils.cloneMethod(globalAdapter, my, 'getOpenDataContext');
|
||||
utils.cloneMethod(globalAdapter, my, 'onMessage');
|
||||
|
||||
// SharedCanvas
|
||||
utils.cloneMethod(globalAdapter, my, 'getSharedCanvas');
|
||||
|
||||
// Font
|
||||
globalAdapter.loadFont = function (url) {
|
||||
// my.loadFont crash when url is not in user data path
|
||||
return "Arial";
|
||||
};
|
||||
|
||||
// hide show Event
|
||||
utils.cloneMethod(globalAdapter, my, 'onShow');
|
||||
utils.cloneMethod(globalAdapter, my, 'onHide');
|
||||
|
||||
// Accelerometer
|
||||
let accelerometerCallback = null;
|
||||
let systemInfo = my.getSystemInfoSync();
|
||||
let windowWidth = systemInfo.windowWidth;
|
||||
let windowHeight = systemInfo.windowHeight;
|
||||
let isLandscape = windowWidth > windowHeight;
|
||||
function accelerometerChangeCallback (res, cb) {
|
||||
let resClone = {};
|
||||
|
||||
let x = res.x;
|
||||
let y = res.y;
|
||||
|
||||
if (isLandscape) {
|
||||
let tmp = x;
|
||||
x = -y;
|
||||
y = tmp;
|
||||
}
|
||||
|
||||
resClone.x = x;
|
||||
resClone.y = y;
|
||||
resClone.z = res.z;
|
||||
accelerometerCallback && accelerometerCallback(resClone);
|
||||
}
|
||||
Object.assign(globalAdapter, {
|
||||
startAccelerometer (cb) {
|
||||
accelerometerCallback = cb;
|
||||
my.onAccelerometerChange && my.onAccelerometerChange(accelerometerChangeCallback);
|
||||
},
|
||||
|
||||
stopAccelerometer () {
|
||||
my.offAccelerometerChange && my.offAccelerometerChange(accelerometerChangeCallback);
|
||||
},
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user