OSDN Git Service

Merge branch 'vgd' of into Split_renderers
[automap/automap.git] / Automap / MapSRC / src / ViewFrame.js
diff --git a/Automap/MapSRC/src/ViewFrame.js b/Automap/MapSRC/src/ViewFrame.js
new file mode 100644 (file)
index 0000000..663a50f
--- /dev/null
@@ -0,0 +1,140 @@
+function ViewFrame() {
+       // dom stuff
+       const map = document.createElement('canvas'); // the map we see
+       map.className = 'map';
+       map.height = window.innerHeight;
+       map.width = window.innerWidth;
+       document.getElementsByTagName('body')[0].append(map);
+       // this is the map that we actually draw on
+       this.map = map.getContext('2d', {
+               alpha: false
+       });
+       this.map.imageSmoothingEnabled = false;
+
+       // the info box in the corner
+       this.infobox = document.getElementsByClassName('infoboxTable')[0];
+       this.infoboxSlots = new Array();
+
+       // load the metadata!
+       this.chunkScript = document.createElement('script');
+       this.chunkScript.type = 'text/javascript';
+       this.chunkScript.src = 'Metadata.js';
+       document.getElementsByTagName('body')[0].append(this.chunkScript);
+       this.chunkScript.addEventListener('load', () => {
+               ViewFrame.initInfobox(this.infobox, this.infoboxSlots);
+               this.x = ViewFrame.chunks.startCoords[0];
+               this.y = ViewFrame.chunks.startCoords[1];
+               this.availableChunks = ViewFrame.chunks.chunkMetadata;
+               this.render();
+       }, {
+               once: true
+       });
+
+       // Tracks images that have been loaded and are on the map
+       this.loadedChunksByName = new Map();
+       // this is needed because [1, 2] != [1, 2] and thats how we store coords.
+       this.loadedChunksByCoords = new Map();
+       this.availableChunks = null; // the chunks in ./Metadata.js
+       // so that we dont render twice at the same time
+       this.rendering = false;
+
+       this.x = -1;
+       this.y = -1; // can be fractional
+       this.zoom = 32; // pixels wide the images are to be
+       this.updateEdges();
+}
+// prototypes, some less... notable? methods are
+// in ViewFrameUtils.js 
+ViewFrame.prototype.reloadChunkList = function () {
+       if (this.chunkScript) {
+               this.chunkScript.remove();
+               delete this.chunkScript;
+       }
+
+       this.chunkScript = document.createElement('script');
+       this.chunkScript.type = 'text/javascript';
+       this.chunkScript.src = 'Metadata.js';
+       document.getElementsByTagName('body')[0].append(this.chunkScript);
+
+       this.chunkScript.addEventListener('load', () => {
+               this.availableChunks = ViewFrame.chunks.chunkMetadata;
+               this.render();
+       });
+};
+
+ViewFrame.prototype.render = function () {
+       if (!this.availableChunks) return;
+       if (this.rendering) clearInterval(ViewFrame.intervalRef);
+       this.rendering = true;
+       this.updateEdges();
+       this.map.clearRect(0, 0, window.innerWidth, window.innerHeight);
+       // culling
+       this.loadedChunksByCoords
+               .forEach((chunk, coord) => { // check the bounds
+                       if (coord[0] < this.eastChunk &&
+                               coord[0] >= this.westChunk &&
+                               coord[1] <= this.northChunk &&
+                               coord[1] >= this.southChunk) {
+
+                               this.place(chunk, coord[0], coord[1]);
+                               return;
+                       }
+                       // its out of range!!!
+                       // get 'em boys!!!!!
+                       this.loadedChunksByCoords.delete(coord);
+                       this.loadedChunksByName.delete(coord.join('_'));
+                       chunk.remove();
+               });
+
+       // gathering what we need to load
+       const neededChunks = new Set();
+       for (var x = this.westChunk; x < this.eastChunk; x++) {
+               for (var y = this.southChunk; y < this.northChunk; y++) {
+                       const chunKey = [x, y]; // chunk + key = chunKey :)
+                       const name = chunKey.join('_');
+                       // continue if its not available, or it is loaded
+                       if (!this.availableChunks.has(name) ||
+                               this.loadedChunksByName.has(name)) continue;
+                       neededChunks.add(chunKey);
+               }
+       }
+       // iterating over everything we need to load
+       const it = neededChunks.values();
+       ViewFrame.intervalRef = setInterval(() => {
+               let round = it.next();
+               if (!round.done) {
+                       // load
+                       const img = new Image(32, 32);
+                       const name = round.value.join('_');
+
+                       img.src = name + '.png';
+
+                       decode(img, loadedImage => {
+                               this.place(img, round.value[0], round.value[1]);
+                       });
+                       this.loadedChunksByName.set(name, img);
+                       this.loadedChunksByCoords.set(round.value, img);
+               } else {
+                       clearInterval(ViewFrame.intervalRef);
+                       this.rendering = false;
+               }
+       }, 4);
+};
+
+ViewFrame.prototype.place = function (img, x, y) {
+       x -= this.x;
+       y -= this.y;
+       x *= this.zoom;
+       y *= this.zoom;
+       x += this.width / 2;
+       y += this.height / 2;
+
+       this.map.drawImage(img, Math.floor(x), Math.floor(y), this.zoom, this.zoom);
+};
+
+ViewFrame.prototype.updateInfobox = function (chunkName) {
+       const chunkMeta = this.availableChunks.get(chunkName);
+       this.infoboxSlots.forEach((l, k) => {
+               l.innerText = chunkMeta ? chunkMeta[k] : '0';
+       });
+};
\ No newline at end of file