tweetdeckhipchattelegramhangoutsslackgmailskypefacebook-workplaceoutlookemailmicrosoft-teamsdiscordmessengercustom-servicesmacoslinuxwindowsinboxwhatsappicloud
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
392 lines
11 KiB
392 lines
11 KiB
9 years ago
|
/**
|
||
|
* @private
|
||
|
*/
|
||
|
Ext.define('Ext.AnimationQueue', {
|
||
|
singleton: true,
|
||
|
|
||
|
constructor: function() {
|
||
|
this.queue = [];
|
||
|
this.taskQueue = [];
|
||
|
this.runningQueue = [];
|
||
|
this.idleQueue = [];
|
||
|
this.isRunning = false;
|
||
|
this.isIdle = true;
|
||
|
|
||
|
this.run = Ext.Function.bind(this.run, this);
|
||
|
|
||
|
// iOS has a nasty bug which causes pending requestAnimationFrame to not release
|
||
|
// the callback when the WebView is switched back and forth from / to being background process
|
||
|
// We use a watchdog timer to workaround this, and restore the pending state correctly if this happens
|
||
|
// This timer has to be set as an interval from the very beginning and we have to keep it running for
|
||
|
// as long as the app lives, setting it later doesn't seem to work
|
||
|
if (Ext.os.is.iOS) {
|
||
|
Ext.interval(this.watch, 500, this);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @param {Function} fn
|
||
|
* @param {Object} [scope]
|
||
|
* @param {Object} [args]
|
||
|
*/
|
||
|
start: function(fn, scope, args) {
|
||
|
this.queue.push(arguments);
|
||
|
|
||
|
if (!this.isRunning) {
|
||
|
if (this.hasOwnProperty('idleTimer')) {
|
||
|
clearTimeout(this.idleTimer);
|
||
|
delete this.idleTimer;
|
||
|
}
|
||
|
|
||
|
if (this.hasOwnProperty('idleQueueTimer')) {
|
||
|
clearTimeout(this.idleQueueTimer);
|
||
|
delete this.idleQueueTimer;
|
||
|
}
|
||
|
|
||
|
this.isIdle = false;
|
||
|
this.isRunning = true;
|
||
|
//<debug>
|
||
|
this.startCountTime = Ext.now();
|
||
|
this.count = 0;
|
||
|
//</debug>
|
||
|
this.doStart();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
watch: function() {
|
||
|
if (this.isRunning && Ext.now() - this.lastRunTime >= 500) {
|
||
|
this.run();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
run: function() {
|
||
|
if (!this.isRunning) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var queue = this.runningQueue,
|
||
|
i, ln;
|
||
|
|
||
|
this.lastRunTime = Ext.now();
|
||
|
this.frameStartTime = Ext.now();
|
||
|
|
||
|
queue.push.apply(queue, this.queue);
|
||
|
|
||
|
for (i = 0, ln = queue.length; i < ln; i++) {
|
||
|
this.invoke(queue[i]);
|
||
|
}
|
||
|
|
||
|
queue.length = 0;
|
||
|
|
||
|
//<debug>
|
||
|
var now = this.frameStartTime,
|
||
|
startCountTime = this.startCountTime,
|
||
|
elapse = now - startCountTime,
|
||
|
count = ++this.count;
|
||
|
|
||
|
if (elapse >= 200) {
|
||
|
this.onFpsChanged(count * 1000 / elapse, count, elapse);
|
||
|
this.startCountTime = now;
|
||
|
this.count = 0;
|
||
|
}
|
||
|
//</debug>
|
||
|
|
||
|
this.doIterate();
|
||
|
},
|
||
|
|
||
|
//<debug>
|
||
|
onFpsChanged: Ext.emptyFn,
|
||
|
|
||
|
onStop: Ext.emptyFn,
|
||
|
//</debug>
|
||
|
|
||
|
doStart: function() {
|
||
|
this.animationFrameId = Ext.Function.requestAnimationFrame(this.run);
|
||
|
this.lastRunTime = Ext.now();
|
||
|
},
|
||
|
|
||
|
doIterate: function() {
|
||
|
this.animationFrameId = Ext.Function.requestAnimationFrame(this.run);
|
||
|
},
|
||
|
|
||
|
doStop: function() {
|
||
|
Ext.Function.cancelAnimationFrame(this.animationFrameId);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @param {Function} fn
|
||
|
* @param {Object} [scope]
|
||
|
* @param {Object} [args]
|
||
|
*/
|
||
|
stop: function(fn, scope, args) {
|
||
|
if (!this.isRunning) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var queue = this.queue,
|
||
|
ln = queue.length,
|
||
|
i, item;
|
||
|
|
||
|
for (i = 0; i < ln; i++) {
|
||
|
item = queue[i];
|
||
|
if (item[0] === fn && item[1] === scope && item[2] === args) {
|
||
|
queue.splice(i, 1);
|
||
|
i--;
|
||
|
ln--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ln === 0) {
|
||
|
this.doStop();
|
||
|
//<debug>
|
||
|
this.onStop();
|
||
|
//</debug>
|
||
|
this.isRunning = false;
|
||
|
|
||
|
this.idleTimer = Ext.defer(this.whenIdle, 100, this);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
onIdle: function(fn, scope, args) {
|
||
|
var listeners = this.idleQueue,
|
||
|
i, ln, listener;
|
||
|
|
||
|
for (i = 0, ln = listeners.length; i < ln; i++) {
|
||
|
listener = listeners[i];
|
||
|
if (fn === listener[0] && scope === listener[1] && args === listener[2]) {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
listeners.push(arguments);
|
||
|
|
||
|
if (this.isIdle) {
|
||
|
this.processIdleQueue();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
unIdle: function(fn, scope, args) {
|
||
|
var listeners = this.idleQueue,
|
||
|
i, ln, listener;
|
||
|
|
||
|
for (i = 0, ln = listeners.length; i < ln; i++) {
|
||
|
listener = listeners[i];
|
||
|
if (fn === listener[0] && scope === listener[1] && args === listener[2]) {
|
||
|
listeners.splice(i, 1);
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
},
|
||
|
|
||
|
queueTask: function(fn, scope, args) {
|
||
|
this.taskQueue.push(arguments);
|
||
|
this.processTaskQueue();
|
||
|
},
|
||
|
|
||
|
dequeueTask: function(fn, scope, args) {
|
||
|
var listeners = this.taskQueue,
|
||
|
i, ln, listener;
|
||
|
|
||
|
for (i = 0, ln = listeners.length; i < ln; i++) {
|
||
|
listener = listeners[i];
|
||
|
if (fn === listener[0] && scope === listener[1] && args === listener[2]) {
|
||
|
listeners.splice(i, 1);
|
||
|
i--;
|
||
|
ln--;
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
invoke: function(listener) {
|
||
|
var fn = listener[0],
|
||
|
scope = listener[1],
|
||
|
args = listener[2];
|
||
|
|
||
|
fn = (typeof fn == 'string' ? scope[fn] : fn);
|
||
|
|
||
|
if (Ext.isArray(args)) {
|
||
|
fn.apply(scope, args);
|
||
|
}
|
||
|
else {
|
||
|
fn.call(scope, args);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
whenIdle: function() {
|
||
|
this.isIdle = true;
|
||
|
this.processIdleQueue();
|
||
|
},
|
||
|
|
||
|
processIdleQueue: function() {
|
||
|
if (!this.hasOwnProperty('idleQueueTimer')) {
|
||
|
this.idleQueueTimer = Ext.defer(this.processIdleQueueItem, 1, this);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
processIdleQueueItem: function() {
|
||
|
delete this.idleQueueTimer;
|
||
|
|
||
|
if (!this.isIdle) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var listeners = this.idleQueue,
|
||
|
listener;
|
||
|
|
||
|
if (listeners.length > 0) {
|
||
|
listener = listeners.shift();
|
||
|
this.invoke(listener);
|
||
|
this.processIdleQueue();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
processTaskQueue: function() {
|
||
|
if (!this.hasOwnProperty('taskQueueTimer')) {
|
||
|
this.taskQueueTimer = Ext.defer(this.processTaskQueueItem, 15, this);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
processTaskQueueItem: function() {
|
||
|
delete this.taskQueueTimer;
|
||
|
|
||
|
var listeners = this.taskQueue,
|
||
|
listener;
|
||
|
|
||
|
if (listeners.length > 0) {
|
||
|
listener = listeners.shift();
|
||
|
this.invoke(listener);
|
||
|
this.processTaskQueue();
|
||
|
}
|
||
|
},
|
||
|
|
||
|
showFps: function() {
|
||
|
Ext.onInternalReady(function() {
|
||
|
Ext.Viewport.add([{
|
||
|
xtype: 'component',
|
||
|
bottom: 50,
|
||
|
left: 0,
|
||
|
width: 50,
|
||
|
height: 20,
|
||
|
html: 'Average',
|
||
|
style: 'background-color: black; color: white; text-align: center; line-height: 20px; font-size: 8px;'
|
||
|
},
|
||
|
{
|
||
|
id: '__averageFps',
|
||
|
xtype: 'component',
|
||
|
bottom: 0,
|
||
|
left: 0,
|
||
|
width: 50,
|
||
|
height: 50,
|
||
|
html: '0',
|
||
|
style: 'background-color: red; color: white; text-align: center; line-height: 50px;'
|
||
|
},
|
||
|
{
|
||
|
xtype: 'component',
|
||
|
bottom: 50,
|
||
|
left: 50,
|
||
|
width: 50,
|
||
|
height: 20,
|
||
|
html: 'Min (Last 1k)',
|
||
|
style: 'background-color: black; color: white; text-align: center; line-height: 20px; font-size: 8px;'
|
||
|
},
|
||
|
{
|
||
|
id: '__minFps',
|
||
|
xtype: 'component',
|
||
|
bottom: 0,
|
||
|
left: 50,
|
||
|
width: 50,
|
||
|
height: 50,
|
||
|
html: '0',
|
||
|
style: 'background-color: orange; color: white; text-align: center; line-height: 50px;'
|
||
|
},
|
||
|
{
|
||
|
xtype: 'component',
|
||
|
bottom: 50,
|
||
|
left: 100,
|
||
|
width: 50,
|
||
|
height: 20,
|
||
|
html: 'Max (Last 1k)',
|
||
|
style: 'background-color: black; color: white; text-align: center; line-height: 20px; font-size: 8px;'
|
||
|
},
|
||
|
{
|
||
|
id: '__maxFps',
|
||
|
xtype: 'component',
|
||
|
bottom: 0,
|
||
|
left: 100,
|
||
|
width: 50,
|
||
|
height: 50,
|
||
|
html: '0',
|
||
|
style: 'background-color: yellow; color: black; text-align: center; line-height: 50px;'
|
||
|
},
|
||
|
{
|
||
|
xtype: 'component',
|
||
|
bottom: 50,
|
||
|
left: 150,
|
||
|
width: 50,
|
||
|
height: 20,
|
||
|
html: 'Current',
|
||
|
style: 'background-color: black; color: white; text-align: center; line-height: 20px; font-size: 8px;'
|
||
|
},
|
||
|
{
|
||
|
id: '__currentFps',
|
||
|
xtype: 'component',
|
||
|
bottom: 0,
|
||
|
left: 150,
|
||
|
width: 50,
|
||
|
height: 50,
|
||
|
html: '0',
|
||
|
style: 'background-color: green; color: white; text-align: center; line-height: 50px;'
|
||
|
}
|
||
|
]);
|
||
|
Ext.AnimationQueue.resetFps();
|
||
|
});
|
||
|
|
||
|
},
|
||
|
|
||
|
resetFps: function() {
|
||
|
var currentFps = Ext.getCmp('__currentFps'),
|
||
|
averageFps = Ext.getCmp('__averageFps'),
|
||
|
minFps = Ext.getCmp('__minFps'),
|
||
|
maxFps = Ext.getCmp('__maxFps'),
|
||
|
min = 1000,
|
||
|
max = 0,
|
||
|
count = 0,
|
||
|
sum = 0;
|
||
|
|
||
|
Ext.AnimationQueue.onFpsChanged = function(fps) {
|
||
|
count++;
|
||
|
|
||
|
if (!(count % 10)) {
|
||
|
min = 1000;
|
||
|
max = 0;
|
||
|
}
|
||
|
|
||
|
sum += fps;
|
||
|
min = Math.min(min, fps);
|
||
|
max = Math.max(max, fps);
|
||
|
currentFps.setHtml(Math.round(fps));
|
||
|
averageFps.setHtml(Math.round(sum / count));
|
||
|
minFps.setHtml(Math.round(min));
|
||
|
maxFps.setHtml(Math.round(max));
|
||
|
};
|
||
|
}
|
||
|
}, function() {
|
||
|
/*
|
||
|
Global FPS indicator. Add ?showfps to use in any application. Note that this REQUIRES true requestAnimationFrame
|
||
|
to be accurate.
|
||
|
*/
|
||
|
//<debug>
|
||
|
var paramsString = window.location.search.substr(1),
|
||
|
paramsArray = paramsString.split("&");
|
||
|
|
||
|
if (Ext.Array.contains(paramsArray, "showfps")) {
|
||
|
Ext.AnimationQueue.showFps();
|
||
|
}
|
||
|
//</debug>
|
||
|
|
||
|
});
|