mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-03-24 11:50:58 -04:00
Merge branch 'master' of https://github.com/codecombat/codecombat
This commit is contained in:
commit
f3c6745b29
17 changed files with 1239 additions and 829 deletions
app
assets/javascripts/workers
lib
templates/account
views
account
modal
play/level/tome
server/users
vendor/scripts
378
app/assets/javascripts/workers/worker_debug.js
Normal file
378
app/assets/javascripts/workers/worker_debug.js
Normal file
|
@ -0,0 +1,378 @@
|
|||
// There's no reason that this file is in JavaScript instead of CoffeeScript.
|
||||
// We should convert it and update the brunch config.
|
||||
|
||||
// If we wanted to be more robust, we could use this: https://github.com/padolsey/operative/blob/master/src/operative.js
|
||||
if(typeof window !== 'undefined' || !self.importScripts)
|
||||
throw "Attempt to load worker_world into main window instead of web worker.";
|
||||
|
||||
// Taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
|
||||
// This is here for running simuations in enviroments lacking function.bind (PhantomJS mostly)
|
||||
if (!Function.prototype.bind) {
|
||||
Function.prototype.bind = function (oThis) {
|
||||
if (typeof this !== "function") {
|
||||
// closest thing possible to the ECMAScript 5 internal IsCallable function
|
||||
throw new TypeError("Function.prototype.bind (Shim) - target is not callable");
|
||||
}
|
||||
|
||||
var aArgs = Array.prototype.slice.call(arguments, 1),
|
||||
fToBind = this,
|
||||
fNOP = function () {},
|
||||
fBound = function () {
|
||||
return fToBind.apply(this instanceof fNOP && oThis
|
||||
? this
|
||||
: oThis,
|
||||
aArgs.concat(Array.prototype.slice.call(arguments)));
|
||||
};
|
||||
|
||||
fNOP.prototype = this.prototype;
|
||||
fBound.prototype = new fNOP();
|
||||
|
||||
return fBound;
|
||||
};
|
||||
}
|
||||
|
||||
// assign global window so that Brunch's require (in world.js) can go into it
|
||||
self.window = self;
|
||||
self.workerID = "DebugWorker";
|
||||
|
||||
self.logLimit = 2000;
|
||||
self.logsLogged = 0;
|
||||
var console = {
|
||||
log: function() {
|
||||
if(self.logsLogged++ == self.logLimit)
|
||||
self.postMessage({type: 'console-log', args: ["Log limit " + self.logLimit + " reached; shutting up."], id: self.workerID});
|
||||
else if(self.logsLogged < self.logLimit) {
|
||||
args = [].slice.call(arguments);
|
||||
for(var i = 0; i < args.length; ++i) {
|
||||
if(args[i] && args[i].constructor) {
|
||||
if(args[i].constructor.className === "Thang" || args[i].isComponent)
|
||||
args[i] = args[i].toString();
|
||||
}
|
||||
}
|
||||
try {
|
||||
self.postMessage({type: 'console-log', args: args, id: self.workerID});
|
||||
}
|
||||
catch(error) {
|
||||
self.postMessage({type: 'console-log', args: ["Could not post log: " + args, error.toString(), error.stack, error.stackTrace], id: self.workerID});
|
||||
}
|
||||
}
|
||||
}}; // so that we don't crash when debugging statements happen
|
||||
console.error = console.info = console.log;
|
||||
self.console = console;
|
||||
|
||||
// We could do way more from this: http://stackoverflow.com/questions/10653809/making-webworkers-a-safe-environment
|
||||
Object.defineProperty(self, "XMLHttpRequest", {
|
||||
get: function() { throw new Error("Access to XMLHttpRequest is forbidden."); },
|
||||
configurable: false
|
||||
});
|
||||
|
||||
self.transferableSupported = function transferableSupported() {
|
||||
// Not in IE, even in IE 11
|
||||
try {
|
||||
var ab = new ArrayBuffer(1);
|
||||
worker.postMessage(ab, [ab]);
|
||||
return ab.byteLength == 0;
|
||||
} catch(error) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
importScripts('/javascripts/world.js');
|
||||
|
||||
var World = self.require('lib/world/world');
|
||||
var GoalManager = self.require('lib/world/GoalManager');
|
||||
serializedClasses = {
|
||||
"Thang": self.require('lib/world/thang'),
|
||||
"Vector": self.require('lib/world/vector'),
|
||||
"Rectangle": self.require('lib/world/rectangle')
|
||||
}
|
||||
|
||||
self.getCurrentFrame = function getCurrentFrame(args) { return self.world.frames.length; };
|
||||
|
||||
//optimize this later
|
||||
self.currentUserCodeMapCopy = {};
|
||||
self.currentWorldFrame = 0;
|
||||
|
||||
self.maxSerializationDepth = 3;
|
||||
|
||||
self.stringifyValue = function(value, depth) {
|
||||
var brackets, i, isArray, isObject, key, prefix, s, sep, size, v, values, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3;
|
||||
if (!value || _.isString(value)) {
|
||||
return value;
|
||||
}
|
||||
if (_.isFunction(value)) {
|
||||
if (depth === 2) {
|
||||
return void 0;
|
||||
} else {
|
||||
return "<Function>";
|
||||
}
|
||||
}
|
||||
if (value === this.thang && depth) {
|
||||
return "<this " + value.id + ">";
|
||||
}
|
||||
if (depth === 2) {
|
||||
if (((_ref = value.constructor) != null ? _ref.className : void 0) === "Thang") {
|
||||
value = "<" + (value.type || value.spriteName) + " - " + value.id + ", " + (value.pos ? value.pos.toString() : 'non-physical') + ">";
|
||||
} else {
|
||||
value = value.toString();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
isArray = _.isArray(value);
|
||||
isObject = _.isObject(value);
|
||||
if (!(isArray || isObject)) {
|
||||
return value.toString();
|
||||
}
|
||||
brackets = isArray ? ["[", "]"] : ["{", "}"];
|
||||
size = _.size(value);
|
||||
if (!size) {
|
||||
return brackets.join("");
|
||||
}
|
||||
values = [];
|
||||
if (isArray) {
|
||||
for (_i = 0, _len = value.length; _i < _len; _i++) {
|
||||
v = value[_i];
|
||||
s = this.stringifyValue(v, depth + 1);
|
||||
if (s !== void 0) {
|
||||
values.push("" + s);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_ref2 = (_ref1 = value.apiProperties) != null ? _ref1 : _.keys(value);
|
||||
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
|
||||
key = _ref2[_j];
|
||||
if (key[0] === "_") continue;
|
||||
s = this.stringifyValue(value[key], depth + 1);
|
||||
if (s !== void 0) {
|
||||
values.push(key + ": " + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
sep = '\n' + ((function() {
|
||||
var _k, _results;
|
||||
_results = [];
|
||||
for (i = _k = 0; 0 <= depth ? _k < depth : _k > depth; i = 0 <= depth ? ++_k : --_k) {
|
||||
_results.push(" ");
|
||||
}
|
||||
return _results;
|
||||
})()).join('');
|
||||
prefix = (_ref3 = value.constructor) != null ? _ref3.className : void 0;
|
||||
if (isArray) {
|
||||
if (prefix == null) {
|
||||
prefix = "Array";
|
||||
}
|
||||
}
|
||||
if (isObject) {
|
||||
if (prefix == null) {
|
||||
prefix = "Object";
|
||||
}
|
||||
}
|
||||
prefix = prefix ? prefix + " " : "";
|
||||
return "" + prefix + brackets[0] + sep + " " + (values.join(sep + ' ')) + sep + brackets[1];
|
||||
};
|
||||
|
||||
var cache = {};
|
||||
|
||||
self.invalidateCache = function () {
|
||||
cache = {};
|
||||
};
|
||||
|
||||
self.retrieveValueFromCache = function (thangID, spellID, variableChain, frame) {
|
||||
var frameCache, thangCache, spellCache;
|
||||
if ((frameCache = cache[frame]) && (thangCache = frameCache[thangID]) && (spellCache = thangCache[spellID]))
|
||||
return spellCache[variableChain.join()];
|
||||
return undefined;
|
||||
};
|
||||
|
||||
|
||||
self.updateCache = function (thangID, spellID, variableChain, frame, value) {
|
||||
var key, keys, currentObject;
|
||||
keys = [frame,thangID, spellID, variableChain.join()];
|
||||
currentObject = cache;
|
||||
|
||||
for (var i = 0, len = keys.length - 1; i < len; i++)
|
||||
{
|
||||
key = keys[i];
|
||||
if (!(key in currentObject))
|
||||
currentObject[key] = {};
|
||||
currentObject = currentObject[key];
|
||||
}
|
||||
currentObject[keys[keys.length - 1]] = value;
|
||||
};
|
||||
|
||||
self.retrieveValueFromFrame = function retrieveValueFromFrame(args) {
|
||||
var cacheValue;
|
||||
if (args.frame === self.currentWorldFrame && (cacheValue = self.retrieveValueFromCache(args.currentThangID, args.currentSpellID, args.variableChain, args.frame)))
|
||||
return self.postMessage({type: 'debug-value-return', serialized: {"key": args.variableChain.join("."), "value": cacheValue}});
|
||||
|
||||
|
||||
var retrieveProperty = function retrieveProperty(currentThangID, currentSpellID, variableChain)
|
||||
{
|
||||
var prop;
|
||||
var value;
|
||||
var keys = [];
|
||||
for (var i = 0, len = variableChain.length; i < len; i++) {
|
||||
prop = variableChain[i];
|
||||
if (prop === "this")
|
||||
{
|
||||
value = self.world.thangMap[currentThangID];
|
||||
|
||||
}
|
||||
else if (i === 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
var flowStates = self.world.userCodeMap[currentThangID][currentSpellID].flow.states;
|
||||
//we have to go to the second last flowState as we run the world for one additional frame
|
||||
//to collect the flow
|
||||
value = _.last(flowStates[flowStates.length - 2].statements).variables[prop];
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
value = undefined;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
value = value[prop];
|
||||
}
|
||||
keys.push(prop);
|
||||
if (!value) break;
|
||||
var classOfValue;
|
||||
if (classOfValue = serializedClasses[value.CN])
|
||||
{
|
||||
if (value.CN === "Thang")
|
||||
{
|
||||
var thang = self.world.thangMap[value.id];
|
||||
value = thang || "<Thang " + value.id + " (non-existent)>"
|
||||
}
|
||||
else
|
||||
{
|
||||
value = classOfValue.deserializeFromAether(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
var serializedProperty = {
|
||||
"key": keys.join("."),
|
||||
"value": self.stringifyValue(value,0)
|
||||
};
|
||||
self.updateCache(currentThangID,currentSpellID,variableChain, args.frame, serializedProperty.value);
|
||||
self.postMessage({type: 'debug-value-return', serialized: serializedProperty});
|
||||
};
|
||||
self.enableFlowOnThangSpell(args.currentThangID, args.currentSpellID, args.userCodeMap);
|
||||
self.setupWorldToRunUntilFrame(args);
|
||||
self.world.loadFramesUntilFrame(
|
||||
args.frame,
|
||||
retrieveProperty.bind({},args.currentThangID, args.currentSpellID, args.variableChain),
|
||||
self.onWorldError,
|
||||
self.onWorldLoadProgress
|
||||
);
|
||||
};
|
||||
|
||||
self.enableFlowOnThangSpell = function enableFlowOnThang(thangID, spellID, userCodeMap) {
|
||||
try {
|
||||
if (userCodeMap[thangID][spellID].originalOptions.includeFlow === true &&
|
||||
userCodeMap[thangID][spellID].originalOptions.noSerializationInFlow === true)
|
||||
return;
|
||||
else
|
||||
{
|
||||
userCodeMap[thangID][spellID].originalOptions.includeFlow = true;
|
||||
userCodeMap[thangID][spellID].originalOptions.noSerializationInFlow = true;
|
||||
var temporaryAether = Aether.deserialize(userCodeMap[thangID][spellID]);
|
||||
temporaryAether.transpile(temporaryAether.raw);
|
||||
userCodeMap[thangID][spellID] = temporaryAether.serialize();
|
||||
}
|
||||
|
||||
}
|
||||
catch (e) {
|
||||
console.log("there was an error enabling flow on thang spell:" + e)
|
||||
}
|
||||
};
|
||||
|
||||
self.setupWorldToRunUntilFrame = function setupWorldToRunUntilFrame(args) {
|
||||
self.postedErrors = {};
|
||||
self.t0 = new Date();
|
||||
self.firstWorld = args.firstWorld;
|
||||
self.postedErrors = false;
|
||||
self.logsLogged = 0;
|
||||
|
||||
var stringifiedUserCodeMap = JSON.stringify(args.userCodeMap);
|
||||
var userCodeMapHasChanged = ! _.isEqual(self.currentUserCodeMapCopy, stringifiedUserCodeMap);
|
||||
self.currentUserCodeMapCopy = stringifiedUserCodeMap;
|
||||
if (!self.world || userCodeMapHasChanged || args.frame != self.currentWorldFrame) {
|
||||
self.invalidateCache();
|
||||
try {
|
||||
self.world = new World(args.worldName, args.userCodeMap);
|
||||
if (args.level)
|
||||
self.world.loadFromLevel(args.level, true);
|
||||
self.goalManager = new GoalManager(self.world);
|
||||
self.goalManager.setGoals(args.goals);
|
||||
self.goalManager.setCode(args.userCodeMap);
|
||||
self.goalManager.worldGenerationWillBegin();
|
||||
self.world.setGoalManager(self.goalManager);
|
||||
}
|
||||
catch (error) {
|
||||
self.onWorldError(error);
|
||||
return;
|
||||
}
|
||||
Math.random = self.world.rand.randf; // so user code is predictable
|
||||
|
||||
self.world.totalFrames = args.frame; //hack to work around error checking
|
||||
self.currentWorldFrame = args.frame;
|
||||
}
|
||||
};
|
||||
self.runWorldUntilFrame = function runWorldUntilFrame(args) {
|
||||
self.setupWorldToRunUntilFrame(args);
|
||||
|
||||
self.world.loadFramesUntilFrame(args.frame, self.onWorldLoaded, self.onWorldError, self.onWorldLoadProgress);
|
||||
|
||||
};
|
||||
|
||||
self.onWorldLoaded = function onWorldLoaded() {
|
||||
console.log("World loaded!");
|
||||
};
|
||||
|
||||
self.onWorldError = function onWorldError(error) {
|
||||
if(error instanceof Aether.problems.UserCodeProblem) {
|
||||
if(!self.postedErrors[error.key]) {
|
||||
var problem = error.serialize();
|
||||
self.postMessage({type: 'user-code-problem', problem: problem});
|
||||
self.postedErrors[error.key] = problem;
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.log("Non-UserCodeError:", error.toString() + "\n" + error.stack || error.stackTrace);
|
||||
}
|
||||
/* We don't actually have the recoverable property any more; hmm
|
||||
if(!self.firstWorld && !error.recoverable) {
|
||||
self.abort();
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
return true;
|
||||
};
|
||||
|
||||
self.onWorldLoadProgress = function onWorldLoadProgress(progress) {
|
||||
self.postMessage({type: 'world-load-progress-changed', progress: progress});
|
||||
};
|
||||
|
||||
self.abort = function abort() {
|
||||
if(self.world && self.world.name) {
|
||||
console.log("About to abort:", self.world.name, typeof self.world.abort);
|
||||
if(typeof self.world !== "undefined")
|
||||
self.world.abort();
|
||||
self.world = null;
|
||||
}
|
||||
self.postMessage({type: 'abort'});
|
||||
};
|
||||
|
||||
self.reportIn = function reportIn() {
|
||||
self.postMessage({type: 'reportIn'});
|
||||
}
|
||||
|
||||
self.addEventListener('message', function(event) {
|
||||
self[event.data.func](event.data.args);
|
||||
});
|
||||
|
||||
self.postMessage({type: 'worker-initialized'});
|
|
@ -22,8 +22,13 @@ module.exports = class God
|
|||
@angels = []
|
||||
@firstWorld = true
|
||||
Backbone.Mediator.subscribe 'tome:cast-spells', @onTomeCast, @
|
||||
@retriveValueFromFrame = _.throttle @retrieveValueFromFrame, 1000
|
||||
Backbone.Mediator.subscribe 'tome:spell-debug-value-request', @retrieveValueFromFrame, @
|
||||
@fillWorkerPool = _.throttle @fillWorkerPool, 3000, leading: false
|
||||
@fillWorkerPool()
|
||||
#TODO: have this as a constructor option
|
||||
@debugWorker = @createDebugWorker()
|
||||
@currentUserCodeMap = {}
|
||||
|
||||
workerCode: '/javascripts/workers/worker_world.js' #Can be a string or a function.
|
||||
|
||||
|
@ -51,6 +56,13 @@ module.exports = class God
|
|||
worker.addEventListener 'message', @onWorkerMessage(worker)
|
||||
worker
|
||||
|
||||
createDebugWorker: ->
|
||||
worker = new Worker '/javascripts/workers/worker_debug.js'
|
||||
worker.creationTime = new Date()
|
||||
worker.addEventListener 'message', @onDebugWorkerMessage
|
||||
worker
|
||||
|
||||
|
||||
onWorkerMessage: (worker) =>
|
||||
unless worker.onMessage?
|
||||
worker.onMessage = (event) =>
|
||||
|
@ -62,6 +74,18 @@ module.exports = class God
|
|||
console.warn "Received strange word from God: #{event.data.type}"
|
||||
worker.onMessage
|
||||
|
||||
onDebugWorkerMessage: (event) =>
|
||||
worker = event.target
|
||||
switch event.data.type
|
||||
when "worker-initialized"
|
||||
worker.initialized = true
|
||||
when 'new-debug-world'
|
||||
console.log "New Debug world!"
|
||||
when 'console-log'
|
||||
console.log "|" + @id + "'s " + @id + "|", event.data.args...
|
||||
when 'debug-value-return'
|
||||
Backbone.Mediator.publish 'god:debug-value-return', event.data.serialized
|
||||
|
||||
getAngel: ->
|
||||
freeAngel = null
|
||||
for angel in @angels
|
||||
|
@ -113,6 +137,22 @@ module.exports = class God
|
|||
goals: @goalManager?.getGoals()
|
||||
}}
|
||||
|
||||
retrieveValueFromFrame: (args) ->
|
||||
if not args.thangID or not args.spellID or not args.variableChain then return
|
||||
args.frame ?= @world.age / @world.dt
|
||||
@debugWorker.postMessage
|
||||
func: 'retrieveValueFromFrame'
|
||||
args:
|
||||
worldName: @level.name
|
||||
userCodeMap: @currentUserCodeMap
|
||||
level: @level
|
||||
firstWorld: @firstWorld
|
||||
goals: @goalManager?.getGoals()
|
||||
frame: args.frame
|
||||
currentThangID: args.thangID
|
||||
currentSpellID: args.spellID
|
||||
variableChain: args.variableChain
|
||||
|
||||
#Coffeescript needs getters and setters.
|
||||
setGoalManager: (@goalManager) =>
|
||||
|
||||
|
@ -144,6 +184,7 @@ module.exports = class God
|
|||
finishBeholdingWorld: (newWorld) =>
|
||||
newWorld.findFirstChangedFrame @world
|
||||
@world = newWorld
|
||||
@currentUserCodeMap = @filterUserCodeMapWhenFromWorld @world.userCodeMap
|
||||
errorCount = (t for t in @world.thangs when t.errorsOut).length
|
||||
Backbone.Mediator.publish('god:new-world-created', world: @world, firstWorld: @firstWorld, errorCount: errorCount, goalStates: @latestGoalStates, team: me.team)
|
||||
for scriptNote in @world.scriptNotes
|
||||
|
@ -154,6 +195,23 @@ module.exports = class God
|
|||
unless _.find @angels, 'busy'
|
||||
@spells = null # Don't hold onto old spells; memory leaks
|
||||
|
||||
filterUserCodeMapWhenFromWorld: (worldUserCodeMap) ->
|
||||
newUserCodeMap = {}
|
||||
for thangName, thang of worldUserCodeMap
|
||||
newUserCodeMap[thangName] = {}
|
||||
for spellName,aether of thang
|
||||
shallowFilteredObject = _.pick aether, ['raw','pure','originalOptions']
|
||||
newUserCodeMap[thangName][spellName] = _.cloneDeep shallowFilteredObject
|
||||
newUserCodeMap[thangName][spellName] = _.defaults newUserCodeMap[thangName][spellName],
|
||||
flow: {}
|
||||
metrics: {}
|
||||
problems:
|
||||
errors: []
|
||||
infos: []
|
||||
warnings: []
|
||||
style: {}
|
||||
newUserCodeMap
|
||||
|
||||
getUserCodeMap: ->
|
||||
userCodeMap = {}
|
||||
for spellKey, spell of @spells
|
||||
|
@ -167,6 +225,10 @@ module.exports = class God
|
|||
@dead = true
|
||||
Backbone.Mediator.unsubscribe('tome:cast-spells', @onTomeCast, @)
|
||||
@goalManager?.destroy()
|
||||
@debugWorker?.terminate()
|
||||
@debugWorker?.removeEventListener 'message', @onDebugWorkerMessage
|
||||
@debugWorker ?= null
|
||||
@currentUserCodeMap = null
|
||||
@goalManager = null
|
||||
@fillWorkerPool = null
|
||||
@simulateWorld = null
|
||||
|
|
|
@ -59,13 +59,13 @@ module.exports = class LevelLoader extends CocoClass
|
|||
url = "/db/level/#{@levelID}/session"
|
||||
url += "?team=#{@team}" if @team
|
||||
|
||||
@session = new LevelSession().setURL url
|
||||
@supermodel.loadModel(@session, 'level_session', {cache:false})
|
||||
session = new LevelSession().setURL url
|
||||
@session = @supermodel.loadModel(session, 'level_session', {cache:false}).model
|
||||
@session.once 'sync', -> @url = -> '/db/level.session/' + @id
|
||||
|
||||
if @opponentSessionID
|
||||
@opponentSession = new LevelSession().setURL "/db/level_session/#{@opponentSessionID}"
|
||||
@supermodel.loadModel(@opponentSession, 'opponent_session')
|
||||
opponentSession = new LevelSession().setURL "/db/level_session/#{@opponentSessionID}"
|
||||
@opponentSession = @supermodel.loadModel(opponentSession, 'opponent_session').model
|
||||
|
||||
# Supermodel (Level) Loading
|
||||
|
||||
|
|
|
@ -379,7 +379,9 @@ module.exports = class SpriteParser
|
|||
argsSource = argsSource.replace(/cjs(.+)\)/, '"createjs$1)"') # turns cjs.Ease.get(0.5)
|
||||
|
||||
args = eval "[#{argsSource}]"
|
||||
if args[0]?.state?[0]?.t?.search?("shape") is 0 and not _.find(localShapes, bn: args[0].state[0].t)
|
||||
shadowTween = args[0]?.search?('shape') is 0 and not _.find(localShapes, bn: args[0])
|
||||
shadowTween = shadowTween or args[0]?.state?[0]?.t?.search?("shape") is 0 and not _.find(localShapes, bn: args[0].state[0].t)
|
||||
if shadowTween
|
||||
console.log "Skipping tween", name, argsSource, args, "from localShapes", localShapes, "presumably because it's a shadow we skipped."
|
||||
return
|
||||
callExpressions.push {n: name, a: args}
|
||||
|
|
|
@ -8,7 +8,6 @@ WorldScriptNote = require './world_script_note'
|
|||
{now, consolidateThangs, typedArraySupport} = require './world_utils'
|
||||
Component = require 'lib/world/component'
|
||||
System = require 'lib/world/system'
|
||||
|
||||
PROGRESS_UPDATE_INTERVAL = 200
|
||||
DESERIALIZATION_INTERVAL = 20
|
||||
|
||||
|
@ -107,6 +106,35 @@ module.exports = class World
|
|||
loadProgressCallback? 1
|
||||
loadedCallback()
|
||||
|
||||
loadFramesUntilFrame: (frameToLoadUntil, loadedCallback, errorCallback, loadProgressCallback) ->
|
||||
return if @aborted
|
||||
unless @thangs.length
|
||||
console.log "Warning: loadFrames called on empty World"
|
||||
t1 = now()
|
||||
@t0 ?= t1
|
||||
i = @frames.length
|
||||
while i <= frameToLoadUntil #state is gathered at next frame
|
||||
try
|
||||
@getFrame(i)
|
||||
++i # increment this after we have succeeded in getting the frame, otherwise we'll have to do that frame again
|
||||
catch error
|
||||
# Not an Aether.errors.UserCodeError; maybe we can't recover
|
||||
@addError error
|
||||
for error in (@unhandledRuntimeErrors ? [])
|
||||
return unless errorCallback error # errorCallback tells us whether the error is recoverable
|
||||
@unhandledRuntimeErrors = []
|
||||
t2 = now()
|
||||
if t2 - t1 > PROGRESS_UPDATE_INTERVAL
|
||||
loadProgressCallback? i / @totalFrames
|
||||
t1 = t2
|
||||
if t2 - @t0 > 1000
|
||||
console.log(' Loaded', i, 'of', frameToLoadUntil, "(+" + (t2 - @t0).toFixed(0) + "ms)")
|
||||
@t0 = t2
|
||||
setTimeout((=> @loadFrames(loadedCallback, errorCallback, loadProgressCallback)), 0)
|
||||
return
|
||||
loadProgressCallback? 1
|
||||
loadedCallback()
|
||||
|
||||
abort: ->
|
||||
@aborted = true
|
||||
|
||||
|
@ -225,7 +253,7 @@ module.exports = class World
|
|||
@scriptNotes.push scriptNote
|
||||
return unless @goalManager
|
||||
@goalManager.submitWorldGenerationEvent(channel, event, @frames.length)
|
||||
|
||||
|
||||
setGoalState: (goalID, status) ->
|
||||
@goalManager.setGoalState(goalID, status)
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ block content
|
|||
if user.id != me.id
|
||||
button.btn.edit-settings-button#enter-espionage-mode 007
|
||||
|
||||
if user.get('jobProfile')
|
||||
if user.get('jobProfile') && allowedToViewJobProfile
|
||||
- var profile = user.get('jobProfile');
|
||||
.job-profile-container
|
||||
.job-profile-row
|
||||
|
@ -112,7 +112,11 @@ block content
|
|||
.project-image(style="background-image: url('/file/" + project.picture + "')")
|
||||
p= project.name
|
||||
div!= marked(project.description)
|
||||
|
||||
else if allowedToViewJobProfile
|
||||
.public-profile-container
|
||||
h2 Loading...
|
||||
|
||||
|
||||
else
|
||||
.public-profile-container
|
||||
h2
|
||||
|
|
|
@ -18,7 +18,7 @@ module.exports = class ProfileView extends View
|
|||
super options
|
||||
if @userID is me.id
|
||||
@user = me
|
||||
else
|
||||
else if me.isAdmin() or "employer" in me.get('permissions')
|
||||
@user = User.getByID(@userID)
|
||||
@user.fetch()
|
||||
@listenTo @user, "sync", =>
|
||||
|
@ -27,6 +27,7 @@ module.exports = class ProfileView extends View
|
|||
getRenderData: ->
|
||||
context = super()
|
||||
context.user = @user
|
||||
context.allowedToViewJobProfile = me.isAdmin() or "employer" in me.get('permissions')
|
||||
context.myProfile = @user.id is context.me.id
|
||||
context.marked = marked
|
||||
context.moment = moment
|
||||
|
|
|
@ -20,6 +20,7 @@ module.exports = class EmployerSignupView extends View
|
|||
"click #contract-agreement-button": "agreeToContract"
|
||||
"click #create-account-button": "createAccount"
|
||||
"click .login-link": "setHashToOpenModalAutomatically"
|
||||
"keydown": "checkForFormSubmissionEnterPress"
|
||||
|
||||
|
||||
constructor: (options) ->
|
||||
|
@ -78,6 +79,9 @@ module.exports = class EmployerSignupView extends View
|
|||
handleAgreementFailure: (error) ->
|
||||
alert "There was an error signing the contract. Please contact team@codecombat.com with this error: #{error.responseText}"
|
||||
|
||||
checkForFormSubmissionEnterPress: (e) ->
|
||||
if e.which is 13 then @createAccount(e)
|
||||
|
||||
createAccount: (e) =>
|
||||
window.tracker?.trackEvent 'Finished Employer Signup'
|
||||
e.stopPropagation()
|
||||
|
|
|
@ -13,6 +13,8 @@ module.exports = class DebugView extends View
|
|||
|
||||
subscriptions:
|
||||
'god:new-world-created': 'onNewWorld'
|
||||
'god:debug-value-return': 'handleDebugValue'
|
||||
'tome:spell-shown': 'changeCurrentThangAndSpell'
|
||||
|
||||
events: {}
|
||||
|
||||
|
@ -20,12 +22,26 @@ module.exports = class DebugView extends View
|
|||
super options
|
||||
@ace = options.ace
|
||||
@thang = options.thang
|
||||
@spell = options.spell
|
||||
@variableStates = {}
|
||||
|
||||
@globals = {Math: Math, _: _, String: String, Number: Number, Array: Array, Object: Object} # ... add more as documented
|
||||
for className, klass of serializedClasses
|
||||
@globals[className] = klass
|
||||
for className, serializedClass of serializedClasses
|
||||
@globals[className] = serializedClass
|
||||
|
||||
@onMouseMove = _.throttle @onMouseMove, 25
|
||||
|
||||
changeCurrentThangAndSpell: (thangAndSpellObject) ->
|
||||
@thang = thangAndSpellObject.thang
|
||||
@spell = thangAndSpellObject.spell
|
||||
|
||||
handleDebugValue: (returnObject) ->
|
||||
{key, value} = returnObject
|
||||
if @variableChain and not key is @variableChain.join(".") then return
|
||||
@$el.find("code").text "#{key}: #{value}"
|
||||
@$el.show().css(@pos)
|
||||
|
||||
|
||||
afterRender: ->
|
||||
super()
|
||||
@ace.on "mousemove", @onMouseMove
|
||||
|
@ -58,7 +74,8 @@ module.exports = class DebugView extends View
|
|||
token = prev
|
||||
start = it.getCurrentTokenColumn()
|
||||
chain.unshift token.value
|
||||
if token and (token.value of @variableStates or token.value is "this" or @globals[token.value])
|
||||
#Highlight all tokens, so true overrides all other conditions TODO: Refactor this later
|
||||
if token and (true or token.value of @variableStates or token.value is "this" or @globals[token.value])
|
||||
@variableChain = chain
|
||||
offsetX = e.domEvent.offsetX ? e.clientX - $(e.domEvent.target).offset().left
|
||||
offsetY = e.domEvent.offsetY ? e.clientY - $(e.domEvent.target).offset().top
|
||||
|
@ -79,8 +96,11 @@ module.exports = class DebugView extends View
|
|||
|
||||
update: ->
|
||||
if @variableChain
|
||||
{key, value} = @deserializeVariableChain @variableChain
|
||||
@$el.find("code").text "#{key}: #{value}"
|
||||
Backbone.Mediator.publish 'tome:spell-debug-value-request',
|
||||
thangID: @thang.id
|
||||
spellID: @spell.name
|
||||
variableChain: @variableChain
|
||||
@$el.find("code").text "Finding value..."
|
||||
@$el.show().css(@pos)
|
||||
else
|
||||
@$el.hide()
|
||||
|
@ -98,7 +118,6 @@ module.exports = class DebugView extends View
|
|||
@hoveredProperty = if @variableChain?.length is 2 then owner: @variableChain[0], property: @variableChain[1] else {}
|
||||
unless _.isEqual oldHoveredProperty, @hoveredProperty
|
||||
Backbone.Mediator.publish 'tome:spell-debug-property-hovered', @hoveredProperty
|
||||
|
||||
updateMarker: ->
|
||||
if @marker
|
||||
@ace.getSession().removeMarker @marker
|
||||
|
|
|
@ -193,7 +193,7 @@ module.exports = class SpellView extends View
|
|||
@createToolbarView()
|
||||
|
||||
createDebugView: ->
|
||||
@debugView = new SpellDebugView ace: @ace, thang: @thang
|
||||
@debugView = new SpellDebugView ace: @ace, thang: @thang, spell:@spell
|
||||
@$el.append @debugView.render().$el.hide()
|
||||
|
||||
createToolbarView: ->
|
||||
|
|
|
@ -105,7 +105,8 @@ UserHandler = class UserHandler extends Handler
|
|||
(req, user, callback) ->
|
||||
return callback(null, req, user) unless req.body.name
|
||||
nameLower = req.body.name?.toLowerCase()
|
||||
# return callback(null, req, user) if nameLower is user.get('nameLower')
|
||||
return callback(null, req, user) unless nameLower
|
||||
return callback(null, req, user) if nameLower is user.get('nameLower') and not user.get('anonymous')
|
||||
User.findOne({nameLower:nameLower,anonymous:false}).exec (err, otherUser) ->
|
||||
log.error "Database error setting user name: #{err}" if err
|
||||
return callback(res:'Database error.', code:500) if err
|
||||
|
|
1
vendor/scripts/SpriteContainer.js
vendored
1
vendor/scripts/SpriteContainer.js
vendored
|
@ -41,6 +41,7 @@ this.createjs = this.createjs||{};
|
|||
* - all children (with the exception of DOMElement) MUST use the same spriteSheet.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* var data = {
|
||||
* images: ["sprites.jpg"],
|
||||
* frames: {width:50, height:50},
|
||||
|
|
1
vendor/scripts/SpriteStage.js
vendored
1
vendor/scripts/SpriteStage.js
vendored
|
@ -403,6 +403,7 @@ var p = SpriteStage.prototype = new createjs.Stage();
|
|||
* Children also MUST have either an image or spriteSheet defined on them (unless it's a DOMElement).
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* addChildAt(child1, index);
|
||||
*
|
||||
* You can also add multiple children, such as:
|
||||
|
|
171
vendor/scripts/easeljs-NEXT.combined.js
vendored
171
vendor/scripts/easeljs-NEXT.combined.js
vendored
|
@ -31,6 +31,7 @@
|
|||
* files of each library and are available on the createsjs namespace directly.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* myObject.addEventListener("change", createjs.proxy(myMethod, scope));
|
||||
*
|
||||
* @module CreateJS
|
||||
|
@ -240,6 +241,18 @@ var p = Event.prototype;
|
|||
p.clone = function() {
|
||||
return new Event(this.type, this.bubbles, this.cancelable);
|
||||
};
|
||||
|
||||
/**
|
||||
* Provides a chainable shortcut method for setting a number of properties on the instance.
|
||||
*
|
||||
* @method set
|
||||
* @param {Object} props A generic object containing properties to copy to the instance.
|
||||
* @return {Event} Returns the instance the method is called on (useful for chaining calls.)
|
||||
*/
|
||||
p.set = function(props) {
|
||||
for (var n in props) { this[n] = props[n]; }
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a string representation of this object.
|
||||
|
@ -862,6 +875,7 @@ this.createjs = this.createjs||{};
|
|||
* should not be instantiated.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* createjs.Ticker.addEventListener("tick", handleTick);
|
||||
* function handleTick(event) {
|
||||
* // Actions carried out each frame
|
||||
|
@ -937,6 +951,7 @@ var Ticker = function() {
|
|||
* {{#crossLink "Ticker/setPaused"}}{{/crossLink}}.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* createjs.Ticker.addEventListener("tick", handleTick);
|
||||
* function handleTick(event) {
|
||||
* console.log("Paused:", event.paused, event.delta);
|
||||
|
@ -1229,6 +1244,7 @@ var Ticker = function() {
|
|||
* callback when Ticker was paused. This is no longer the case.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* createjs.Ticker.addEventListener("tick", handleTick);
|
||||
* createjs.Ticker.setPaused(true);
|
||||
* function handleTick(event) {
|
||||
|
@ -1251,6 +1267,7 @@ var Ticker = function() {
|
|||
* callback when Ticker was paused. This is no longer the case.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* createjs.Ticker.addEventListener("tick", handleTick);
|
||||
* createjs.Ticker.setPaused(true);
|
||||
* function handleTick(event) {
|
||||
|
@ -2279,8 +2296,9 @@ this.createjs = this.createjs||{};
|
|||
* Represents a point on a 2 dimensional x / y coordinate system.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
* var point = new Point(0, 100);
|
||||
*
|
||||
*
|
||||
* var point = new createjs.Point(0, 100);
|
||||
*
|
||||
* @class Point
|
||||
* @param {Number} [x=0] X position.
|
||||
* @param {Number} [y=0] Y position.
|
||||
|
@ -2393,7 +2411,8 @@ this.createjs = this.createjs||{};
|
|||
/**
|
||||
* Represents a rectangle as defined by the points (x, y) and (x+width, y+height).
|
||||
*
|
||||
* @example
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* var rect = new createjs.Rectangle(0, 0, 100, 100);
|
||||
*
|
||||
* @class Rectangle
|
||||
|
@ -2789,6 +2808,7 @@ this.createjs = this.createjs||{};
|
|||
* via its <code>shadow</code> property.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* myImage.shadow = new createjs.Shadow("#000000", 5, 5, 10);
|
||||
*
|
||||
* @class Shadow
|
||||
|
@ -3427,6 +3447,7 @@ Command.prototype.exec = function(scope) { this.f.apply(scope, this.params); };
|
|||
* context of an Easel display list.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* var g = new createjs.Graphics();
|
||||
* g.setStrokeStyle(1);
|
||||
* g.beginStroke(createjs.Graphics.getRGB(0,0,0));
|
||||
|
@ -3760,7 +3781,7 @@ var p = Graphics.prototype;
|
|||
|
||||
/**
|
||||
* Draws only the path described for this Graphics instance, skipping any non-path instructions, including fill and
|
||||
* stroke descriptions. Used by <code>DisplayObject.clippingPath</code> to draw the clipping path, for example.
|
||||
* stroke descriptions. Used for <code>DisplayObject.mask</code> to draw the clipping path, for example.
|
||||
* @method drawAsPath
|
||||
* @param {CanvasRenderingContext2D} ctx The canvas 2D context object to draw into.
|
||||
**/
|
||||
|
@ -5785,9 +5806,8 @@ var p = DisplayObject.prototype = new createjs.EventDispatcher();
|
|||
};
|
||||
|
||||
/**
|
||||
* Tests whether the display object intersects the specified local point (ie. draws a pixel with alpha > 0 at
|
||||
* the specified position). This ignores the alpha, shadow and compositeOperation of the display object, and all
|
||||
* transform properties including regX/Y.
|
||||
* Tests whether the display object intersects the specified point in local coordinates (ie. draws a pixel with alpha > 0 at
|
||||
* the specified position). This ignores the alpha, shadow, hitArea, mask, and compositeOperation of the display object.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
|
@ -5804,7 +5824,7 @@ var p = DisplayObject.prototype = new createjs.EventDispatcher();
|
|||
* local Point.
|
||||
*/
|
||||
p.hitTest = function(x, y) {
|
||||
// TODO: update with support for .hitArea and update hitArea docs?
|
||||
// TODO: update with support for .hitArea & .mask and update hitArea / mask docs?
|
||||
var ctx = DisplayObject._hitTestContext;
|
||||
ctx.setTransform(1, 0, 0, 1, -x, -y);
|
||||
this.draw(ctx);
|
||||
|
@ -5816,7 +5836,7 @@ var p = DisplayObject.prototype = new createjs.EventDispatcher();
|
|||
};
|
||||
|
||||
/**
|
||||
* Provides a chainable shortcut method for setting a number of properties on a DisplayObject instance.
|
||||
* Provides a chainable shortcut method for setting a number of properties on the instance.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
|
@ -5826,7 +5846,7 @@ var p = DisplayObject.prototype = new createjs.EventDispatcher();
|
|||
*
|
||||
* @method set
|
||||
* @param {Object} props A generic object containing properties to copy to the DisplayObject instance.
|
||||
* @return {DisplayObject} Returns The DisplayObject instance the method is called on (useful for chaining calls.)
|
||||
* @return {DisplayObject} Returns the instance the method is called on (useful for chaining calls.)
|
||||
*/
|
||||
p.set = function(props) {
|
||||
for (var n in props) { this[n] = props[n]; }
|
||||
|
@ -6002,17 +6022,16 @@ var p = DisplayObject.prototype = new createjs.EventDispatcher();
|
|||
|
||||
/**
|
||||
* @method _tick
|
||||
* @param {Array} params Parameters to pass on to any listeners of the tick function. This will usually include the
|
||||
* @param {Object} props Props to copy to the tick event object. This will usually include the
|
||||
* properties from the {{#crossLink "Ticker"}}{{/crossLink}} "tick" event, such as `delta` and `paused`, but may
|
||||
* be undefined or contain other values depending on the usage by the application.
|
||||
* @protected
|
||||
**/
|
||||
p._tick = function(params) {
|
||||
p._tick = function(props) {
|
||||
// because tick can be really performance sensitive, we'll inline some of the dispatchEvent work.
|
||||
var ls = this._listeners;
|
||||
if (ls && ls["tick"]) {
|
||||
var evt = new createjs.Event("tick");
|
||||
evt.params = params;
|
||||
var evt = new createjs.Event("tick").set(props);
|
||||
this._dispatchEvent(evt, this, 2);
|
||||
}
|
||||
};
|
||||
|
@ -6180,6 +6199,7 @@ this.createjs = this.createjs||{};
|
|||
* Containers have some overhead, so you generally shouldn't create a Container to hold a single child.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* var container = new createjs.Container();
|
||||
* container.addChild(bitmapInstance, shapeInstance);
|
||||
* container.x = 100;
|
||||
|
@ -6299,6 +6319,7 @@ var p = Container.prototype = new createjs.DisplayObject();
|
|||
* Adds a child to the top of the display list.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* container.addChild(bitmapInstance);
|
||||
*
|
||||
* You can also add multiple children at once:
|
||||
|
@ -6327,6 +6348,7 @@ var p = Container.prototype = new createjs.DisplayObject();
|
|||
* setting its parent to this Container.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* addChildAt(child1, index);
|
||||
*
|
||||
* You can also add multiple children, such as:
|
||||
|
@ -6364,6 +6386,7 @@ var p = Container.prototype = new createjs.DisplayObject();
|
|||
* already known.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* container.removeChild(child);
|
||||
*
|
||||
* You can also remove multiple children:
|
||||
|
@ -6422,6 +6445,7 @@ var p = Container.prototype = new createjs.DisplayObject();
|
|||
* Removes all children from the display list.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* container.removeAlLChildren();
|
||||
*
|
||||
* @method removeAllChildren
|
||||
|
@ -6435,6 +6459,7 @@ var p = Container.prototype = new createjs.DisplayObject();
|
|||
* Returns the child at the specified index.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* container.getChildAt(2);
|
||||
*
|
||||
* @method getChildAt
|
||||
|
@ -6483,6 +6508,7 @@ var p = Container.prototype = new createjs.DisplayObject();
|
|||
* Returns the index of the specified child in the display list, or -1 if it is not in the display list.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* var index = container.getChildIndex(child);
|
||||
*
|
||||
* @method getChildIndex
|
||||
|
@ -6590,6 +6616,8 @@ var p = Container.prototype = new createjs.DisplayObject();
|
|||
* of visual depth, with the top-most display object at index 0. This uses shape based hit detection, and can be an
|
||||
* expensive operation to run, so it is best to use it carefully. For example, if testing for objects under the
|
||||
* mouse, test on tick (instead of on mousemove), and only if the mouse's position has changed.
|
||||
*
|
||||
* Accounts for both {{#crossLink "DisplayObject/hitArea:property"}}{{/crossLink}} and {{#crossLink "DisplayObject/mask:property"}}{{/crossLink}}.
|
||||
* @method getObjectsUnderPoint
|
||||
* @param {Number} x The x position in the container to test.
|
||||
* @param {Number} y The y position in the container to test.
|
||||
|
@ -6679,18 +6707,18 @@ var p = Container.prototype = new createjs.DisplayObject();
|
|||
|
||||
/**
|
||||
* @method _tick
|
||||
* @param {Array} params Parameters to pass onto the DisplayObject {{#crossLink "DisplayObject/tick"}}{{/crossLink}}
|
||||
* @param {Object} props Properties to copy to the DisplayObject {{#crossLink "DisplayObject/tick"}}{{/crossLink}} event object.
|
||||
* function.
|
||||
* @protected
|
||||
**/
|
||||
p._tick = function(params) {
|
||||
p._tick = function(props) {
|
||||
if (this.tickChildren) {
|
||||
for (var i=this.children.length-1; i>=0; i--) {
|
||||
var child = this.children[i];
|
||||
if (child.tickEnabled && child._tick) { child._tick(params); }
|
||||
if (child.tickEnabled && child._tick) { child._tick(props); }
|
||||
}
|
||||
}
|
||||
this.DisplayObject__tick(params);
|
||||
this.DisplayObject__tick(props);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -6713,8 +6741,23 @@ var p = Container.prototype = new createjs.DisplayObject();
|
|||
var l = children.length;
|
||||
for (var i=l-1; i>=0; i--) {
|
||||
var child = children[i];
|
||||
var hitArea = child.hitArea;
|
||||
var hitArea = child.hitArea, mask = child.mask;
|
||||
if (!child.visible || (!hitArea && !child.isVisible()) || (mouse && !child.mouseEnabled)) { continue; }
|
||||
if (!hitArea && mask && mask.graphics && !mask.graphics.isEmpty()) {
|
||||
var maskMtx = mask.getMatrix(mask._matrix).prependMatrix(this.getConcatenatedMatrix(mtx));
|
||||
ctx.setTransform(maskMtx.a, maskMtx.b, maskMtx.c, maskMtx.d, maskMtx.tx-x, maskMtx.ty-y);
|
||||
|
||||
// draw the mask as a solid fill:
|
||||
mask.graphics.drawAsPath(ctx);
|
||||
ctx.fillStyle = "#000";
|
||||
ctx.fill();
|
||||
|
||||
// if we don't hit the mask, then no need to keep looking at this DO:
|
||||
if (!this._testHit(ctx)) { continue; }
|
||||
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
||||
ctx.clearRect(0, 0, 2, 2);
|
||||
}
|
||||
|
||||
// if a child container has a hitArea then we only need to check its hitArea, so we can treat it as a normal DO:
|
||||
if (!hitArea && child instanceof Container) {
|
||||
var result = child._getObjectsUnderPoint(x, y, arr, mouse, activeListener);
|
||||
|
@ -7138,30 +7181,19 @@ var p = Stage.prototype = new createjs.Container();
|
|||
// public methods:
|
||||
|
||||
/**
|
||||
* Each time the update method is called, the stage will tick all descendants (see: {{#crossLink "DisplayObject/tick"}}{{/crossLink}})
|
||||
* and then render the display list to the canvas. Any parameters passed to `update()` will be passed on to any
|
||||
* {{#crossLink "DisplayObject/tick:event"}}{{/crossLink}} event handlers.
|
||||
*
|
||||
* Some time-based features in EaselJS (for example {{#crossLink "Sprite/framerate"}}{{/crossLink}} require that
|
||||
* a tick event object (or equivalent) be passed as the first parameter to update(). For example:
|
||||
*
|
||||
* Ticker.addEventListener("tick", handleTick);
|
||||
* function handleTick(evtObj) {
|
||||
* // do some work here, then update the stage, passing through the event object:
|
||||
* myStage.update(evtObj);
|
||||
* }
|
||||
* Each time the update method is called, the stage will call {{#crossLink "Stage/tick"}}{{/crossLink}}
|
||||
* unless {{#crossLink "Stage/tickOnUpdate:property"}}{{/crossLink}} is set to false,
|
||||
* and then render the display list to the canvas.
|
||||
*
|
||||
* @method update
|
||||
* @param {*} [params]* Params to include when ticking descendants. The first param should usually be a tick event.
|
||||
* @param {*} [params]* Params to pass to .tick() if .tickOnUpdate is true.
|
||||
**/
|
||||
p.update = function(params) {
|
||||
if (!this.canvas) { return; }
|
||||
if (this.tickOnUpdate) {
|
||||
this.dispatchEvent("tickstart"); // TODO: make cancellable?
|
||||
this.tickEnabled&&this._tick((arguments.length ? arguments : null));
|
||||
this.dispatchEvent("tickend");
|
||||
if (this.tickOnUpdate) { // update this logic in SpriteStage when necessary
|
||||
this.tick.apply(this, arguments);
|
||||
}
|
||||
this.dispatchEvent("drawstart"); // TODO: make cancellable?
|
||||
this.dispatchEvent("drawstart"); //TODO: make cancellable?
|
||||
createjs.DisplayObject._snapToPixelEnabled = this.snapToPixelEnabled;
|
||||
if (this.autoClear) { this.clear(); }
|
||||
var ctx = this.canvas.getContext("2d");
|
||||
|
@ -7171,6 +7203,47 @@ var p = Stage.prototype = new createjs.Container();
|
|||
ctx.restore();
|
||||
this.dispatchEvent("drawend");
|
||||
};
|
||||
|
||||
/**
|
||||
* Propagates a tick event through the display list. This is automatically called by {{#crossLink "Stage/update"}}{{/crossLink}}
|
||||
* unless {{#crossLink "Stage/tickOnUpdate:property"}}{{/crossLink}} is set to false.
|
||||
*
|
||||
* Any parameters passed to `tick()` will be included as an array in the "param" property of the event object dispatched
|
||||
* to {{#crossLink "DisplayObject/tick:event"}}{{/crossLink}} event handlers. Additionally, if the first parameter
|
||||
* is a {{#crossLink "Ticker/tick:event"}}{{/crossLink}} event object (or has equivalent properties), then the delta,
|
||||
* time, runTime, and paused properties will be copied to the event object.
|
||||
*
|
||||
* Some time-based features in EaselJS (for example {{#crossLink "Sprite/framerate"}}{{/crossLink}} require that
|
||||
* a {{#crossLink "Ticker/tick:event"}}{{/crossLink}} event object (or equivalent) be passed as the first parameter
|
||||
* to tick(). For example:
|
||||
*
|
||||
* Ticker.on("tick", handleTick);
|
||||
* function handleTick(evtObj) {
|
||||
* // do some work here, then update the stage, passing through the tick event object as the first param
|
||||
* // and some custom data as the second and third param:
|
||||
* myStage.update(evtObj, "hello", 2014);
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
* myDisplayObject.on("tick", handleDisplayObjectTick);
|
||||
* function handleDisplayObjectTick(evt) {
|
||||
* console.log(evt.params[0]); // the original tick evtObj
|
||||
* console.log(evt.delta, evt.paused); // ex. "17 false"
|
||||
* console.log(evt.params[1], evt.params[2]); // "hello 2014"
|
||||
* }
|
||||
*
|
||||
* @method tick
|
||||
* @param {*} [params]* Params to include when ticking descendants. The first param should usually be a tick event.
|
||||
**/
|
||||
p.tick = function(params) {
|
||||
this.dispatchEvent("tickstart"); //TODO: make cancellable?
|
||||
var args = arguments.length ? Array.prototype.slice.call(arguments,0) : null;
|
||||
var evt = args&&args[0];
|
||||
var props = evt&&(evt.delta != null) ? {delta:evt.delta, paused:evt.paused, time:evt.time, runTime:evt.runTime } : {};
|
||||
props.params = args;
|
||||
this.tickEnabled&&this._tick(props);
|
||||
this.dispatchEvent("tickend");
|
||||
};
|
||||
|
||||
/**
|
||||
* Default event handler that calls the Stage {{#crossLink "Stage/update"}}{{/crossLink}} method when a {{#crossLink "DisplayObject/tick:event"}}{{/crossLink}}
|
||||
|
@ -7263,6 +7336,7 @@ var p = Stage.prototype = new createjs.Container();
|
|||
* independently of mouse move events via the optional `frequency` parameter.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* var stage = new createjs.Stage("canvasId");
|
||||
* stage.enableMouseOver(10); // 10 updates per second
|
||||
*
|
||||
|
@ -7687,6 +7761,7 @@ this.createjs = this.createjs||{};
|
|||
* HTML element, or a string.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* var bitmap = new createjs.Bitmap("imagePath.jpg");
|
||||
*
|
||||
* <strong>Notes:</strong>
|
||||
|
@ -7924,6 +7999,7 @@ this.createjs = this.createjs||{};
|
|||
* See the {{#crossLink "SpriteSheet"}}{{/crossLink}} class for more information on setting up frames and animations.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* var instance = new createjs.Sprite(spriteSheet);
|
||||
* instance.gotoAndStop("frameName");
|
||||
*
|
||||
|
@ -7935,7 +8011,7 @@ this.createjs = this.createjs||{};
|
|||
* @constructor
|
||||
* @param {SpriteSheet} spriteSheet The SpriteSheet instance to play back. This includes the source image(s), frame
|
||||
* dimensions, and frame data. See {{#crossLink "SpriteSheet"}}{{/crossLink}} for more information.
|
||||
* @param {String|Number} frameOrAnimation The frame number or animation to play initially.
|
||||
* @param {String|Number} [frameOrAnimation] The frame number or animation to play initially.
|
||||
**/
|
||||
var Sprite = function(spriteSheet, frameOrAnimation) {
|
||||
this.initialize(spriteSheet, frameOrAnimation);
|
||||
|
@ -8254,14 +8330,15 @@ var p = Sprite.prototype = new createjs.DisplayObject();
|
|||
/**
|
||||
* Advances the <code>currentFrame</code> if paused is not true. This is called automatically when the {{#crossLink "Stage"}}{{/crossLink}}
|
||||
* ticks.
|
||||
* @param {Object} props Properties to copy to the DisplayObject {{#crossLink "DisplayObject/tick"}}{{/crossLink}} event object.
|
||||
* @protected
|
||||
* @method _tick
|
||||
**/
|
||||
p._tick = function(params) {
|
||||
p._tick = function(props) {
|
||||
if (!this.paused) {
|
||||
this.advance(params&¶ms[0]&¶ms[0].delta);
|
||||
this.advance(props&&props.delta);
|
||||
}
|
||||
this.DisplayObject__tick(params);
|
||||
this.DisplayObject__tick(props);
|
||||
};
|
||||
|
||||
|
||||
|
@ -8338,7 +8415,7 @@ var p = Sprite.prototype = new createjs.DisplayObject();
|
|||
|
||||
/**
|
||||
* @method cloneProps
|
||||
* @param {Text} o
|
||||
* @param {Sprite} o
|
||||
* @protected
|
||||
**/
|
||||
p.cloneProps = function(o) {
|
||||
|
@ -8477,6 +8554,7 @@ this.createjs = this.createjs||{};
|
|||
* rendering cost.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* var graphics = new createjs.Graphics().beginFill("#ff0000").drawRect(0, 0, 100, 100);
|
||||
* var shape = new createjs.Shape(graphics);
|
||||
*
|
||||
|
@ -8629,6 +8707,7 @@ this.createjs = this.createjs||{};
|
|||
* multiple font styles, you will need to create multiple text instances, and position them manually.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* var text = new createjs.Text("Hello World", "20px Arial", "#ff7700");
|
||||
* text.x = 100;
|
||||
* text.textBaseline = "alphabetic";
|
||||
|
@ -10341,14 +10420,14 @@ var p = DOMElement.prototype = new createjs.DisplayObject();
|
|||
|
||||
/**
|
||||
* @method _tick
|
||||
* @param {Array} params Parameters to pass onto the DisplayObject {{#crossLink "DisplayObject/tick"}}{{/crossLink}}
|
||||
* @param {Object} props Properties to copy to the DisplayObject {{#crossLink "DisplayObject/tick"}}{{/crossLink}} event object.
|
||||
* function.
|
||||
* @protected
|
||||
*/
|
||||
p._tick = function(params) {
|
||||
p._tick = function(props) {
|
||||
var stage = this.getStage();
|
||||
stage&&stage.on("drawend", this._handleDrawEnd, this, true);
|
||||
this.DisplayObject__tick(params);
|
||||
this.DisplayObject__tick(props);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -10427,6 +10506,7 @@ this.createjs = this.createjs||{};
|
|||
* {{#crossLink "DisplayObject/updateCache"}}{{/crossLink}}. Note that the filters must be applied before caching.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* myInstance.filters = [
|
||||
* new createjs.ColorFilter(0, 0, 0, 1, 255, 0, 0),
|
||||
* new createjs.BlurFilter(5, 5, 10)
|
||||
|
@ -11428,6 +11508,7 @@ this.createjs = this.createjs||{};
|
|||
* chained calls.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* myColorMatrix.adjustHue(20).adjustBrightness(50);
|
||||
*
|
||||
* See {{#crossLink "Filter"}}{{/crossLink}} for an example of how to apply filters, or {{#crossLink "ColorMatrixFilter"}}{{/crossLink}}
|
||||
|
|
126
vendor/scripts/preloadjs-NEXT.combined.js
vendored
126
vendor/scripts/preloadjs-NEXT.combined.js
vendored
|
@ -27,7 +27,7 @@ this.createjs = this.createjs||{};
|
|||
* @type String
|
||||
* @static
|
||||
**/
|
||||
s.buildDate = /*date*/"Thu, 06 Mar 2014 22:58:10 GMT"; // injected by build process
|
||||
s.buildDate = /*date*/"Wed, 02 Apr 2014 17:54:19 GMT"; // injected by build process
|
||||
|
||||
})();
|
||||
/*
|
||||
|
@ -909,24 +909,32 @@ this.createjs = this.createjs||{};
|
|||
var s = AbstractLoader;
|
||||
|
||||
/**
|
||||
* The RegExp pattern to use to parse file URIs. This supports simple file names, as well as full domain URIs with
|
||||
* query strings. The resulting match is: protocol:$1 domain:$2 relativePath:$3 path:$4 file:$5 extension:$6 query:$7.
|
||||
* @property FILE_PATTERN
|
||||
* @type {RegExp}
|
||||
* The Regular Expression used to test file URLS for an absolute path.
|
||||
* @property ABSOLUTE_PATH
|
||||
* @static
|
||||
* @protected
|
||||
* @type {RegExp}
|
||||
* @since 0.4.2
|
||||
*/
|
||||
s.FILE_PATTERN = /^(?:(\w+:)\/{2}(\w+(?:\.\w+)*\/?)|(.{0,2}\/{1}))?([/.]*?(?:[^?]+)?\/)?((?:[^/?]+)\.(\w+))(?:\?(\S+)?)?$/;
|
||||
s.ABSOLUTE_PATT = /^(?:\w+:)?\/{2}/i;
|
||||
|
||||
/**
|
||||
* The RegExp pattern to use to parse path URIs. This supports protocols, relative files, and paths. The resulting
|
||||
* match is: protocol:$1 relativePath:$2 path$3.
|
||||
* @property PATH_PATTERN
|
||||
* @type {RegExp}
|
||||
* The Regular Expression used to test file URLS for an absolute path.
|
||||
* @property RELATIVE_PATH
|
||||
* @static
|
||||
* @protected
|
||||
* @type {RegExp}
|
||||
* @since 0.4.2
|
||||
*/
|
||||
s.PATH_PATTERN = /^(?:(\w+:)\/{2})|(.{0,2}\/{1})?([/.]*?(?:[^?]+)?\/?)?$/;
|
||||
s.RELATIVE_PATT = (/^[./]*?\//i);
|
||||
|
||||
/**
|
||||
* The Regular Expression used to test file URLS for an extension. Note that URIs must already have the query string
|
||||
* removed.
|
||||
* @property EXTENSION_PATT
|
||||
* @static
|
||||
* @type {RegExp}
|
||||
* @since 0.4.2
|
||||
*/
|
||||
s.EXTENSION_PATT = /\/?[^/]+\.(\w{1,5})$/i;
|
||||
|
||||
/**
|
||||
* If the loader has completed loading. This provides a quick check, but also ensures that the different approaches
|
||||
|
@ -1164,29 +1172,49 @@ this.createjs = this.createjs||{};
|
|||
};
|
||||
|
||||
/**
|
||||
* Parse a file URI using the {{#crossLink "AbstractLoader/FILE_PATTERN:property"}}{{/crossLink}} RegExp pattern.
|
||||
* @method _parseURI
|
||||
* @param {String} path The file path to parse.
|
||||
* @return {Array} The matched file contents. Please see the FILE_PATTERN property for details on the return value.
|
||||
* This will return null if it does not match.
|
||||
* @protected
|
||||
* Parse a file path to determine the information we need to work with it. Currently, PreloadJS needs to know:
|
||||
* <ul>
|
||||
* <li>If the path is absolute. Absolute paths start with a protocol (such as `http://`, `file://`, or
|
||||
* `//networkPath`)</li>
|
||||
* <li>If the path is relative. Relative paths start with `../` or `/path` (or similar)</li>
|
||||
* <li>The file extension. This is determined by the filename with an extension. Query strings are dropped, and
|
||||
* the file path is expected to follow the format `name.ext`.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <strong>Note:</strong> This has changed from earlier versions, which used a single, complicated Regular Expression, which
|
||||
* was difficult to maintain, and over-aggressive in determining all file properties. It has been simplified to
|
||||
* only pull out what it needs.
|
||||
* @param path
|
||||
* @returns {Object} An Object with an `absolute` and `relative` Boolean, as well as an optional 'extension` String
|
||||
* property, which is the lowercase extension.
|
||||
* @private
|
||||
*/
|
||||
p._parseURI = function(path) {
|
||||
if (!path) { return null; }
|
||||
return path.match(s.FILE_PATTERN);
|
||||
};
|
||||
var info = { absolute: false, relative:false };
|
||||
if (path == null) { return info; };
|
||||
|
||||
/**
|
||||
* Parse a file URI using the {{#crossLink "AbstractLoader/PATH_PATTERN"}}{{/crossLink}} RegExp pattern.
|
||||
* @method _parsePath
|
||||
* @param {String} path The file path to parse.
|
||||
* @return {Array} The matched path contents. Please see the PATH_PATTERN property for details on the return value.
|
||||
* This will return null if it does not match.
|
||||
* @protected
|
||||
*/
|
||||
p._parsePath = function(path) {
|
||||
if (!path) { return null; }
|
||||
return path.match(s.PATH_PATTERN);
|
||||
// Drop the query string
|
||||
var queryIndex = path.indexOf("?");
|
||||
if (queryIndex > -1) {
|
||||
path = path.substr(0,queryIndex);
|
||||
}
|
||||
|
||||
// Absolute
|
||||
var match;
|
||||
if (s.ABSOLUTE_PATT.test(path)) {
|
||||
info.absolute = true;
|
||||
|
||||
// Relative
|
||||
} else if (s.RELATIVE_PATT.test(path)) {
|
||||
info.relative = true;
|
||||
}
|
||||
|
||||
// Extension
|
||||
if (match = path.match(s.EXTENSION_PATT)) {
|
||||
info.extension = match[1].toLowerCase();
|
||||
}
|
||||
return info;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2593,7 +2621,7 @@ TODO: WINDOWS ISSUES
|
|||
|
||||
// Determine Extension, etc.
|
||||
var match = this._parseURI(item.src);
|
||||
if (match != null) { item.ext = match[6]; }
|
||||
if (match.extension) { item.ext = match.extension; }
|
||||
if (item.type == null) {
|
||||
item.type = this._getTypeByExtension(item.ext);
|
||||
}
|
||||
|
@ -2602,13 +2630,13 @@ TODO: WINDOWS ISSUES
|
|||
var bp = ""; // Store the generated basePath
|
||||
var useBasePath = basePath || this._basePath;
|
||||
var autoId = item.src;
|
||||
if (match && match[1] == null && match[3] == null) {
|
||||
if (!match.absolute && !match.relative) {
|
||||
if (path) {
|
||||
bp = path;
|
||||
var pathMatch = this._parsePath(path);
|
||||
var pathMatch = this._parseURI(path);
|
||||
autoId = path + autoId;
|
||||
// Also append basePath
|
||||
if (useBasePath != null && pathMatch && pathMatch[1] == null && pathMatch[2] == null) {
|
||||
if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) {
|
||||
bp = useBasePath + bp;
|
||||
}
|
||||
} else if (useBasePath != null) {
|
||||
|
@ -2666,8 +2694,8 @@ TODO: WINDOWS ISSUES
|
|||
|
||||
// Update the extension in case the type changed:
|
||||
match = this._parseURI(item.src);
|
||||
if (match != null && match[6] != null) {
|
||||
item.ext = match[6].toLowerCase();
|
||||
if (match.extension != null) {
|
||||
item.ext = match.extension;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3396,7 +3424,16 @@ this.createjs = this.createjs||{};
|
|||
item.type == createjs.LoadQueue.CSS) {
|
||||
this._startTagVisibility = tag.style.visibility;
|
||||
tag.style.visibility = "hidden";
|
||||
(document.body || document.getElementsByTagName("body")[0]).appendChild(tag);
|
||||
var node = document.body || document.getElementsByTagName("body")[0];
|
||||
if (node == null) {
|
||||
if (item.type == createjs.LoadQueue.SVG) {
|
||||
this._handleSVGError();
|
||||
return;
|
||||
} else {
|
||||
node = document.head || document.getElementsByTagName("head");
|
||||
}
|
||||
}
|
||||
node.appendChild(tag);
|
||||
}
|
||||
|
||||
// Note: Previous versions didn't seem to work when we called load() for OGG tags in Firefox. Seems fixed in 15.0.1
|
||||
|
@ -3405,6 +3442,13 @@ this.createjs = this.createjs||{};
|
|||
}
|
||||
};
|
||||
|
||||
p._handleSVGError = function() {
|
||||
this._clean();
|
||||
var event = new createjs.Event("error");
|
||||
event.text = "SVG_NO_BODY";
|
||||
this._sendError(event);
|
||||
};
|
||||
|
||||
p._handleJSONPLoad = function(data) {
|
||||
this._jsonResult = data;
|
||||
};
|
||||
|
@ -3488,8 +3532,8 @@ this.createjs = this.createjs||{};
|
|||
// case createjs.LoadQueue.CSS:
|
||||
//LM: We may need to remove CSS tags loaded using a LINK
|
||||
tag.style.visibility = this._startTagVisibility;
|
||||
(document.body || document.getElementsByTagName("body")[0]).removeChild(tag);
|
||||
break;
|
||||
tag.parentNode && tag.parentNode.contains(tag) && tag.parentNode.removeChild(tag);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
|
|
1222
vendor/scripts/soundjs-NEXT.combined.js
vendored
1222
vendor/scripts/soundjs-NEXT.combined.js
vendored
File diff suppressed because it is too large
Load diff
12
vendor/scripts/tweenjs-NEXT.combined.js
vendored
12
vendor/scripts/tweenjs-NEXT.combined.js
vendored
|
@ -909,9 +909,10 @@ var p = Tween.prototype = new createjs.EventDispatcher();
|
|||
if (!target.tweenjs_count) { return; }
|
||||
var tweens = Tween._tweens;
|
||||
for (var i=tweens.length-1; i>=0; i--) {
|
||||
if (tweens[i]._target == target) {
|
||||
tweens[i]._paused = true;
|
||||
tweens.splice(i,1);
|
||||
var tween = tweens[i];
|
||||
if (tween._target == target) {
|
||||
tween._paused = true;
|
||||
tweens.splice(i, 1);
|
||||
}
|
||||
}
|
||||
target.tweenjs_count = 0;
|
||||
|
@ -927,7 +928,7 @@ var p = Tween.prototype = new createjs.EventDispatcher();
|
|||
var tweens = Tween._tweens;
|
||||
for (var i= 0, l=tweens.length; i<l; i++) {
|
||||
var tween = tweens[i];
|
||||
tween.paused = true;
|
||||
tween._paused = true;
|
||||
tween.target.tweenjs_count = 0;
|
||||
}
|
||||
tweens.length = 0;
|
||||
|
@ -1376,6 +1377,7 @@ var p = Tween.prototype = new createjs.EventDispatcher();
|
|||
* @return {Tween} This tween instance (for chaining calls)
|
||||
*/
|
||||
p.setPaused = function(value) {
|
||||
if (this._paused === !!value) { return this; }
|
||||
this._paused = !!value;
|
||||
Tween._register(this, !value);
|
||||
return this;
|
||||
|
@ -2755,6 +2757,6 @@ this.createjs = this.createjs || {};
|
|||
* @type String
|
||||
* @static
|
||||
**/
|
||||
s.buildDate = /*date*/"Thu, 12 Dec 2013 23:37:07 GMT"; // injected by build process
|
||||
s.buildDate = /*date*/"Wed, 02 Apr 2014 20:57:09 GMT"; // injected by build process
|
||||
|
||||
})();
|
||||
|
|
Loading…
Add table
Reference in a new issue