diff options
Diffstat (limited to 'objects.js')
| -rw-r--r-- | objects.js | 217 |
1 files changed, 200 insertions, 17 deletions
@@ -125,7 +125,7 @@ PrototypeHatBlockMorph*/ // Global stuff //////////////////////////////////////////////////////// -modules.objects = '2015-January-21'; +modules.objects = '2015-February-28'; var SpriteMorph; var StageMorph; @@ -613,11 +613,22 @@ SpriteMorph.prototype.initBlocks = function () { category: 'control', spec: 'when %keyHat key pressed' }, + + /* migrated to a newer block version: + receiveClick: { type: 'hat', category: 'control', spec: 'when I am clicked' }, + */ + + receiveInteraction: { + type: 'hat', + category: 'control', + spec: 'when I am %interaction', + defaults: ['clicked'] + }, receiveMessage: { type: 'hat', category: 'control', @@ -1254,6 +1265,29 @@ SpriteMorph.prototype.initBlocks = function () { defaults: [localize('each item')] }, + // peer to peer communication + receivePeerMessage: { + type: 'hat', + category: 'other', + spec: 'when I receive %upvar from %upvar', + defaults: [localize('message'), localize('peer')] + }, + sendPeerMessage: { + type: 'command', + category: 'other', + spec: 'send %s to %s' + }, + reportPeerId: { + type: 'reporter', + category: 'other', + spec: 'my peer id' + }, + reportPeerList: { + type: 'reporter', + category: 'other', + spec: 'peers online' + }, + // Code mapping - experimental doMapCodeOrHeader: { // experimental type: 'command', @@ -1294,6 +1328,10 @@ SpriteMorph.prototype.initBlockMigrations = function () { doStopBlock: { selector: 'doStopThis', inputs: [['this block']] + }, + receiveClick: { + selector: 'receiveInteraction', + inputs: [['clicked']] } }; }; @@ -1342,8 +1380,6 @@ SpriteMorph.prototype.blockAlternatives = { setSize: ['changeSize'], // control: - receiveGo: ['receiveClick'], - receiveClick: ['receiveGo'], doBroadcast: ['doBroadcastAndWait'], doBroadcastAndWait: ['doBroadcast'], doIf: ['doIfElse', 'doUntil'], @@ -1514,15 +1550,13 @@ SpriteMorph.prototype.setName = function (string) { SpriteMorph.prototype.drawNew = function () { var myself = this, - currentCenter = this.center(), + currentCenter, facing, // actual costume heading based on my rotation style isFlipped, - isLoadingCostume = this.costume && - typeof this.costume.loaded === 'function', + isLoadingCostume, cst, pic, // (flipped copy of) actual costume based on my rotation style - stageScale = this.parent instanceof StageMorph ? - this.parent.scale : 1, + stageScale, newX, corners = [], origin, @@ -1536,6 +1570,11 @@ SpriteMorph.prototype.drawNew = function () { this.wantsRedraw = true; return; } + currentCenter = this.center(); + isLoadingCostume = this.costume && + typeof this.costume.loaded === 'function'; + stageScale = this.parent instanceof StageMorph ? + this.parent.scale : 1; facing = this.rotationStyle ? this.heading : 90; if (this.rotationStyle === 2) { facing = 90; @@ -1683,7 +1722,7 @@ SpriteMorph.prototype.blockForSelector = function (selector, setDefaults) { : new ReporterBlockMorph(info.type === 'predicate'); block.color = this.blockColor[info.category]; block.category = info.category; - block.selector = selector; + block.selector = migration ? migration.selector : selector; if (contains(['reifyReporter', 'reifyPredicate'], block.selector)) { block.isStatic = true; } @@ -1930,7 +1969,7 @@ SpriteMorph.prototype.blockTemplates = function (category) { blocks.push(block('receiveGo')); blocks.push(block('receiveKey')); - blocks.push(block('receiveClick')); + blocks.push(block('receiveInteraction')); blocks.push(block('receiveMessage')); blocks.push('-'); blocks.push(block('doBroadcast')); @@ -2204,6 +2243,13 @@ SpriteMorph.prototype.blockTemplates = function (category) { blocks.push('='); + blocks.push(block('receivePeerMessage')); + blocks.push(block('sendPeerMessage')); + blocks.push(block('reportPeerId')); + blocks.push(block('reportPeerList')); + + blocks.push('='); + if (StageMorph.prototype.enableCodeMapping) { blocks.push(block('doMapCodeOrHeader')); blocks.push(block('doMapStringCode')); @@ -2915,7 +2961,7 @@ SpriteMorph.prototype.setColor = function (aColor) { var x = this.xPosition(), y = this.yPosition(); if (!this.color.eq(aColor)) { - this.color = aColor; + this.color = aColor.copy(); this.drawNew(); this.gotoXY(x, y); } @@ -3326,6 +3372,7 @@ SpriteMorph.prototype.prepareToBeGrabbed = function (hand) { SpriteMorph.prototype.justDropped = function () { this.restoreLayers(); this.positionTalkBubble(); + this.receiveUserInteraction('dropped'); }; // SpriteMorph drawing: @@ -3655,8 +3702,8 @@ SpriteMorph.prototype.allHatBlocksFor = function (message) { if (morph.selector === 'receiveOnClone') { return message === '__clone__init__'; } - if (morph.selector === 'receiveClick') { - return message === '__click__'; + if (morph.selector === 'receivePeerMessage') { + return message === '__peer__message__'; } } return false; @@ -3686,13 +3733,37 @@ SpriteMorph.prototype.allHatBlocksForKey = function (key) { }); }; +SpriteMorph.prototype.allHatBlocksForInteraction = function (interaction) { + return this.scripts.children.filter(function (morph) { + if (morph.selector) { + if (morph.selector === 'receiveInteraction') { + return morph.inputs()[0].evaluate()[0] === interaction; + } + } + return false; + }); +}; + // SpriteMorph events SpriteMorph.prototype.mouseClickLeft = function () { - var stage = this.parentThatIsA(StageMorph), - hats = this.allHatBlocksFor('__click__'), - procs = []; + return this.receiveUserInteraction('clicked'); +}; + +SpriteMorph.prototype.mouseEnter = function () { + return this.receiveUserInteraction('mouse-entered'); +}; + +SpriteMorph.prototype.mouseDownLeft = function () { + return this.receiveUserInteraction('pressed'); +}; +SpriteMorph.prototype.receiveUserInteraction = function (interaction) { + var stage = this.parentThatIsA(StageMorph), + procs = [], + hats; + if (!stage) {return; } // currently dragged + hats = this.allHatBlocksForInteraction(interaction); hats.forEach(function (block) { procs.push(stage.threads.startProcess(block, stage.isThreadSafe)); }); @@ -4367,6 +4438,7 @@ SpriteMorph.prototype.mouseEnterDragging = function () { }; SpriteMorph.prototype.mouseLeave = function () { + this.receiveUserInteraction('mouse-departed'); if (!this.enableNesting) {return; } this.removeHighlight(); }; @@ -4531,6 +4603,95 @@ StageMorph.prototype.init = function (globals) { this.acceptsDrops = false; this.setColor(new Color(255, 255, 255)); this.fps = this.frameRate; + + this.initPeering(); +}; + +StageMorph.prototype.initPeering = function (id) { + var myself = this; + + if (window.peers) { + // I don't know why, but it works. + window.peers.forEach(function (oldpeer) { + if (id != oldpeer.id) { + oldpeer.destroy() + } + }); + } + + this.peer = new Peer(id, { + host: 'snapmesh.herokuapp.com', + port: 443, + secure: true, + path: '/' + }); + + this.peer.on('open', function (id) { + myself.peerId = id; + }); + this.peer.on('disconnected', function () { + // peer.reconnect does not work (?) because 'id' is undefined + if (!myself.peer.destroyed) { + myself.initPeering(myself.peerId); + } + }); + this.peer.on('error', function (err) { + console.log(err); // DEBUG + }); + + this.peer.on('connection', function (connection) { + connection.on('open', function () { + connection.on('data', function (data) { + myself.newPeerMessage(data, connection.peer); + }); + }); + }); + + window.peers.push(this.peer); +}; + +StageMorph.prototype.newPeerMessage = function (data, peer) { + var ide = this.parentThatIsA(IDE_Morph); + var myself = this; + var hats = [], model, message; + + try { + model = ide.serializer.parse(data); + message = ide.serializer.loadValue(model); + + // TODO: If a Context is sent, a new Sprite appears. + // This below is just a workaround for one-level rings, + // objects should be cleaned recursively. + message.receiver = null; + message.outerContext = null; + } catch (err) { + console.log(err); // DEBUG + // Ok, it does not seem to be XML. It must be a string then. + message = data; + } + + // call hat blocks + this.children.concat(myself).forEach(function (morph) { + if (morph instanceof SpriteMorph + || morph instanceof StageMorph) { + hats = hats.concat( + morph.allHatBlocksFor('__peer__message__')); + } + }); + hats.forEach(function (block) { + var process = myself.threads.startProcess(block, + myself.isThreadSafe); + process.context.outerContext.variables.addVar(localize('message')); + process.context.outerContext.variables.setVar( + localize('message'), + message + ); + process.context.outerContext.variables.addVar(localize('peer')); + process.context.outerContext.variables.setVar( + localize('peer'), + peer + ); + }); }; // StageMorph scaling @@ -5224,7 +5385,7 @@ StageMorph.prototype.blockTemplates = function (category) { blocks.push(block('receiveGo')); blocks.push(block('receiveKey')); - blocks.push(block('receiveClick')); + blocks.push(block('receiveInteraction')); blocks.push(block('receiveMessage')); blocks.push('-'); blocks.push(block('doBroadcast')); @@ -5484,6 +5645,12 @@ StageMorph.prototype.blockTemplates = function (category) { blocks.push('='); + blocks.push(block('receivePeerMessage')); + blocks.push(block('sendPeerMessage')); + blocks.push(block('reportPeerId')); + blocks.push(block('reportPeerList')); + blocks.push('='); + if (StageMorph.prototype.enableCodeMapping) { blocks.push(block('doMapCodeOrHeader')); blocks.push(block('doMapStringCode')); @@ -5819,11 +5986,27 @@ StageMorph.prototype.allHatBlocksFor StageMorph.prototype.allHatBlocksForKey = SpriteMorph.prototype.allHatBlocksForKey; +StageMorph.prototype.allHatBlocksForInteraction + = SpriteMorph.prototype.allHatBlocksForInteraction; + // StageMorph events StageMorph.prototype.mouseClickLeft = SpriteMorph.prototype.mouseClickLeft; +StageMorph.prototype.mouseEnter + = SpriteMorph.prototype.mouseEnter; + +StageMorph.prototype.mouseLeave = function () { + this.receiveUserInteraction('mouse-departed'); +}; + +StageMorph.prototype.mouseDownLeft + = SpriteMorph.prototype.mouseDownLeft; + +StageMorph.prototype.receiveUserInteraction + = SpriteMorph.prototype.receiveUserInteraction; + // StageMorph custom blocks StageMorph.prototype.deleteAllBlockInstances |
