mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-07 13:22:07 -05:00
Add support for switching PaperScope contexts in PaperScript code exeuction and callback handling. This should add proper support for multiple PaperScript instances in one site.
This commit is contained in:
parent
3072eed91d
commit
518803f492
5 changed files with 95 additions and 61 deletions
|
@ -38,5 +38,19 @@ var PaperScope = this.PaperScope = Base.extend({
|
||||||
return Base.each(this, function(value, key) {
|
return Base.each(this, function(value, key) {
|
||||||
this[key] = value;
|
this[key] = value;
|
||||||
}, scope);
|
}, scope);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Methods for setting and restoring paper scopes:
|
||||||
|
statics: {
|
||||||
|
scopes: [],
|
||||||
|
|
||||||
|
set: function(scope) {
|
||||||
|
this.scopes.push(paper);
|
||||||
|
paper = scope;
|
||||||
|
},
|
||||||
|
|
||||||
|
restore: function() {
|
||||||
|
paper = this.scopes.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,7 +18,7 @@ var Document = this.Document = Base.extend({
|
||||||
beans: true,
|
beans: true,
|
||||||
|
|
||||||
initialize: function(canvas) {
|
initialize: function(canvas) {
|
||||||
// Store reference to currently active global paper scope:
|
// Store reference to the currently active global paper scope:
|
||||||
this._scope = paper;
|
this._scope = paper;
|
||||||
if (canvas && canvas instanceof HTMLCanvasElement) {
|
if (canvas && canvas instanceof HTMLCanvasElement) {
|
||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
|
|
|
@ -24,18 +24,22 @@ var Tool = this.Tool = ToolHandler.extend(new function() {
|
||||||
beans: true,
|
beans: true,
|
||||||
|
|
||||||
initialize: function(handlers, doc) {
|
initialize: function(handlers, doc) {
|
||||||
this.base(handlers);
|
this.base(handlers, doc._scope);
|
||||||
// Create events once, so they can be removed easily too.
|
this._document = doc;
|
||||||
var that = this, curPoint;
|
|
||||||
|
var curPoint;
|
||||||
var dragging = false;
|
var dragging = false;
|
||||||
this.events = {
|
var that = this;
|
||||||
|
// TODO: Move event handling to DocumentView
|
||||||
|
var events = {
|
||||||
mousedown: function(event) {
|
mousedown: function(event) {
|
||||||
curPoint = viewToArtwork(event, that._document);
|
curPoint = viewToArtwork(event, that._document);
|
||||||
that.onHandleEvent('mousedown', curPoint, event);
|
that.onHandleEvent('mousedown', curPoint, event);
|
||||||
if (that.onMouseDown)
|
if (that.onMouseDown) {
|
||||||
that._document.redraw();
|
that._document.redraw();
|
||||||
|
}
|
||||||
if (that.eventInterval != null) {
|
if (that.eventInterval != null) {
|
||||||
this.timer = setInterval(that.events.mousemove,
|
this.timer = setInterval(events.mousemove,
|
||||||
that.eventInterval);
|
that.eventInterval);
|
||||||
}
|
}
|
||||||
dragging = true;
|
dragging = true;
|
||||||
|
@ -45,54 +49,55 @@ var Tool = this.Tool = ToolHandler.extend(new function() {
|
||||||
// If the event was triggered by a touch screen device,
|
// If the event was triggered by a touch screen device,
|
||||||
// prevent the default behaviour, as it will otherwise
|
// prevent the default behaviour, as it will otherwise
|
||||||
// scroll the page:
|
// scroll the page:
|
||||||
if (event && event.targetTouches)
|
if (event && event.targetTouches) {
|
||||||
event.preventDefault();
|
DomEvent.preventDefault(event);
|
||||||
|
}
|
||||||
var point = event && viewToArtwork(event, that._document);
|
var point = event && viewToArtwork(event, that._document);
|
||||||
// If there is only an onMouseMove handler, call it when
|
// If there is only an onMouseMove handler, call it when
|
||||||
// the user is dragging
|
// the user is dragging
|
||||||
var onlyMove = !!(!that.onMouseDrag && that.onMouseMove);
|
var onlyMove = !!(!that.onMouseDrag && that.onMouseMove);
|
||||||
if (dragging && !onlyMove) {
|
if (dragging && !onlyMove) {
|
||||||
curPoint = point || curPoint;
|
curPoint = point || curPoint;
|
||||||
if (curPoint)
|
if (curPoint) {
|
||||||
that.onHandleEvent('mousedrag', curPoint, event);
|
that.onHandleEvent('mousedrag', curPoint, event);
|
||||||
|
}
|
||||||
} else if (!dragging || onlyMove) {
|
} else if (!dragging || onlyMove) {
|
||||||
that.onHandleEvent('mousemove', point, event);
|
that.onHandleEvent('mousemove', point, event);
|
||||||
}
|
}
|
||||||
if (that.onMouseMove || that.onMouseDrag)
|
if (that.onMouseMove || that.onMouseDrag) {
|
||||||
that._document.redraw();
|
that._document.redraw();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mouseup: function(event) {
|
mouseup: function(event) {
|
||||||
if (dragging) {
|
if (dragging) {
|
||||||
curPoint = null;
|
curPoint = null;
|
||||||
if (that.eventInterval != null)
|
if (that.eventInterval != null) {
|
||||||
clearInterval(this.timer);
|
clearInterval(this.timer);
|
||||||
|
}
|
||||||
that.onHandleEvent('mouseup',
|
that.onHandleEvent('mouseup',
|
||||||
viewToArtwork(event, that._document), event);
|
viewToArtwork(event, that._document), event);
|
||||||
if (that.onMouseUp)
|
if (that.onMouseUp) {
|
||||||
that._document.redraw();
|
that._document.redraw();
|
||||||
|
}
|
||||||
dragging = false;
|
dragging = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
touchmove: function(event) {
|
touchmove: function(event) {
|
||||||
that.events.mousemove(event);
|
events.mousemove(event);
|
||||||
},
|
},
|
||||||
|
|
||||||
touchstart: function(event) {
|
touchstart: function(event) {
|
||||||
that.events.mousedown(event);
|
events.mousedown(event);
|
||||||
},
|
},
|
||||||
|
|
||||||
touchend: function(event) {
|
touchend: function(event) {
|
||||||
that.events.mouseup(event);
|
events.mouseup(event);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove old events first.
|
DomEvent.add(doc.canvas, events);
|
||||||
if (this._document)
|
|
||||||
DomEvent.remove(this._document.canvas, this.events);
|
|
||||||
this._document = doc;
|
|
||||||
DomEvent.add(doc.canvas, this.events);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getDocument: function() {
|
getDocument: function() {
|
||||||
|
|
|
@ -21,6 +21,7 @@ var ToolHandler = this.ToolHandler = Base.extend({
|
||||||
* Initializes the tool's settings, so a new tool can be assigned to it
|
* Initializes the tool's settings, so a new tool can be assigned to it
|
||||||
*/
|
*/
|
||||||
initialize: function(handlers, scope) {
|
initialize: function(handlers, scope) {
|
||||||
|
this._scope = scope;
|
||||||
this._firstMove = true;
|
this._firstMove = true;
|
||||||
this._count = 0;
|
this._count = 0;
|
||||||
this._downCount = 0;
|
this._downCount = 0;
|
||||||
|
@ -120,6 +121,7 @@ var ToolHandler = this.ToolHandler = Base.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
onHandleEvent: function(type, pt, event) {
|
onHandleEvent: function(type, pt, event) {
|
||||||
|
PaperScope.set(this._scope);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'mousedown':
|
case 'mousedown':
|
||||||
this.updateEvent(type, pt, null, null, true, false, false);
|
this.updateEvent(type, pt, null, null, true, false, false);
|
||||||
|
@ -176,5 +178,6 @@ var ToolHandler = this.ToolHandler = Base.extend({
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
PaperScope.restore();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -129,14 +129,19 @@ var PaperScript = this.PaperScript = new function() {
|
||||||
return parse_js.stringify(ast, true);
|
return parse_js.stringify(ast, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function run(code) {
|
function run(code, scope) {
|
||||||
with (paper) {
|
try { with (scope) { // Safe one indentation by grouping try and with
|
||||||
var doc = paper.document,
|
PaperScope.set(scope);
|
||||||
tool = paper.tool = /on(?:Key|Mouse)(?:Up|Down|Move|Drag)/.test(code)
|
var doc = scope.document;
|
||||||
&& new Tool(null, doc),
|
// TODO: Add support for multiple tools
|
||||||
onEditOptions, onSelect, onDeselect, onReselect, onMouseDown,
|
var tool = scope.tool =
|
||||||
onMouseUp, onMouseDrag, onMouseMove, onKeyDown, onKeyUp,
|
/on(?:Key|Mouse)(?:Up|Down|Move|Drag)/.test(code)
|
||||||
res = eval(compile(code));
|
&& new Tool(null, doc);
|
||||||
|
// Define variables for potential handlers, so eval() calls below to
|
||||||
|
// fetch their values do not require try-catch around them.
|
||||||
|
var onEditOptions, onSelect, onDeselect, onReselect, onMouseDown,
|
||||||
|
onMouseUp, onMouseDrag, onMouseMove, onKeyDown, onKeyUp, onFrame;
|
||||||
|
var res = eval(compile(code));
|
||||||
if (tool) {
|
if (tool) {
|
||||||
Base.each(['onEditOptions', 'onSelect', 'onDeselect',
|
Base.each(['onEditOptions', 'onSelect', 'onDeselect',
|
||||||
'onReselect', 'onMouseDown', 'onMouseUp', 'onMouseDrag',
|
'onReselect', 'onMouseDown', 'onMouseUp', 'onMouseDrag',
|
||||||
|
@ -146,44 +151,44 @@ var PaperScript = this.PaperScript = new function() {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
try {
|
// TODO: Move onFrame support to DocumentView
|
||||||
var onFrame = eval('onFrame');
|
var onFrame = eval('onFrame');
|
||||||
if (onFrame) {
|
if (onFrame) {
|
||||||
var lastTime;
|
var lastTime;
|
||||||
var totalTime = 0;
|
var totalTime = 0;
|
||||||
function frame() {
|
function frame() {
|
||||||
// Request next frame already
|
// Request next frame already
|
||||||
DomEvent.requestAnimationFrame(frame, doc && doc.canvas);
|
DomEvent.requestAnimationFrame(frame, doc && doc.canvas);
|
||||||
var time = Date.now() / 1000;
|
var time = Date.now() / 1000;
|
||||||
// Time elapsed since last redraw in seconds:
|
// Time elapsed since last redraw in seconds:
|
||||||
var delta = lastTime ? time - lastTime : 0;
|
var delta = lastTime ? time - lastTime : 0;
|
||||||
// Time since first call of frame() in seconds:
|
// Time since first call of frame() in seconds:
|
||||||
totalTime += delta;
|
totalTime += delta;
|
||||||
onFrame({
|
onFrame({
|
||||||
delta: delta,
|
delta: delta,
|
||||||
time: totalTime
|
time: totalTime
|
||||||
});
|
});
|
||||||
// Automatically redraw document each frame.
|
// Automatically redraw document each frame.
|
||||||
if (doc)
|
|
||||||
doc.redraw();
|
|
||||||
lastTime = time;
|
|
||||||
};
|
|
||||||
// Call the onFrame handler and redraw the document:
|
|
||||||
frame();
|
|
||||||
} else {
|
|
||||||
// Automatically redraw document at the end.
|
|
||||||
if (doc)
|
if (doc)
|
||||||
doc.redraw();
|
doc.redraw();
|
||||||
}
|
lastTime = time;
|
||||||
} catch (e) {
|
};
|
||||||
|
// Call the onFrame handler and redraw the document:
|
||||||
|
frame();
|
||||||
|
} else {
|
||||||
|
// Automatically redraw document at the end.
|
||||||
|
if (doc)
|
||||||
|
doc.redraw();
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
} } finally {
|
||||||
|
PaperScope.restore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#ifdef BROWSER
|
//#ifdef BROWSER
|
||||||
// Code borrowed from Coffee Script:
|
// Code borrowed from Coffee Script:
|
||||||
function request(url) {
|
function request(url, scope) {
|
||||||
var xhr = new (window.ActiveXObject || XMLHttpRequest)(
|
var xhr = new (window.ActiveXObject || XMLHttpRequest)(
|
||||||
'Microsoft.XMLHTTP');
|
'Microsoft.XMLHTTP');
|
||||||
xhr.open('GET', url, true);
|
xhr.open('GET', url, true);
|
||||||
|
@ -192,7 +197,7 @@ var PaperScript = this.PaperScript = new function() {
|
||||||
}
|
}
|
||||||
xhr.onreadystatechange = function() {
|
xhr.onreadystatechange = function() {
|
||||||
if (xhr.readyState === 4) {
|
if (xhr.readyState === 4) {
|
||||||
return run(xhr.responseText);
|
return run(xhr.responseText, scope);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return xhr.send(null);
|
return xhr.send(null);
|
||||||
|
@ -205,16 +210,23 @@ var PaperScript = this.PaperScript = new function() {
|
||||||
// Only load this cript if it not loaded already.
|
// Only load this cript if it not loaded already.
|
||||||
if (script.type === 'text/paperscript'
|
if (script.type === 'text/paperscript'
|
||||||
&& !script.getAttribute('loaded')) {
|
&& !script.getAttribute('loaded')) {
|
||||||
|
// Produce a new PaperScope for this script now. Scopes are
|
||||||
|
// cheap so let's not worry about the initial one that was
|
||||||
|
// already created.
|
||||||
|
var scope = new PaperScope();
|
||||||
// If a canvas id is provided, create a document for it now,
|
// If a canvas id is provided, create a document for it now,
|
||||||
// so the active document is defined.
|
// so the active document is defined.
|
||||||
var canvas = script.getAttribute('canvas');
|
var canvas = script.getAttribute('canvas');
|
||||||
if (canvas = canvas && document.getElementById(canvas)) {
|
if (canvas = canvas && document.getElementById(canvas)) {
|
||||||
|
// Create a Document for this canvas, using the right scope
|
||||||
|
PaperScope.set(scope);
|
||||||
new Document(canvas);
|
new Document(canvas);
|
||||||
|
PaperScope.restore();
|
||||||
}
|
}
|
||||||
if (script.src) {
|
if (script.src) {
|
||||||
request(script.src);
|
request(script.src, scope);
|
||||||
} else {
|
} else {
|
||||||
run(script.innerHTML);
|
run(script.innerHTML, scope);
|
||||||
}
|
}
|
||||||
// Mark script as loaded now.
|
// Mark script as loaded now.
|
||||||
script.setAttribute('loaded', true);
|
script.setAttribute('loaded', true);
|
||||||
|
|
Loading…
Reference in a new issue