ig.module( 'weltmeister.edit-map' ) .requires( 'impact.background-map', 'weltmeister.tile-select' ) .defines(function(){ "use strict"; wm.EditMap = ig.BackgroundMap.extend({ name: '', visible: true, active: true, linkWithCollision: false, div: null, brush: [[0]], oldData: null, hotkey: -1, ignoreLastClick: false, tileSelect: null, isSelecting: false, selectionBegin: null, init: function( name, tilesize, tileset, foreground ) { this.name = name; this.parent( tilesize, [[0]], tileset || '' ); this.foreground = foreground; this.div = $( '
', { 'class': 'layer layerActive', 'id': ('layer_' + name), 'mouseup': this.click.bind(this) }); this.setName( name ); if( this.foreground ) { $('#layers').prepend( this.div ); } else { $('#layerEntities').after( this.div ); } this.tileSelect = new wm.TileSelect( this ); }, getSaveData: function() { return { name: this.name, width: this.width, height: this.height, linkWithCollision: this.linkWithCollision, visible: this.visible, tilesetName: this.tilesetName, repeat: this.repeat, preRender: this.preRender, distance: this.distance, tilesize: this.tilesize, foreground: this.foreground, data: this.data }; }, resize: function( newWidth, newHeight ) { var newData = new Array( newHeight ); for( var y = 0; y < newHeight; y++ ) { newData[y] = new Array( newWidth ); for( var x = 0; x < newWidth; x++ ) { newData[y][x] = (x < this.width && y < this.height) ? this.data[y][x] : 0; } } this.data = newData; this.width = newWidth; this.height = newHeight; this.resetDiv(); }, beginEditing: function() { this.oldData = ig.copy(this.data); }, getOldTile: function( x, y ) { var tx = Math.floor( x / this.tilesize ); var ty = Math.floor( y / this.tilesize ); if( (tx >= 0 && tx < this.width) && (ty >= 0 && ty < this.height) ) { return this.oldData[ty][tx]; } else { return 0; } }, setTileset: function( tileset ) { if( this.name == 'collision' ) { this.setCollisionTileset(); } else { this.parent( tileset ); } }, setCollisionTileset: function() { var path = wm.config.collisionTiles.path; var scale = this.tilesize / wm.config.collisionTiles.tilesize; this.tiles = new ig.AutoResizedImage( path, scale ); }, // ------------------------------------------------------------------------- // UI setHotkey: function( hotkey ) { this.hotkey = hotkey; this.setName( this.name ); }, setName: function( name ) { this.name = name.replace(/[^0-9a-zA-Z]/g, '_'); this.resetDiv(); }, resetDiv: function() { var visClass = this.visible ? ' checkedVis' : ''; this.div.html( '' + '' + this.name + '' + ' (' + this.width + 'x' + this.height + ')' ); this.div.attr('title', 'Select Layer ('+this.hotkey+')' ); this.div.children('.visible').bind('mousedown', this.toggleVisibilityClick.bind(this) ); }, setActive: function( active ) { this.active = active; if( active ) { this.div.addClass( 'layerActive' ); } else { this.div.removeClass( 'layerActive' ); } }, toggleVisibility: function() { this.visible ^= 1; this.resetDiv(); if( this.visible ) { this.div.children('.visible').addClass('checkedVis'); } else { this.div.children('.visible').removeClass('checkedVis'); } ig.game.draw(); }, toggleVisibilityClick: function( event ) { if( !this.active ) { this.ignoreLastClick = true; } this.toggleVisibility() }, click: function() { if( this.ignoreLastClick ) { this.ignoreLastClick = false; return; } ig.editor.setActiveLayer( this.name ); }, destroy: function() { this.div.remove(); }, // ------------------------------------------------------------------------- // Selecting beginSelecting: function( x, y ) { this.isSelecting = true; this.selectionBegin = {x:x, y:y}; }, endSelecting: function( x, y ) { var r = this.getSelectionRect( x, y); var brush = []; for( var ty = r.y; ty < r.y+r.h; ty++ ) { var row = []; for( var tx = r.x; tx < r.x+r.w; tx++ ) { if( tx < 0 || ty < 0 || tx >= this.width || ty >= this.height ) { row.push( 0 ); } else { row.push( this.data[ty][tx] ); } } brush.push( row ); } this.isSelecting = false; this.selectionBegin = null; return brush; }, getSelectionRect: function( x, y ) { var sx = this.selectionBegin ? this.selectionBegin.x : x, sy = this.selectionBegin ? this.selectionBegin.y : y; var txb = Math.floor( (sx + this.scroll.x) / this.tilesize ), tyb = Math.floor( (sy + this.scroll.y) / this.tilesize ), txe = Math.floor( (x + this.scroll.x) / this.tilesize ), tye = Math.floor( (y + this.scroll.y) / this.tilesize ); return { x: Math.min( txb, txe ), y: Math.min( tyb, tye ), w: Math.abs( txb - txe) + 1, h: Math.abs( tyb - tye) + 1 } }, // ------------------------------------------------------------------------- // Drawing draw: function() { // For performance reasons, repeated background maps are not drawn // when zoomed out if( this.visible && !(wm.config.view.zoom < 1 && this.repeat) ) { this.drawTiled(); } // Grid if( this.active && wm.config.view.grid ) { var x = -ig.system.getDrawPos(this.scroll.x % this.tilesize) - 0.5; var y = -ig.system.getDrawPos(this.scroll.y % this.tilesize) - 0.5; var step = this.tilesize * ig.system.scale; ig.system.context.beginPath(); for( x; x < ig.system.realWidth; x += step ) { ig.system.context.moveTo( x, 0 ); ig.system.context.lineTo( x, ig.system.realHeight ); } for( y; y < ig.system.realHeight; y += step ) { ig.system.context.moveTo( 0, y ); ig.system.context.lineTo( ig.system.realWidth, y ); } ig.system.context.strokeStyle = wm.config.colors.secondary; ig.system.context.stroke(); ig.system.context.closePath(); // Not calling beginPath() again has some weird performance issues // in Firefox 5. closePath has no effect. So to make it happy: ig.system.context.beginPath(); } // Bounds if( this.active ) { ig.system.context.lineWidth = 1; ig.system.context.strokeStyle = wm.config.colors.primary; ig.system.context.strokeRect( -ig.system.getDrawPos(this.scroll.x) - 0.5, -ig.system.getDrawPos(this.scroll.y) - 0.5, this.width * this.tilesize * ig.system.scale + 1, this.height * this.tilesize * ig.system.scale + 1 ); } }, getCursorOffset: function() { var w = this.brush[0].length; var h = this.brush.length; //return {x:0, y:0}; return { x: (w/2-0.5).toInt() * this.tilesize, y: (h/2-0.5).toInt() * this.tilesize } }, drawCursor: function( x, y ) { if( this.isSelecting ) { var r = this.getSelectionRect( x, y); ig.system.context.lineWidth = 1; ig.system.context.strokeStyle = wm.config.colors.selection; ig.system.context.strokeRect( (r.x * this.tilesize - this.scroll.x) * ig.system.scale - 0.5, (r.y * this.tilesize - this.scroll.y) * ig.system.scale - 0.5, r.w * this.tilesize * ig.system.scale + 1, r.h * this.tilesize * ig.system.scale + 1 ); } else { var w = this.brush[0].length; var h = this.brush.length; var co = this.getCursorOffset(); var cx = Math.floor( (x+this.scroll.x) / this.tilesize ) * this.tilesize - this.scroll.x - co.x; var cy = Math.floor( (y+this.scroll.y) / this.tilesize ) * this.tilesize - this.scroll.y - co.y; ig.system.context.lineWidth = 1; ig.system.context.strokeStyle = wm.config.colors.primary; ig.system.context.strokeRect( ig.system.getDrawPos(cx)-0.5, ig.system.getDrawPos(cy)-0.5, w * this.tilesize * ig.system.scale + 1, h * this.tilesize * ig.system.scale + 1 ); ig.system.context.globalAlpha = 0.5; for( var ty = 0; ty < h; ty++ ) { for( var tx = 0; tx < w; tx++ ) { var t = this.brush[ty][tx]; if( t ) { var px = cx + tx * this.tilesize; var py = cy + ty * this.tilesize; this.tiles.drawTile( px, py, t-1, this.tilesize ); } } } ig.system.context.globalAlpha = 1; } } }); ig.AutoResizedImage = ig.Image.extend({ internalScale: 1, staticInstantiate: function() { return null; // Never cache! }, init: function( path, internalScale ) { this.internalScale = internalScale; this.parent( path ); }, onload: function( event ) { this.width = Math.ceil(this.data.width * this.internalScale); this.height = Math.ceil(this.data.height * this.internalScale); if( this.internalScale != 1 ) { var scaled = ig.$new('canvas'); scaled.width = this.width; scaled.height = this.height; var scaledCtx = scaled.getContext('2d'); scaledCtx.drawImage( this.data, 0, 0, this.data.width, this.data.height, 0, 0, this.width , this.height ); this.data = scaled; } this.loaded = true; if( ig.system.scale != 1 ) { this.resize( ig.system.scale ); } if( this.loadCallback ) { this.loadCallback( this.path, true ); } } }); });