2012-06-21 10:13:21 +02:00
|
|
|
ig.module(
|
|
|
|
'weltmeister.edit-map'
|
|
|
|
)
|
|
|
|
.requires(
|
|
|
|
'impact.background-map',
|
|
|
|
'weltmeister.tile-select'
|
|
|
|
)
|
2012-06-22 17:26:53 +02:00
|
|
|
.defines(function(){ "use strict";
|
2012-06-21 10:13:21 +02:00
|
|
|
|
|
|
|
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 = $( '<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(
|
|
|
|
'<span class="visible'+visClass+'" title="Toggle Visibility (Shift+'+this.hotkey+')"></span>' +
|
|
|
|
'<span class="name">' + this.name + '</span>' +
|
|
|
|
'<span class="size"> (' + this.width + 'x' + this.height + ')</span>'
|
|
|
|
);
|
|
|
|
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
|
|
|
|
|
2012-06-22 17:26:53 +02:00
|
|
|
draw: function() {
|
|
|
|
// For performance reasons, repeated background maps are not drawn
|
|
|
|
// when zoomed out
|
|
|
|
if( this.visible && !(wm.config.view.zoom < 1 && this.repeat) ) {
|
2012-06-21 10:13:21 +02:00
|
|
|
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
|
2012-06-22 17:26:53 +02:00
|
|
|
if( this.active ) {
|
2012-06-21 10:13:21 +02:00
|
|
|
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');
|
2012-06-22 17:26:53 +02:00
|
|
|
scaled.width = this.width;
|
|
|
|
scaled.height = this.height;
|
2012-06-21 10:13:21 +02:00
|
|
|
var scaledCtx = scaled.getContext('2d');
|
|
|
|
|
2012-06-22 17:26:53 +02:00
|
|
|
scaledCtx.drawImage( this.data, 0, 0, this.data.width, this.data.height, 0, 0, this.width , this.height );
|
2012-06-21 10:13:21 +02:00
|
|
|
this.data = scaled;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.loaded = true;
|
2012-06-22 17:26:53 +02:00
|
|
|
if( ig.system.scale != 1 ) {
|
|
|
|
this.resize( ig.system.scale );
|
|
|
|
}
|
|
|
|
|
2012-06-21 10:13:21 +02:00
|
|
|
if( this.loadCallback ) {
|
|
|
|
this.loadCallback( this.path, true );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
});
|