summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gui.js9
-rw-r--r--objects.js130
-rwxr-xr-xsnap.html42
-rw-r--r--threads.js40
4 files changed, 137 insertions, 84 deletions
diff --git a/gui.js b/gui.js
index 7fb48ac..875a3d2 100644
--- a/gui.js
+++ b/gui.js
@@ -211,6 +211,10 @@ IDE_Morph.prototype.init = function (isAutoFill) {
this.serializer = new SnapSerializer();
this.globalVariables = new VariableFrame();
+
+ // recreate all Sprite markers (Snap-YOW)
+ window.spriteGroup = L.layerGroup().addTo(window.map);
+
this.currentSprite = new SpriteMorph(this.globalVariables);
this.sprites = new List([this.currentSprite]);
this.currentCategory = 'map';
@@ -2797,6 +2801,11 @@ IDE_Morph.prototype.newProject = function () {
location.hash = '';
}
this.globalVariables = new VariableFrame();
+
+ // recreate all Sprite markers (Snap-YOW)
+ window.map.removeLayer(window.spriteGroup);
+ window.spriteGroup = L.layerGroup().addTo(window.map);
+
this.currentSprite = new SpriteMorph(this.globalVariables);
this.sprites = new List([this.currentSprite]);
StageMorph.prototype.dimensions = new Point(480, 360);
diff --git a/objects.js b/objects.js
index 433ce4b..41ffe3c 100644
--- a/objects.js
+++ b/objects.js
@@ -203,10 +203,15 @@ SpriteMorph.prototype.initBlocks = function () {
SpriteMorph.prototype.blocks = {
// Map (Snap! in Your Own World)
- reportLocation: {
+ reportUserLocation: {
type: 'reporter',
category: 'map',
- spec: 'current location'
+ spec: 'current user location'
+ },
+ reportMyLocation: {
+ type: 'reporter',
+ category: 'map',
+ spec: 'my location'
},
focusMap: {
type: 'command',
@@ -218,37 +223,49 @@ SpriteMorph.prototype.initBlocks = function () {
dev: true,
type: 'command',
category: 'map',
- spec: 'add a marker to %l'
+ spec: 'debug: add a marker to %l'
},
-
- // Motion
- forward: {
+ moveTo: {
only: SpriteMorph,
type: 'command',
- category: 'motion',
- spec: 'move %n steps',
- defaults: [10]
+ category: 'map',
+ spec: 'move to %l'
},
turn: {
only: SpriteMorph,
type: 'command',
- category: 'motion',
+ category: 'map',
spec: 'turn %clockwise %n degrees',
defaults: [15]
},
turnLeft: {
only: SpriteMorph,
type: 'command',
- category: 'motion',
+ category: 'map',
spec: 'turn %counterclockwise %n degrees',
defaults: [15]
},
setHeading: {
only: SpriteMorph,
type: 'command',
- category: 'motion',
+ category: 'map',
spec: 'point in direction %dir'
},
+ direction: {
+ only: SpriteMorph,
+ type: 'reporter',
+ category: 'map',
+ spec: 'direction'
+ },
+
+ // Motion
+ forward: {
+ only: SpriteMorph,
+ type: 'command',
+ category: 'motion',
+ spec: 'move %n steps',
+ defaults: [10]
+ },
doFaceTowards: {
only: SpriteMorph,
type: 'command',
@@ -321,12 +338,6 @@ SpriteMorph.prototype.initBlocks = function () {
category: 'motion',
spec: 'y position'
},
- direction: {
- only: SpriteMorph,
- type: 'reporter',
- category: 'motion',
- spec: 'direction'
- },
// Looks
doSwitchToCostume: {
@@ -1319,8 +1330,8 @@ SpriteMorph.prototype.init = function (globals) {
this.variables = new VariableFrame(globals || null, this);
this.scripts = new ScriptsMorph(this);
this.customBlocks = [];
- this.costumes = new List();
- this.costume = null;
+ this.costume = new Costume(window.defaultCostume, "marker");
+ this.costumes = new List([this.costume]);
this.sounds = new List();
this.normalExtent = new Point(60, 60); // only for costume-less situation
this.scale = 1;
@@ -1360,14 +1371,12 @@ SpriteMorph.prototype.init = function (globals) {
this.isDown = false;
// Snap! - YOW code
- this.icon = L.icon({
- iconUrl: 'images/marker-icon.png',
- iconRetinaUrl: 'images/marker-icon-2x.png',
- shadowUrl: 'images/marker-shadow.png'
- });
this.geoposition = window.map.getCenter();
- this.marker = L.marker(this.geoposition, {icon: this.icon, title: this.name});
- this.marker.addTo(window.map);
+
+ // TODO this is a bit hacky
+ this.marker = L.spriteMarker(this.geoposition);
+ this.marker.addTo(window.spriteGroup);
+ this.updateMarker();
this.heading = 90;
this.changed();
@@ -1375,6 +1384,33 @@ SpriteMorph.prototype.init = function (globals) {
this.changed();
};
+SpriteMorph.prototype.updateMarker = function () {
+ // sadly, the name can not be changed on the fly, so the element has to be recreated
+ // TODO: XSS? Extend L.Icon?
+ if (!this.marker) return;
+ window.spriteGroup.removeLayer(this.marker);
+ this.icon = L.divIcon({
+ className: 'snap-sprite',
+ html: '<div id="icon-' + this.name + '"></div>',
+ iconSize: [this.costume.contents.width, this.costume.contents.height],
+ iconAnchor: [this.rotationOffset.x, this.rotationOffset.y]
+ });
+ this.marker = L.spriteMarker(this.geoposition, {icon: this.icon, title: this.name});
+ this.marker.setAngle(this.heading - 90);
+ this.marker.addTo(window.spriteGroup);
+ document.getElementById('icon-' + this.name).appendChild(this.costume.contents);
+};
+
+/*
+ * // for later
+ this.icon = new L.Icon.Canvas({
+ iconSize: [this.costume.contents.width, this.costume.contents.height]});
+ var myself = this;
+ this.icon.draw = function(ctx, w, h) {ctx.drawImage(myself.costume.contents, 0, 0);};
+ this.marker = L.marker(this.geoposition, {icon: this.icon, title: this.name});
+ this.marker.addTo(window.spriteGroup);
+*/
+
// SpriteMorph duplicating (fullCopy)
SpriteMorph.prototype.fullCopy = function () {
@@ -1554,6 +1590,7 @@ SpriteMorph.prototype.drawNew = function () {
}
}
this.version = Date.now();
+ this.updateMarker(); // Snap! YOW
};
SpriteMorph.prototype.endWarp = function () {
@@ -1732,21 +1769,24 @@ SpriteMorph.prototype.blockTemplates = function (category) {
}
if (cat === 'map') {
-
- blocks.push(block('reportLocation'));
+ blocks.push(block('reportUserLocation'));
blocks.push(block('focusMap'));
+ blocks.push(block('moveTo'));
//if (this.world().isDevMode) {
blocks.push(block('addMarker'));
//}
+ blocks.push('-');
+ blocks.push(block('turn'));
+ blocks.push(block('turnLeft'));
+ blocks.push(block('setHeading'));
+ blocks.push(watcherToggle('direction'));
+ blocks.push(block('direction'));
} /* else if (cat === 'motion') {
blocks.push(block('forward'));
- blocks.push(block('turn'));
- blocks.push(block('turnLeft'));
blocks.push('-');
- blocks.push(block('setHeading'));
blocks.push(block('doFaceTowards'));
blocks.push('-');
blocks.push(block('gotoXY'));
@@ -1764,8 +1804,6 @@ SpriteMorph.prototype.blockTemplates = function (category) {
blocks.push(block('xPosition'));
blocks.push(watcherToggle('yPosition'));
blocks.push(block('yPosition'));
- blocks.push(watcherToggle('direction'));
- blocks.push(block('direction'));
} */ else if (cat === 'looks') {
@@ -1950,7 +1988,7 @@ SpriteMorph.prototype.blockTemplates = function (category) {
blocks.push(block('doSetFastTracking'));
blocks.push('-');
blocks.push(block('reportDate'));
- blocks.push(block('reportLocation'));
+ blocks.push(block('reportUserLocation'));
// for debugging: ///////////////
@@ -2615,7 +2653,7 @@ SpriteMorph.prototype.doSwitchToCostume = function (id) {
(id instanceof Array ? id[0] : null)
)
) {
- costume = null;
+ this.costume = new Costume(window.defaultCostume, "marker");
} else {
if (id === -1) {
this.doWearPreviousCostume();
@@ -2627,7 +2665,7 @@ SpriteMorph.prototype.doSwitchToCostume = function (id) {
if (costume === null) {
num = parseFloat(id);
if (num === 0) {
- costume = null;
+ this.costume = new Costume(window.defaultCostume, "marker");
} else {
costume = arr[num - 1] || null;
}
@@ -3310,6 +3348,13 @@ SpriteMorph.prototype.nestingBounds = function () {
return result;
};
+// SpriteMorph YOW map primitives
+
+SpriteMorph.prototype.moveTo = function (pos) {
+ this.geoposition = pos.contents;
+ this.updateMarker();
+};
+
// SpriteMorph motion primitives
Morph.prototype.setPosition = function (aPoint, justMe) {
@@ -4451,13 +4496,10 @@ StageMorph.prototype.drawNew = function () {
StageMorph.prototype.drawOn = function (aCanvas, aRect) {
var map = document.getElementById('map');
- var rectangle, area;
- rectangle = aRect || this.bounds;
- area = rectangle.intersect(this.bounds).round();
map.style.width = this.dimensions.x * this.scale + 'px';
map.style.height = this.dimensions.y * this.scale + 'px';
- map.style.left = area.left() + 'px';
- map.style.top = area.top() + 'px';
+ map.style.left = this.left() + 'px';
+ map.style.top = this.top() + 'px';
window.map.invalidateSize();
};
@@ -4922,7 +4964,7 @@ StageMorph.prototype.blockTemplates = function (category) {
if (cat === 'map') {
- blocks.push(block('reportLocation'));
+ blocks.push(block('reportUserLocation'));
blocks.push(block('focusMap'));
if (this.world().isDevMode) {
blocks.push(block('addMarker'));
@@ -5084,7 +5126,7 @@ StageMorph.prototype.blockTemplates = function (category) {
blocks.push(block('doSetFastTracking'));
blocks.push('-');
blocks.push(block('reportDate'));
- blocks.push(block('reportLocation'));
+ blocks.push(block('reportUserLocation'));
// for debugging: ///////////////
diff --git a/snap.html b/snap.html
index f2c323f..8a2f6de 100755
--- a/snap.html
+++ b/snap.html
@@ -27,7 +27,25 @@
<div id="map" style="position: absolute; width: 480px; height: 360px;" />
<!-- set initial size to 480x360 or the map will not load properly -->
<script type="text/javascript">
- var world, map, layer;
+ L.SpriteMarker = L.Marker.extend({
+ options: {
+ angle: 0
+ },
+ _setPos: function (pos) {
+ L.Marker.prototype._setPos.call(this, pos);
+ this._icon.style[L.DomUtil.TRANSFORM] += ' rotate(' + this.options.angle + 'deg)';
+ // TODO: set rotation center with transform-origin
+ },
+ setAngle: function (angle) {
+ this.options.angle = angle;
+ this.update();
+ }
+ });
+ L.spriteMarker = function(pos, options) {
+ return new L.SpriteMarker(pos, options);
+ };
+
+ var world, map, layer, spriteGroup, defaultCostume;
function loop() {
world.doOneCycle();
@@ -38,22 +56,42 @@
}
function startYOW (e) {
+ setGlobalPosition(e);
+ map.stopLocate();
map.on('locationfound', setGlobalPosition);
map.locate({watch: true, enableHighAccuracy: true});
new OSMBuildings(map).load();
+ window.spriteGroup = spriteGroup;
+ spriteGroup = L.layerGroup().addTo(map);
+
world = new WorldMorph(document.getElementById('world'));
world.worldCanvas.focus();
new IDE_Morph().openIn(world);
setInterval(loop, 10);
}
+ // TODO: this needs to be improved
+ function loadDefaultCostume (e) {
+ image = new Image();
+ image.src = 'images/marker-icon.png';
+ image.onload = function () {
+ defaultCostume = document.createElement('canvas');
+ defaultCostume.width = image.width;
+ defaultCostume.height = image.height;
+ var context = defaultCostume.getContext('2d');
+ context.drawImage(image, 0, 0);
+ window.defaultCostume = defaultCostume;
+ startYOW(e);
+ }
+ }
+
window.map = map;
window.layer = layer;
map = L.map('map');
- map.on('locationfound', startYOW);
+ map.on('locationfound', loadDefaultCostume);
map.locate({setView: true});
layer = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
diff --git a/threads.js b/threads.js
index 52e1c11..fab05a0 100644
--- a/threads.js
+++ b/threads.js
@@ -2626,51 +2626,15 @@ Process.prototype.reportTimer = function () {
return 0;
};
-Process.prototype.reportLocation = function (name) {
- var myself = this;
-
- if (!myself.context.position) {
- myself.context.position = [];
-
- if (!navigator.geolocation) {
- myself.handleError({name: 'Location',
- message: 'navigator.geolocation is not supported'});
- }
-
- navigator.geolocation.getCurrentPosition(
- function (pos) {
- myself.context.position = [
- pos.coords.latitude, pos.coords.longitude];
- },
- function (err) {
- console.log(err);
- myself.handleError({name: 'Location', message: err.message});
- },
- { enableHightAccuracy: true, timeout: 5000, maximumAge: 0}
- );
- } else {
- if (myself.context.position.length == 2) {
- return new List(myself.context.position);
- }
- }
-
- this.pushContext('doYield');
- this.pushContext();
+Process.prototype.reportUserLocation = function () {
+ return new List([window.geoposition.lat, window.geoposition.lng]);
};
Process.prototype.focusMap = function (pos, zoom) {
- if (pos.contents.length != 2) {
- this.handleError({name: 'Location',
- message: 'expecting a list of latitude/longitude'});
- }
window.map.setView(pos.contents, zoom);
};
Process.prototype.addMarker = function (pos) {
- if (pos.contents.length != 2) {
- this.handleError({name: 'Location',
- message: 'expecting a list of latitude/longitude'});
- }
L.marker(pos.contents).addTo(window.map);
};