added the raw impact licence into the "/dev" folder

This commit is contained in:
Ruben Müller 2012-06-21 10:13:21 +02:00
parent 0f4a2d7271
commit 6d6c98ddf2
47 changed files with 8488 additions and 0 deletions

32
dev/index.html Executable file
View file

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<title>Impact Game</title>
<style type="text/css">
html,body {
background-color: #000;
color: #fff;
font-family: helvetica, arial, sans-serif;
margin: 0;
padding: 0;
font-size: 12pt;
}
#canvas {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
border: 1px solid #555;
}
</style>
<script type="text/javascript" src="lib/impact/impact.js"></script>
<script type="text/javascript" src="lib/game/main.js"></script>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>

45
dev/lib/game/main.js Executable file
View file

@ -0,0 +1,45 @@
ig.module(
'game.main'
)
.requires(
'impact.game',
'impact.font'
)
.defines(function(){
MyGame = ig.Game.extend({
// Load a font
font: new ig.Font( 'media/04b03.font.png' ),
init: function() {
// Initialize your game here; bind keys etc.
},
update: function() {
// Update all entities and backgroundMaps
this.parent();
// Add your own, additional update code here
},
draw: function() {
// Draw all entities and backgroundMaps
this.parent();
// Add your own drawing code here
var x = ig.system.width/2,
y = ig.system.height/2;
this.font.draw( 'It Works!', x, y, ig.Font.ALIGN.CENTER );
}
});
// Start the Game with 60fps, a resolution of 320x240, scaled
// up by a factor of 2
ig.main( '#canvas', MyGame, 60, 320, 240, 2 );
});

127
dev/lib/impact/animation.js Executable file
View file

@ -0,0 +1,127 @@
ig.module(
'impact.animation'
)
.requires(
'impact.timer',
'impact.image'
)
.defines(function(){
ig.AnimationSheet = ig.Class.extend({
width: 8,
height: 8,
image: null,
init: function( path, width, height ) {
this.width = width;
this.height = height;
this.image = new ig.Image( path );
}
});
ig.Animation = ig.Class.extend({
sheet: null,
timer: null,
sequence: [],
flip: {x: false, y: false},
pivot: {x: 0, y: 0},
frame: 0,
tile: 0,
loopCount: 0,
alpha: 1,
angle: 0,
init: function( sheet, frameTime, sequence, stop ) {
this.sheet = sheet;
this.pivot = {x: sheet.width/2, y: sheet.height/2 };
this.timer = new ig.Timer();
this.frameTime = frameTime;
this.sequence = sequence;
this.stop = !!stop;
this.tile = this.sequence[0];
},
rewind: function() {
this.timer.reset();
this.loopCount = 0;
this.tile = this.sequence[0];
return this;
},
gotoFrame: function( f ) {
this.timer.set( this.frameTime * -f );
this.update();
},
gotoRandomFrame: function() {
this.gotoFrame( Math.floor(Math.random() * this.sequence.length) )
},
update: function() {
var frameTotal = Math.floor(this.timer.delta() / this.frameTime);
this.loopCount = Math.floor(frameTotal / this.sequence.length);
if( this.stop && this.loopCount > 0 ) {
this.frame = this.sequence.length - 1;
}
else {
this.frame = frameTotal % this.sequence.length;
}
this.tile = this.sequence[ this.frame ];
},
draw: function( targetX, targetY ) {
var bbsize = Math.max(this.sheet.width, this.sheet.height);
// On screen?
if(
targetX > ig.system.width || targetY > ig.system.height ||
targetX + bbsize < 0 || targetY + bbsize < 0
) {
return;
}
if( this.alpha != 1) {
ig.system.context.globalAlpha = this.alpha;
}
if( this.angle == 0 ) {
this.sheet.image.drawTile(
targetX, targetY,
this.tile, this.sheet.width, this.sheet.height,
this.flip.x, this.flip.y
);
}
else {
ig.system.context.save();
ig.system.context.translate(
ig.system.getDrawPos(targetX + this.pivot.x),
ig.system.getDrawPos(targetY + this.pivot.y)
);
ig.system.context.rotate( this.angle );
this.sheet.image.drawTile(
-this.pivot.x, -this.pivot.y,
this.tile, this.sheet.width, this.sheet.height,
this.flip.x, this.flip.y
);
ig.system.context.restore();
}
if( this.alpha != 1) {
ig.system.context.globalAlpha = 1;
}
}
});
});

242
dev/lib/impact/background-map.js Executable file
View file

@ -0,0 +1,242 @@
ig.module(
'impact.background-map'
)
.requires(
'impact.map',
'impact.image'
)
.defines(function(){
ig.BackgroundMap = ig.Map.extend({
tiles: null,
scroll: {x: 0, y:0},
distance: 1,
repeat: false,
tilesetName: '',
foreground: false,
enabled: true,
preRender: false,
preRenderedChunks: null,
chunkSize: 512,
debugChunks: false,
anims: {},
init: function( tilesize, data, tileset ) {
this.parent( tilesize, data );
this.setTileset( tileset );
},
setTileset: function( tileset ) {
this.tilesetName = tileset instanceof ig.Image ? tileset.path : tileset;
this.tiles = new ig.Image( this.tilesetName );
this.preRenderedChunks = null;
},
setScreenPos: function( x, y ) {
this.scroll.x = x / this.distance;
this.scroll.y = y / this.distance;
},
preRenderMapToChunks: function() {
var totalWidth = this.width * this.tilesize * ig.system.scale,
totalHeight = this.height * this.tilesize * ig.system.scale;
var chunkCols = Math.ceil(totalWidth / this.chunkSize),
chunkRows = Math.ceil(totalHeight / this.chunkSize);
this.preRenderedChunks = [];
for( var y = 0; y < chunkRows; y++ ) {
this.preRenderedChunks[y] = [];
for( var x = 0; x < chunkCols; x++ ) {
var chunkWidth = (x == chunkCols-1)
? totalWidth - x * this.chunkSize
: this.chunkSize;
var chunkHeight = (y == chunkRows-1)
? totalHeight - y * this.chunkSize
: this.chunkSize;
this.preRenderedChunks[y][x] = this.preRenderChunk( x, y, chunkWidth, chunkHeight );
}
}
},
preRenderChunk: function( cx, cy, w, h ) {
var tw = w / this.tilesize / ig.system.scale + 1;
th = h / this.tilesize / ig.system.scale + 1;
var nx = (cx * this.chunkSize / ig.system.scale) % this.tilesize,
ny = (cy * this.chunkSize / ig.system.scale) % this.tilesize;
var tx = Math.floor(cx * this.chunkSize / this.tilesize / ig.system.scale),
ty = Math.floor(cy * this.chunkSize / this.tilesize / ig.system.scale);
var chunk = ig.$new( 'canvas');
chunk.width = w;
chunk.height = h;
var oldContext = ig.system.context;
ig.system.context = chunk.getContext("2d");
for( var x = 0; x < tw; x++ ) {
for( var y = 0; y < th; y++ ) {
if( x + tx < this.width && y + ty < this.height ) {
var tile = this.data[y+ty][x+tx];
if( tile ) {
this.tiles.drawTile(
x * this.tilesize - nx, y * this.tilesize - ny,
tile - 1, this.tilesize
);
}
}
}
}
ig.system.context = oldContext;
return chunk;
},
draw: function() {
if( !this.tiles.loaded || !this.enabled ) {
return;
}
if( this.preRender ) {
this.drawPreRendered();
}
else {
this.drawTiled();
}
},
drawPreRendered: function() {
if( !this.preRenderedChunks ) {
this.preRenderMapToChunks();
}
var dx = ig.system.getDrawPos(this.scroll.x),
dy = ig.system.getDrawPos(this.scroll.y);
if( this.repeat ) {
dx %= this.width * this.tilesize * ig.system.scale;
dy %= this.height * this.tilesize * ig.system.scale;
}
var minChunkX = Math.max( Math.floor(dx / this.chunkSize), 0 ),
minChunkY = Math.max( Math.floor(dy / this.chunkSize), 0 ),
maxChunkX = Math.ceil((dx+ig.system.realWidth) / this.chunkSize),
maxChunkY = Math.ceil((dy+ig.system.realHeight) / this.chunkSize),
maxRealChunkX = this.preRenderedChunks[0].length,
maxRealChunkY = this.preRenderedChunks.length;
if( !this.repeat ) {
maxChunkX = Math.min( maxChunkX, maxRealChunkX );
maxChunkY = Math.min( maxChunkY, maxRealChunkY );
}
var nudgeY = 0;
for( var cy = minChunkY; cy < maxChunkY; cy++ ) {
var nudgeX = 0;
for( var cx = minChunkX; cx < maxChunkX; cx++ ) {
var chunk = this.preRenderedChunks[cy % maxRealChunkY][cx % maxRealChunkX];
var x = -dx + cx * this.chunkSize - nudgeX;
var y = -dy + cy * this.chunkSize - nudgeY;
ig.system.context.drawImage( chunk, x, y);
ig.Image.drawCount++;
if( this.debugChunks ) {
ig.system.context.strokeStyle = '#f0f';
ig.system.context.strokeRect( x, y, this.chunkSize, this.chunkSize );
}
// If we repeat in X and this chunks width wasn't the full chunk size
// and the screen is not already filled, we need to draw anohter chunk
// AND nudge it to be flush with the last chunk
if( this.repeat && chunk.width < this.chunkSize && x + chunk.width < ig.system.realWidth ) {
nudgeX = this.chunkSize - chunk.width;
maxChunkX++;
}
}
// Same as above, but for Y
if( this.repeat && chunk.height < this.chunkSize && y + chunk.height < ig.system.realHeight ) {
nudgeY = this.chunkSize - chunk.height;
maxChunkY++;
}
}
},
drawTiled: function() {
var tile = 0,
anim = null,
tileOffsetX = (this.scroll.x / this.tilesize).toInt(),
tileOffsetY = (this.scroll.y / this.tilesize).toInt(),
pxOffsetX = this.scroll.x % this.tilesize,
pxOffsetY = this.scroll.y % this.tilesize,
pxMinX = -pxOffsetX - this.tilesize,
pxMinY = -pxOffsetY - this.tilesize,
pxMaxX = ig.system.width + this.tilesize - pxOffsetX,
pxMaxY = ig.system.height + this.tilesize - pxOffsetY;
// FIXME: could be sped up for non-repeated maps: restrict the for loops
// to the map size instead of to the screen size and skip the 'repeat'
// checks inside the loop.
for( var mapY = -1, pxY = pxMinY; pxY < pxMaxY; mapY++, pxY += this.tilesize) {
var tileY = mapY + tileOffsetY;
// Repeat Y?
if( tileY >= this.height || tileY < 0 ) {
if( !this.repeat ) { continue; }
tileY = tileY > 0
? tileY % this.height
: ((tileY+1) % this.height) + this.height - 1;
}
for( var mapX = -1, pxX = pxMinX; pxX < pxMaxX; mapX++, pxX += this.tilesize ) {
var tileX = mapX + tileOffsetX;
// Repeat X?
if( tileX >= this.width || tileX < 0 ) {
if( !this.repeat ) { continue; }
tileX = tileX > 0
? tileX % this.width
: ((tileX+1) % this.width) + this.width - 1;
}
// Draw!
if( (tile = this.data[tileY][tileX]) ) {
if( (anim = this.anims[tile-1]) ) {
anim.draw( pxX, pxY );
}
else {
this.tiles.drawTile( pxX, pxY, tile-1, this.tilesize );
}
}
} // end for x
} // end for y
}
});
});

258
dev/lib/impact/collision-map.js Executable file
View file

@ -0,0 +1,258 @@
ig.module(
'impact.collision-map'
)
.requires(
'impact.map'
)
.defines(function(){
ig.CollisionMap = ig.Map.extend({
init: function( tilesize, data, tiledef ) {
this.parent( tilesize, data );
this.tiledef = tiledef || ig.CollisionMap.defaultTileDef;
},
trace: function( x, y, vx, vy, objectWidth, objectHeight ) {
// Set up the trace-result
var res = {
collision: {x: false, y: false, slope: false},
pos: {x: x, y: y},
tile: {x: 0, y: 0}
};
// Break the trace down into smaller steps if necessary
var steps = Math.ceil(Math.max(Math.abs(vx), Math.abs(vy)) / this.tilesize);
if( steps > 1 ) {
var sx = vx / steps;
var sy = vy / steps;
for( var i = 0; i < steps && (sx || sy); i++ ) {
this._traceStep( res, x, y, sx, sy, objectWidth, objectHeight, vx, vy, i );
x = res.pos.x;
y = res.pos.y;
if( res.collision.x ) { sx = 0; vx = 0; }
if( res.collision.y ) { sy = 0; vy = 0; }
if( res.collision.slope ) { break; }
}
}
// Just one step
else {
this._traceStep( res, x, y, vx, vy, objectWidth, objectHeight, vx, vy, 0 );
}
return res;
},
_traceStep: function( res, x, y, vx, vy, width, height, rvx, rvy, step ) {
res.pos.x += vx;
res.pos.y += vy;
var t = 0;
// Horizontal collision (walls)
if( vx ) {
var pxOffsetX = (vx > 0 ? width : 0);
var tileOffsetX = (vx < 0 ? this.tilesize : 0);
var firstTileY = Math.max( Math.floor(y / this.tilesize), 0 );
var lastTileY = Math.min( Math.ceil((y + height) / this.tilesize), this.height );
var tileX = Math.floor( (res.pos.x + pxOffsetX) / this.tilesize );
// We need to test the new tile position as well as the current one, as we
// could still collide with the current tile if it's a line def.
// We can skip this test if this is not the first step or the new tile position
// is the same as the current one.
var prevTileX = Math.floor( (x + pxOffsetX) / this.tilesize );
if( step > 0 || tileX == prevTileX || prevTileX < 0 || prevTileX >= this.width ) {
prevTileX = -1;
}
// Still inside this collision map?
if( tileX >= 0 && tileX < this.width ) {
for( var tileY = firstTileY; tileY < lastTileY; tileY++ ) {
if( prevTileX != -1 ) {
t = this.data[tileY][prevTileX];
if( t > 1 && this._checkTileDef(res, t, x, y, rvx, rvy, width, height, prevTileX, tileY) ) {
break;
}
}
t = this.data[tileY][tileX];
if(
t == 1 || // fully solid tile?
(t > 1 && this._checkTileDef(res, t, x, y, rvx, rvy, width, height, tileX, tileY)) // slope?
) {
if( t > 1 && res.collision.slope ) {
break;
}
// full tile collision!
res.collision.x = true;
res.tile.x = t;
res.pos.x = tileX * this.tilesize - pxOffsetX + tileOffsetX;
break;
}
}
}
}
// Vertical collision (floor, ceiling)
if( vy ) {
var pxOffsetY = (vy > 0 ? height : 0);
var tileOffsetY = (vy < 0 ? this.tilesize : 0);
var firstTileX = Math.max( Math.floor(res.pos.x / this.tilesize), 0 );
var lastTileX = Math.min( Math.ceil((res.pos.x + width) / this.tilesize), this.width );
var tileY = Math.floor( (res.pos.y + pxOffsetY) / this.tilesize );
var prevTileY = Math.floor( (y + pxOffsetY) / this.tilesize );
if( step > 0 || tileY == prevTileY || prevTileY < 0 || prevTileY >= this.height ) {
prevTileY = -1;
}
// Still inside this collision map?
if( tileY >= 0 && tileY < this.height ) {
for( var tileX = firstTileX; tileX < lastTileX; tileX++ ) {
if( prevTileY != -1 ) {
t = this.data[prevTileY][tileX];
if( t > 1 && this._checkTileDef(res, t, x, y, rvx, rvy, width, height, tileX, prevTileY) ) {
break;
}
}
t = this.data[tileY][tileX];
if(
t == 1 || // fully solid tile?
(t > 1 && this._checkTileDef(res, t, x, y, rvx, rvy, width, height, tileX, tileY)) // slope?
) {
if( t > 1 && res.collision.slope ) {
break;
}
// full tile collision!
res.collision.y = true;
res.tile.y = t;
res.pos.y = tileY * this.tilesize - pxOffsetY + tileOffsetY;
break;
}
}
}
}
// res is changed in place, nothing to return
},
_checkTileDef: function( res, t, x, y, vx, vy, width, height, tileX, tileY ) {
var def = this.tiledef[t];
if( !def ) { return false; }
var lx = (tileX + def[0]) * this.tilesize,
ly = (tileY + def[1]) * this.tilesize,
lvx = (def[2] - def[0]) * this.tilesize,
lvy = (def[3] - def[1]) * this.tilesize,
solid = def[4];
// Find the box corner to test, relative to the line
var tx = x + vx + (lvy < 0 ? width : 0) - lx,
ty = y + vy + (lvx > 0 ? height : 0) - ly;
// Is the box corner behind the line?
if( lvx * ty - lvy * tx > 0 ) {
// Lines are only solid from one side - find the dot product of
// line normal and movement vector and dismiss if wrong side
if( vx * -lvy + vy * lvx < 0 ) {
return solid;
}
// Find the line normal
var length = Math.sqrt(lvx * lvx + lvy * lvy);
var nx = lvy/length,
ny = -lvx/length;
// Project out of the line
var proj = tx * nx + ty * ny;
var px = nx * proj,
py = ny * proj;
// If we project further out than we moved in, then this is a full
// tile collision
if( px*px+py*py >= vx*vx+vy*vy ) {
return true;
}
res.pos.x = x + vx - px;
res.pos.y = y + vy - py;
res.collision.slope = {x: lvx, y: lvy, nx: nx, ny: ny};
return true;
}
return false;
}
});
// Default Slope Tile definition. Each tile is defined by an array of 5 vars:
// - 4 for the line in tile coordinates (0 -- 1)
// - 1 specifing whether the tile is 'filled' behind the line or not
// [ x1, y1, x2, y2, solid ]
// Defining 'half', 'one third' and 'two thirds' as vars makes it a bit
// easier to read... I hope.
var H = 1/2,
N = 1/3,
M = 2/3,
SOLID = true,
NON_SOLID = false;
ig.CollisionMap.defaultTileDef = {
/* 15 NE */ 5: [0,1, 1,M, SOLID], 6: [0,M, 1,N, SOLID], 7: [0,N, 1,0, SOLID],
/* 22 NE */ 3: [0,1, 1,H, SOLID], 4: [0,H, 1,0, SOLID],
/* 45 NE */ 2: [0,1, 1,0, SOLID],
/* 67 NE */ 10: [H,1, 1,0, SOLID], 21: [0,1, H,0, SOLID],
/* 75 NE */ 32: [M,1, 1,0, SOLID], 43: [N,1, M,0, SOLID], 54: [0,1, N,0, SOLID],
/* 15 SE */ 27: [0,0, 1,N, SOLID], 28: [0,N, 1,M, SOLID], 29: [0,M, 1,1, SOLID],
/* 22 SE */ 25: [0,0, 1,H, SOLID], 26: [0,H, 1,1, SOLID],
/* 45 SE */ 24: [0,0, 1,1, SOLID],
/* 67 SE */ 11: [0,0, H,1, SOLID], 22: [H,0, 1,1, SOLID],
/* 75 SE */ 33: [0,0, N,1, SOLID], 44: [N,0, M,1, SOLID], 55: [M,0, 1,1, SOLID],
/* 15 NW */ 16: [1,N, 0,0, SOLID], 17: [1,M, 0,N, SOLID], 18: [1,1, 0,M, SOLID],
/* 22 NW */ 14: [1,H, 0,0, SOLID], 15: [1,1, 0,H, SOLID],
/* 45 NW */ 13: [1,1, 0,0, SOLID],
/* 67 NW */ 8: [H,1, 0,0, SOLID], 19: [1,1, H,0, SOLID],
/* 75 NW */ 30: [N,1, 0,0, SOLID], 41: [M,1, N,0, SOLID], 52: [1,1, M,0, SOLID],
/* 15 SW */ 38: [1,M, 0,1, SOLID], 39: [1,N, 0,M, SOLID], 40: [1,0, 0,N, SOLID],
/* 22 SW */ 36: [1,H, 0,1, SOLID], 37: [1,0, 0,H, SOLID],
/* 45 SW */ 35: [1,0, 0,1, SOLID],
/* 67 SW */ 9: [1,0, H,1, SOLID], 20: [H,0, 0,1, SOLID],
/* 75 SW */ 31: [1,0, M,1, SOLID], 42: [M,0, N,1, SOLID], 53: [N,0, 0,1, SOLID],
/* Go N */ 12: [0,0, 1,0, NON_SOLID],
/* Go S */ 23: [1,1, 0,1, NON_SOLID],
/* Go E */ 34: [1,0, 1,1, NON_SOLID],
/* Go W */ 45: [0,1, 0,0, NON_SOLID]
// Now that was fun!
};
// Static Dummy CollisionMap; never collides
ig.CollisionMap.staticNoCollision = { trace: function( x, y, vx, vy ) {
return {
collision: {x: false, y: false, slope: false},
pos: {x: x+vx, y: y+vy},
tile: {x: 0, y: 0}
};
}};
});

148
dev/lib/impact/debug/debug.css Executable file
View file

@ -0,0 +1,148 @@
.ig_debug {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
background-color: #000;
border-top: 2px solid #f57401;
font-size: 12px;
color: #fff;
z-index: 1000;
-webkit-user-select: none;
}
.ig_debug_panel_menu {
height: 28px;
background: #222;
background: -webkit-gradient(linear, left bottom, left top, color-stop(0,#000000), color-stop(1,#333));
background: -moz-linear-gradient(center bottom, #000000 0%, #333 100%);
background: -o-linear-gradient(#333, #000000);
}
.ig_debug_panel_menu div {
float: left;
height: 22px;
padding: 6px 8px 0 8px;
border-right: 1px solid #333;
}
.ig_debug_panel_menu .ig_debug_head {
font-weight: bold;
color: #888;
}
.ig_debug_menu_item:hover {
cursor: pointer;
background-color: #fff;
color: #000;
}
.ig_debug_menu_item.active, .ig_debug_menu_item.active:hover {
background-color: #000;
color: #fff;
}
.ig_debug_stats {
position: absolute;
right: 0;
top: 0;
float: right;
color: #888;
border-left: 1px solid #333;
text-align: right;
}
.ig_debug_stats span {
width: 3em;
display:inline-block;
color: #fff !important;
margin-right: 0.2em;
margin-left: 0.3em;
font-family: bitstream vera sans mono, courier new;
white-space: nowrap;
}
.ig_debug_panel {
height: 152px;
overflow: auto;
position: relative;
}
.ig_debug_panel canvas {
border-bottom: 1px solid #444;
}
.ig_debug_panel .ig_debug_panel {
padding: 8px;
height: auto;
float: left;
background-color: #000;
border-right: 2px solid #222;
}
.ig_debug_option {
padding: 2px 0 2px 8px;
cursor: pointer;
}
.ig_debug_option:first-child {
margin-top: 8px;
}
.ig_debug_option:hover {
background-color: #111;
}
.ig_debug_graph_mark {
position: absolute;
color: #888;
left: 4px;
font-size: 10px;
margin-top: -12px;
}
.ig_debug_legend {
color: #ccc;
}
.ig_debug_label_mark {
display: inline-block;
width: 10px;
height: 10px;
margin-right: 4px;
-webkit-transition: 0.1s linear;
-moz-transition: 0.1s linear;
}
.ig_debug_legend_color {
display: inline-block;
width: 6px;
height: 10px;
margin-right: 4px;
margin-left: 16px;
}
.ig_debug_legend_number {
width: 3em;
display: inline-block;
text-align: right;
font-family: bitstream vera sans mono, courier new;
color: #fff;
margin-right: 0.2em;
}
.ig_debug_map_container {
position: relative;
overflow: hidden;
border: 1px solid #888;
}
.ig_debug_map_container canvas {
position: absolute;
}
.ig_debug_map_screen {
position: absolute;
border: 1px solid #f0f;
}

13
dev/lib/impact/debug/debug.js Executable file
View file

@ -0,0 +1,13 @@
ig.module(
'impact.debug.debug'
)
.requires(
'impact.debug.entities-panel',
'impact.debug.maps-panel',
'impact.debug.graph-panel'
)
.defines(function(){
/* Empty module to require all debug panels */
});

View file

@ -0,0 +1,129 @@
ig.module(
'impact.debug.entities-panel'
)
.requires(
'impact.debug.menu',
'impact.entity'
)
.defines(function(){
ig.Entity.inject({
colors: {
names: '#fff',
velocities: '#0f0',
boxes: '#f00'
},
draw: function() {
this.parent();
// Collision Boxes
if( ig.Entity._debugShowBoxes ) {
ig.system.context.strokeStyle = this.colors.boxes;
ig.system.context.lineWidth = 1.0;
ig.system.context.strokeRect(
ig.system.getDrawPos(this.pos.x.round() - ig.game.screen.x) - 0.5,
ig.system.getDrawPos(this.pos.y.round() - ig.game.screen.y) - 0.5,
this.size.x * ig.system.scale,
this.size.y * ig.system.scale
);
}
// Velocities
if( ig.Entity._debugShowVelocities ) {
var x = this.pos.x + this.size.x/2;
var y = this.pos.y + this.size.y/2;
this._debugDrawLine( this.colors.velocities, x, y, x + this.vel.x, y + this.vel.y );
}
// Names & Targets
if( ig.Entity._debugShowNames ) {
if( this.name ) {
ig.system.context.fillStyle = this.colors.names;
ig.system.context.fillText(
this.name,
ig.system.getDrawPos(this.pos.x - ig.game.screen.x),
ig.system.getDrawPos(this.pos.y - ig.game.screen.y)
);
}
if( typeof(this.target) == 'object' ) {
for( var t in this.target ) {
var ent = ig.game.getEntityByName( this.target[t] );
if( ent ) {
this._debugDrawLine( this.colors.names,
this.pos.x + this.size.x/2, this.pos.y + this.size.y/2,
ent.pos.x + ent.size.x/2, ent.pos.y + ent.size.y/2
);
}
}
}
}
},
_debugDrawLine: function( color, sx, sy, dx, dy ) {
ig.system.context.strokeStyle = color;
ig.system.context.lineWidth = 1.0;
ig.system.context.beginPath();
ig.system.context.moveTo(
ig.system.getDrawPos(sx - ig.game.screen.x),
ig.system.getDrawPos(sy - ig.game.screen.y)
);
ig.system.context.lineTo(
ig.system.getDrawPos(dx - ig.game.screen.x),
ig.system.getDrawPos(dy - ig.game.screen.y)
);
ig.system.context.stroke();
ig.system.context.closePath();
}
});
ig.Entity._debugEnableChecks = true;
ig.Entity._debugShowBoxes = false;
ig.Entity._debugShowVelocities = false;
ig.Entity._debugShowNames = false;
ig.Entity.oldCheckPair = ig.Entity.checkPair;
ig.Entity.checkPair = function( a, b ) {
if( !ig.Entity._debugEnableChecks ) {
return;
}
ig.Entity.oldCheckPair( a, b );
};
ig.debug.addPanel({
type: ig.DebugPanel,
name: 'entities',
label: 'Entities',
options: [
{
name: 'Checks & Collisions',
object: ig.Entity,
property: '_debugEnableChecks'
},
{
name: 'Show Collision Boxes',
object: ig.Entity,
property: '_debugShowBoxes'
},
{
name: 'Show Velocities',
object: ig.Entity,
property: '_debugShowVelocities'
},
{
name: 'Show Names & Targets',
object: ig.Entity,
property: '_debugShowNames'
}
]
});
});

View file

@ -0,0 +1,198 @@
ig.module(
'impact.debug.graph-panel'
)
.requires(
'impact.debug.menu',
'impact.system',
'impact.game',
'impact.image'
)
.defines(function(){
ig.Game.inject({
draw: function() {
ig.graph.beginClock('draw');
this.parent();
ig.graph.endClock('draw');
},
update: function() {
ig.graph.beginClock('update');
this.parent();
ig.graph.endClock('update');
},
checkEntities: function() {
ig.graph.beginClock('checks');
this.parent();
ig.graph.endClock('checks');
}
});
ig.DebugGraphPanel = ig.DebugPanel.extend({
clocks: {},
marks: [],
textY: 0,
height: 128,
ms: 64,
timeBeforeRun: 0,
init: function( name, label ) {
this.parent( name, label );
this.mark16ms = (this.height - (this.height/this.ms) * 16).round();
this.mark33ms = (this.height - (this.height/this.ms) * 33).round();
this.msHeight = this.height/this.ms;
this.graph = ig.$new('canvas');
this.graph.width = window.innerWidth;
this.graph.height = this.height;
this.container.appendChild( this.graph );
this.ctx = this.graph.getContext('2d');
this.ctx.fillStyle = '#444';
this.ctx.fillRect( 0, this.mark16ms, this.graph.width, 1 );
this.ctx.fillRect( 0, this.mark33ms, this.graph.width, 1 );
this.addGraphMark( '16ms', this.mark16ms );
this.addGraphMark( '33ms', this.mark33ms );
this.addClock( 'draw', 'Draw', '#13baff' );
this.addClock( 'update', 'Entity Update', '#bb0fff' );
this.addClock( 'checks', 'Entity Checks & Collisions', '#a2e908' );
this.addClock( 'lag', 'System Lag', '#f26900' );
ig.mark = this.mark.bind(this);
ig.graph = this;
},
addGraphMark: function( name, height ) {
var span = ig.$new('span');
span.className = 'ig_debug_graph_mark';
span.textContent = name;
span.style.top = height.round() + 'px';
this.container.appendChild( span );
},
addClock: function( name, description, color ) {
var mark = ig.$new('span');
mark.className = 'ig_debug_legend_color';
mark.style.backgroundColor = color;
var number = ig.$new('span');
number.className = 'ig_debug_legend_number';
number.appendChild( document.createTextNode('0') );
var legend = ig.$new('span');
legend.className = 'ig_debug_legend';
legend.appendChild( mark );
legend.appendChild( document.createTextNode(description +' (') );
legend.appendChild( number );
legend.appendChild( document.createTextNode('ms)') );
this.container.appendChild( legend );
this.clocks[name] = {
description: description,
color: color,
current: 0,
start: Date.now(),
avg: 0,
html: number
};
},
beginClock: function( name, offset ) {
this.clocks[name].start = Date.now() + (offset || 0);
},
endClock: function( name ) {
var c = this.clocks[name];
c.current = Math.round(Date.now() - c.start);
c.avg = c.avg * 0.8 + c.current * 0.2;
},
mark: function( msg, color ) {
if( this.active ) {
this.marks.push( {msg:msg, color:(color||'#fff')} );
}
},
beforeRun: function() {
this.endClock('lag');
this.timeBeforeRun = Date.now();
},
afterRun: function() {
var frameTime = Date.now() - this.timeBeforeRun;
var nextFrameDue = (1000/ig.system.fps) - frameTime;
this.beginClock('lag', Math.max(nextFrameDue, 0));
var x = this.graph.width-1;
var y = this.height;
this.ctx.drawImage( this.graph, -1, 0 );
this.ctx.fillStyle = '#000';
this.ctx.fillRect( x, 0, 1, this.height );
this.ctx.fillStyle = '#444';
this.ctx.fillRect( x, this.mark16ms, 1, 1 );
this.ctx.fillStyle = '#444';
this.ctx.fillRect( x, this.mark33ms, 1, 1 );
for( var ci in this.clocks ) {
var c = this.clocks[ci];
c.html.textContent = c.avg.toFixed(2);
if( c.color && c.current > 0 ) {
this.ctx.fillStyle = c.color;
var h = c.current * this.msHeight;
y -= h;
this.ctx.fillRect( x, y, 1, h );
c.current = 0;
}
}
this.ctx.textAlign = 'right';
this.ctx.textBaseline = 'top';
this.ctx.globalAlpha = 0.5;
for( var i = 0; i < this.marks.length; i++ ) {
var m = this.marks[i];
this.ctx.fillStyle = m.color;
this.ctx.fillRect( x, 0, 1, this.height );
if( m.msg ) {
this.ctx.fillText( m.msg, x-1, this.textY );
this.textY = (this.textY+8)%32;
}
}
this.ctx.globalAlpha = 1;
this.marks = [];
}
});
ig.debug.addPanel({
type: ig.DebugGraphPanel,
name: 'graph',
label: 'Performance'
});
});

View file

@ -0,0 +1,154 @@
ig.module(
'impact.debug.maps-panel'
)
.requires(
'impact.debug.menu',
'impact.game',
'impact.background-map'
)
.defines(function(){
ig.Game.inject({
loadLevel: function( data ) {
this.parent(data);
ig.debug.panels.maps.load(this);
}
});
ig.DebugMapsPanel = ig.DebugPanel.extend({
maps: [],
mapScreens: [],
init: function( name, label ) {
this.parent( name, label );
this.load();
},
load: function( game ) {
this.options = [];
this.panels = [];
if( !game || !game.backgroundMaps.length ) {
this.container.innerHTML = '<em>No Maps Loaded</em>';
return;
}
this.maps = game.backgroundMaps;
this.mapScreens = [];
this.container.innerHTML = '';
for( var m = 0; m < this.maps.length; m++ ) {
var map = this.maps[m];
var subPanel = new ig.DebugPanel( m, 'Layer '+m );
var head = new ig.$new('strong');
head.textContent = m +': ' + map.tiles.path;
subPanel.container.appendChild( head );
subPanel.addOption( new ig.DebugOption('Enabled', map, 'enabled') );
subPanel.addOption( new ig.DebugOption('Pre Rendered', map, 'preRender') );
subPanel.addOption( new ig.DebugOption('Show Chunks', map, 'debugChunks') );
this.generateMiniMap( subPanel, map, m );
this.addPanel( subPanel );
}
},
generateMiniMap: function( panel, map, id ) {
var s = ig.system.scale; // we'll need this a lot
// resize the tileset, so that one tile is 's' pixels wide and high
var ts = ig.$new('canvas');
var tsctx = ts.getContext('2d');
var w = map.tiles.width * s;
var h = map.tiles.height * s;
var ws = w / map.tilesize;
var hs = h / map.tilesize;
tsctx.drawImage( map.tiles.data, 0, 0, w, h, 0, 0, ws, hs );
// create the minimap canvas
var mapCanvas = ig.$new('canvas');
mapCanvas.width = map.width * s;
mapCanvas.height = map.height * s;
var ctx = mapCanvas.getContext('2d');
if( ig.game.clearColor ) {
ctx.fillStyle = ig.game.clearColor;
ctx.fillRect(0, 0, w, h);
}
// draw the map
var tile = 0;
for( var x = 0; x < map.width; x++ ) {
for( var y = 0; y < map.height; y++ ) {
if( (tile = map.data[y][x]) ) {
ctx.drawImage(
ts,
Math.floor(((tile-1) * s) % ws),
Math.floor((tile-1) * s / ws) * s,
s, s,
x * s, y * s,
s, s
);
}
}
}
var mapContainer = ig.$new('div');
mapContainer.className = 'ig_debug_map_container';
mapContainer.style.width = map.width * s + 'px';
mapContainer.style.height = map.height * s + 'px';
var mapScreen = ig.$new('div');
mapScreen.className = 'ig_debug_map_screen';
mapScreen.style.width = ((ig.system.width / map.tilesize) * s - 2) + 'px';
mapScreen.style.height = ((ig.system.height / map.tilesize) * s - 2) + 'px';
this.mapScreens[id] = mapScreen;
mapContainer.appendChild( mapCanvas );
mapContainer.appendChild( mapScreen );
panel.container.appendChild( mapContainer );
},
afterRun: function() {
// Update the screen position DIV for each mini-map
var s = ig.system.scale;
for( var m = 0; m < this.maps.length; m++ ) {
var map = this.maps[m];
var screen = this.mapScreens[m];
if( !map || !screen ) { // Quick sanity check
continue;
}
var x = map.scroll.x / map.tilesize;
var y = map.scroll.y / map.tilesize;
if( map.repeat ) {
x %= map.width;
y %= map.height;
}
screen.style.left = (x * s) + 'px';
screen.style.top = (y * s) + 'px';
}
}
});
ig.debug.addPanel({
type: ig.DebugMapsPanel,
name: 'maps',
label: 'Background Maps'
});
});

292
dev/lib/impact/debug/menu.js Executable file
View file

@ -0,0 +1,292 @@
ig.module(
'impact.debug.menu'
)
.requires(
'dom.ready',
'impact.system'
)
.defines(function(){
ig.System.inject({
run: function() {
ig.debug.beforeRun();
this.parent();
ig.debug.afterRun();
},
setGameNow: function( gameClass ) {
this.parent( gameClass );
ig.debug.ready();
}
});
ig.Debug = ig.Class.extend({
options: {},
panels: {},
numbers:{},
container: null,
panelMenu: null,
activePanel: null,
debugTime: 0,
debugTickAvg: 0.016,
debugRealTime: Date.now(),
init: function() {
// Inject the Stylesheet
var style = ig.$new('link');
style.rel = 'stylesheet';
style.type = 'text/css';
style.href = 'lib/impact/debug/debug.css';
ig.$('body')[0].appendChild( style );
// Create the Debug Container
this.container = ig.$new('div');
this.container.className ='ig_debug';
ig.$('body')[0].appendChild( this.container );
// Create and add the Menu Container
this.panelMenu = ig.$new('div');
this.panelMenu.innerHTML = '<div class="ig_debug_head">Impact.Debug:</div>';
this.panelMenu.className ='ig_debug_panel_menu';
this.container.appendChild( this.panelMenu );
// Create and add the Stats Container
this.numberContainer = ig.$new('div');
this.numberContainer.className ='ig_debug_stats';
this.panelMenu.appendChild( this.numberContainer );
// Set ig.log() and ig.show()
if( window.console && window.console.log ) {
ig.log = window.console.log.bind(window.console);
}
ig.show = this.showNumber.bind(this);
},
addNumber: function( name, width ) {
var number = ig.$new('span');
this.numberContainer.appendChild( number );
this.numberContainer.appendChild( document.createTextNode(name) );
this.numbers[name] = number;
},
showNumber: function( name, number, width ) {
if( !this.numbers[name] ) {
this.addNumber( name, width );
}
this.numbers[name].textContent = number;
},
addPanel: function( panelDef ) {
// Create the panel and options
var panel = new (panelDef.type)( panelDef.name, panelDef.label );
if( panelDef.options ) {
for( var i = 0; i < panelDef.options.length; i++ ) {
var opt = panelDef.options[i];
panel.addOption( new ig.DebugOption(opt.name, opt.object, opt.property) );
}
}
this.panels[ panel.name ] = panel;
panel.container.style.display = 'none';
this.container.appendChild( panel.container );
// Create the menu item
var menuItem = ig.$new('div');
menuItem.className = 'ig_debug_menu_item';
menuItem.textContent = panel.label;
menuItem.addEventListener(
'click',
(function(ev){ this.togglePanel(ev, panel); }).bind(this),
false
);
panel.menuItem = menuItem;
// Insert menu item in alphabetical order into the menu
var inserted = false;
for( var i = 1; i < this.panelMenu.childNodes.length; i++ ) {
var cn = this.panelMenu.childNodes[i];
if( cn.textContent > panel.label ) {
this.panelMenu.insertBefore( menuItem, cn );
inserted = true;
break;
}
}
if( !inserted ) {
// Not inserted? Append at the end!
this.panelMenu.appendChild( menuItem );
}
},
togglePanel: function( ev, panel ) {
if( panel != this.activePanel && this.activePanel ) {
this.activePanel.toggle( false );
this.activePanel.menuItem.className = 'ig_debug_menu_item';
this.activePanel = null;
}
var dsp = panel.container.style.display;
var active = (dsp != 'block');
panel.toggle( active );
ev.target.className = 'ig_debug_menu_item' + (active ? ' active' : '');
if( active ) {
this.activePanel = panel;
}
},
ready: function() {
for( var p in this.panels ) {
this.panels[p].ready();
}
},
beforeRun: function() {
var timeBeforeRun = Date.now();
this.debugTickAvg = this.debugTickAvg * 0.8 + (timeBeforeRun - this.debugRealTime) * 0.2;
this.debugRealTime = timeBeforeRun;
if( this.activePanel ) {
this.activePanel.beforeRun();
}
},
afterRun: function() {
var frameTime = Date.now() - this.debugRealTime;
var nextFrameDue = (1000/ig.system.fps) - frameTime;
this.debugTime = this.debugTime * 0.8 + frameTime * 0.2;
if( this.activePanel ) {
this.activePanel.afterRun();
}
this.showNumber( 'ms', this.debugTime.toFixed(2) );
this.showNumber( 'fps', Math.round(1000/this.debugTickAvg) );
this.showNumber( 'draws', ig.Image.drawCount );
if( ig.game && ig.game.entities ) {
this.showNumber( 'entities', ig.game.entities.length );
}
ig.Image.drawCount = 0;
}
});
ig.DebugPanel = ig.Class.extend({
active: false,
container: null,
options: [],
panels: [],
label: '',
name: '',
init: function( name, label ) {
this.name = name;
this.label = label;
this.container = ig.$new('div');
this.container.className = 'ig_debug_panel ' + this.name;
},
toggle: function( active ) {
this.active = active;
this.container.style.display = active ? 'block' : 'none';
},
addPanel: function( panel ) {
this.panels.push( panel );
this.container.appendChild( panel.container );
},
addOption: function( option ) {
this.options.push( option );
this.container.appendChild( option.container );
},
ready: function(){},
beforeRun: function(){},
afterRun: function(){}
});
ig.DebugOption = ig.Class.extend({
name: '',
labelName: '',
className: 'ig_debug_option',
label: null,
mark: null,
container: null,
active: false,
colors: {
enabled: '#fff',
disabled: '#444'
},
init: function( name, object, property ) {
this.name = name;
this.object = object;
this.property = property;
this.active = this.object[this.property];
this.container = ig.$new('div');
this.container.className = 'ig_debug_option';
this.label = ig.$new('span');
this.label.className = 'ig_debug_label';
this.label.textContent = this.name;
this.mark = ig.$new('span');
this.mark.className = 'ig_debug_label_mark';
this.container.appendChild( this.mark );
this.container.appendChild( this.label );
this.container.addEventListener( 'click', this.click.bind(this), false );
this.setLabel();
},
setLabel: function() {
this.mark.style.backgroundColor = this.active ? this.colors.enabled : this.colors.disabled;
},
click: function( ev ) {
this.active = !this.active;
this.object[this.property] = this.active;
this.setLabel();
ev.stopPropagation();
ev.preventDefault();
return false;
}
});
// Create the debug instance!
ig.debug = new ig.Debug();
});

415
dev/lib/impact/entity.js Executable file
View file

@ -0,0 +1,415 @@
ig.module(
'impact.entity'
)
.requires(
'impact.animation',
'impact.impact'
)
.defines(function(){
ig.Entity = ig.Class.extend({
id: 0,
settings: {},
size: {x: 16, y:16},
offset: {x: 0, y: 0},
pos: {x: 0, y:0},
last: {x: 0, y:0},
vel: {x: 0, y: 0},
accel: {x: 0, y: 0},
friction: {x: 0, y: 0},
maxVel: {x: 100, y: 100},
zIndex: 0,
gravityFactor: 1,
standing: false,
bounciness: 0,
minBounceVelocity: 40,
anims: {},
animSheet: null,
currentAnim: null,
health: 10,
type: 0, // TYPE.NONE
checkAgainst: 0, // TYPE.NONE
collides: 0, // COLLIDES.NEVER
_killed: false,
slopeStanding: {min: (44).toRad(), max: (136).toRad() },
init: function( x, y, settings ) {
this.id = ++ig.Entity._lastId;
this.pos.x = x;
this.pos.y = y;
ig.merge( this, settings );
},
addAnim: function( name, frameTime, sequence, stop ) {
if( !this.animSheet ) {
throw( 'No animSheet to add the animation '+name+' to.' );
}
var a = new ig.Animation( this.animSheet, frameTime, sequence, stop );
this.anims[name] = a;
if( !this.currentAnim ) {
this.currentAnim = a;
}
return a;
},
update: function() {
this.last.x = this.pos.x;
this.last.y = this.pos.y;
this.vel.y += ig.game.gravity * ig.system.tick * this.gravityFactor;
this.vel.x = this.getNewVelocity( this.vel.x, this.accel.x, this.friction.x, this.maxVel.x );
this.vel.y = this.getNewVelocity( this.vel.y, this.accel.y, this.friction.y, this.maxVel.y );
// movement & collision
var mx = this.vel.x * ig.system.tick;
var my = this.vel.y * ig.system.tick;
var res = ig.game.collisionMap.trace(
this.pos.x, this.pos.y, mx, my, this.size.x, this.size.y
);
this.handleMovementTrace( res );
if( this.currentAnim ) {
this.currentAnim.update();
}
},
getNewVelocity: function( vel, accel, friction, max ) {
if( accel ) {
return ( vel + accel * ig.system.tick ).limit( -max, max );
}
else if( friction ) {
var delta = friction * ig.system.tick;
if( vel - delta > 0) {
return vel - delta;
}
else if( vel + delta < 0 ) {
return vel + delta;
}
else {
return 0;
}
}
return vel.limit( -max, max );
},
handleMovementTrace: function( res ) {
this.standing = false;
if( res.collision.y ) {
if( this.bounciness > 0 && Math.abs(this.vel.y) > this.minBounceVelocity ) {
this.vel.y *= -this.bounciness;
}
else {
if( this.vel.y > 0 ) {
this.standing = true;
}
this.vel.y = 0;
}
}
if( res.collision.x ) {
if( this.bounciness > 0 && Math.abs(this.vel.x) > this.minBounceVelocity ) {
this.vel.x *= -this.bounciness;
}
else {
this.vel.x = 0;
}
}
if( res.collision.slope ) {
var s = res.collision.slope;
if( this.bounciness > 0 ) {
var proj = this.vel.x * s.nx + this.vel.y * s.ny;
this.vel.x -= s.nx * proj * 2;
this.vel.y -= s.ny * proj * 2;
this.vel.x *= this.bounciness;
this.vel.y *= this.bounciness;
}
else {
var lengthSquared = s.x * s.x + s.y * s.y;
var dot = (this.vel.x * s.x + this.vel.y * s.y)/lengthSquared;
this.vel.x = s.x * dot;
this.vel.y = s.y * dot;
var angle = Math.atan2( s.x, s.y );
if( angle > this.slopeStanding.min && angle < this.slopeStanding.max ) {
this.standing = true;
}
}
}
this.pos = res.pos;
},
draw: function() {
if( this.currentAnim ) {
this.currentAnim.draw(
this.pos.x - this.offset.x - ig.game._rscreen.x,
this.pos.y - this.offset.y - ig.game._rscreen.y
);
}
},
kill: function() {
ig.game.removeEntity( this );
},
receiveDamage: function( amount, from ) {
this.health -= amount;
if( this.health <= 0 ) {
this.kill();
}
},
touches: function( other ) {
return !(
this.pos.x >= other.pos.x + other.size.x ||
this.pos.x + this.size.x <= other.pos.x ||
this.pos.y >= other.pos.y + other.size.y ||
this.pos.y + this.size.y <= other.pos.y
);
},
distanceTo: function( other ) {
var xd = (this.pos.x + this.size.x/2) - (other.pos.x + other.size.x/2);
var yd = (this.pos.y + this.size.y/2) - (other.pos.y + other.size.y/2);
return Math.sqrt( xd*xd + yd*yd );
},
angleTo: function( other ) {
return Math.atan2(
(other.pos.y + other.size.y/2) - (this.pos.y + this.size.y/2),
(other.pos.x + other.size.x/2) - (this.pos.x + this.size.x/2)
);
},
check: function( other ) {},
collideWith: function( other, axis ) {},
ready: function() {}
});
// Last used entity id; incremented with each spawned entity
ig.Entity._lastId = 0;
// Collision Types - Determine if and how entities collide with each other
// In ACTIVE vs. LITE or FIXED vs. ANY collisions, only the "weak" entity moves,
// while the other one stays fixed. In ACTIVE vs. ACTIVE and ACTIVE vs. PASSIVE
// collisions, both entities are moved. LITE or PASSIVE entities don't collide
// with other LITE or PASSIVE entities at all. The behaiviour for FIXED vs.
// FIXED collisions is undefined.
ig.Entity.COLLIDES = {
NEVER: 0,
LITE: 1,
PASSIVE: 2,
ACTIVE: 4,
FIXED: 8
};
// Entity Types - used for checks
ig.Entity.TYPE = {
NONE: 0,
A: 1,
B: 2,
BOTH: 3
};
ig.Entity.checkPair = function( a, b ) {
// Do these entities want checks?
if( a.checkAgainst & b.type ) {
a.check( b );
}
if( b.checkAgainst & a.type ) {
b.check( a );
}
// If this pair allows collision, solve it! At least one entity must
// collide ACTIVE or FIXED, while the other one must not collide NEVER.
if(
a.collides && b.collides &&
a.collides + b.collides > ig.Entity.COLLIDES.ACTIVE
) {
ig.Entity.solveCollision( a, b );
}
};
ig.Entity.solveCollision = function( a, b ) {
// If one entity is FIXED, or the other entity is LITE, the weak
// (FIXED/NON-LITE) entity won't move in collision response
var weak = null;
if(
a.collides == ig.Entity.COLLIDES.LITE ||
b.collides == ig.Entity.COLLIDES.FIXED
) {
weak = a;
}
else if(
b.collides == ig.Entity.COLLIDES.LITE ||
a.collides == ig.Entity.COLLIDES.FIXED
) {
weak = b;
}
// Did they already overlap on the X-axis in the last frame? If so,
// this must be a vertical collision!
if(
a.last.x + a.size.x > b.last.x &&
a.last.x < b.last.x + b.size.x
) {
// Which one is on top?
if( a.last.y < b.last.y ) {
ig.Entity.seperateOnYAxis( a, b, weak );
}
else {
ig.Entity.seperateOnYAxis( b, a, weak );
}
a.collideWith( b, 'y' );
b.collideWith( a, 'y' );
}
// Horizontal collision
else if(
a.last.y + a.size.y > b.last.y &&
a.last.y < b.last.y + b.size.y
){
// Which one is on the left?
if( a.last.x < b.last.x ) {
ig.Entity.seperateOnXAxis( a, b, weak );
}
else {
ig.Entity.seperateOnXAxis( b, a, weak );
}
a.collideWith( b, 'x' );
b.collideWith( a, 'x' );
}
};
// FIXME: This is a mess. Instead of doing all the movements here, the entities
// should get notified of the collision (with all details) and resolve it
// themselfs.
ig.Entity.seperateOnXAxis = function( left, right, weak ) {
var nudge = (left.pos.x + left.size.x - right.pos.x);
// We have a weak entity, so just move this one
if( weak ) {
var strong = left === weak ? right : left;
weak.vel.x = -weak.vel.x * weak.bounciness + strong.vel.x;
var resWeak = ig.game.collisionMap.trace(
weak.pos.x, weak.pos.y, weak == left ? -nudge : nudge, 0, weak.size.x, weak.size.y
);
weak.pos.x = resWeak.pos.x;
}
// Normal collision - both move
else {
var v2 = (left.vel.x - right.vel.x)/2;
left.vel.x = -v2;
right.vel.x = v2;
var resLeft = ig.game.collisionMap.trace(
left.pos.x, left.pos.y, -nudge/2, 0, left.size.x, left.size.y
);
left.pos.x = Math.floor(resLeft.pos.x);
var resRight = ig.game.collisionMap.trace(
right.pos.x, right.pos.y, nudge/2, 0, right.size.x, right.size.y
);
right.pos.x = Math.ceil(resRight.pos.x);
}
};
ig.Entity.seperateOnYAxis = function( top, bottom, weak ) {
var nudge = (top.pos.y + top.size.y - bottom.pos.y);
// We have a weak entity, so just move this one
if( weak ) {
var strong = top === weak ? bottom : top;
weak.vel.y = -weak.vel.y * weak.bounciness + strong.vel.y;
// Riding on a platform?
var nudgeX = 0;
if( weak == top && Math.abs(weak.vel.y - strong.vel.y) < weak.minBounceVelocity ) {
weak.standing = true;
nudgeX = strong.vel.x * ig.system.tick;
}
var resWeak = ig.game.collisionMap.trace(
weak.pos.x, weak.pos.y, nudgeX, weak == top ? -nudge : nudge, weak.size.x, weak.size.y
);
weak.pos.y = resWeak.pos.y;
weak.pos.x = resWeak.pos.x;
}
// Bottom entity is standing - just bounce the top one
else if( ig.game.gravity && (bottom.standing || top.vel.y > 0) ) {
var resTop = ig.game.collisionMap.trace(
top.pos.x, top.pos.y, 0, -(top.pos.y + top.size.y - bottom.pos.y), top.size.x, top.size.y
);
top.pos.y = resTop.pos.y;
if( top.bounciness > 0 && top.vel.y > top.minBounceVelocity ) {
top.vel.y *= -top.bounciness;
}
else {
top.standing = true;
top.vel.y = 0;
}
}
// Normal collision - both move
else {
var v2 = (top.vel.y - bottom.vel.y)/2;
top.vel.y = -v2;
bottom.vel.y = v2;
var nudgeX = bottom.vel.x * ig.system.tick;
var resTop = ig.game.collisionMap.trace(
top.pos.x, top.pos.y, nudgeX, -nudge/2, top.size.x, top.size.y
);
top.pos.y = resTop.pos.y;
var resBottom = ig.game.collisionMap.trace(
bottom.pos.x, bottom.pos.y, 0, nudge/2, bottom.size.x, bottom.size.y
);
bottom.pos.y = resBottom.pos.y;
}
};
});

129
dev/lib/impact/font.js Executable file
View file

@ -0,0 +1,129 @@
ig.module(
'impact.font'
)
.requires(
'impact.image'
)
.defines(function(){
ig.Font = ig.Image.extend({
widthMap: [],
indices: [],
firstChar: 32,
height: 0,
onload: function( ev ) {
this._loadMetrics( this.data );
this.parent( ev );
},
widthForString: function( s ) {
var width = 0;
for( var i = 0; i < s.length; i++ ) {
width += this.widthMap[s.charCodeAt(i) - this.firstChar] + 1;
}
return width;
},
draw: function( text, x, y, align ) {
if( typeof(text) != 'string' ) {
text = text.toString();
}
// Multiline?
if( text.indexOf('\n') !== -1 ) {
var lines = text.split( '\n' );
for( i = 0; i < lines.length; i++ ) {
this.draw( lines[i], x, y + i * this.height, align );
}
return;
}
if( align == ig.Font.ALIGN.RIGHT || align == ig.Font.ALIGN.CENTER ) {
var width = 0;
for( var i = 0; i < text.length; i++ ) {
var c = text.charCodeAt(i);
width += this.widthMap[c - this.firstChar] + 1;
}
x -= align == ig.Font.ALIGN.CENTER ? width/2 : width;
}
for( var i = 0; i < text.length; i++ ) {
var c = text.charCodeAt(i);
x += this._drawChar( c - this.firstChar, x, y );
}
ig.Image.drawCount += text.length;
},
_drawChar: function( c, targetX, targetY ) {
if( !this.loaded || c < 0 || c >= this.indices.length ) { return 0; }
var scale = ig.system.scale;
var charX = this.indices[c] * scale;
var charY = 0;
var charWidth = this.widthMap[c] * scale;
var charHeight = (this.height-2) * scale;
ig.system.context.drawImage(
this.data,
charX, charY,
charWidth, charHeight,
ig.system.getDrawPos(targetX), ig.system.getDrawPos(targetY),
charWidth, charHeight
);
return this.widthMap[c] + 1;
},
_loadMetrics: function( image ) {
// Draw the bottommost line of this font image into an offscreen canvas
// and analyze it pixel by pixel.
// A run of non-transparent pixels represents a character and its width
this.height = image.height-1;
this.widthMap = [];
this.indices = [];
var canvas = ig.$new('canvas');
canvas.width = image.width;
canvas.height = image.height;
var ctx = canvas.getContext('2d');
ctx.drawImage( image, 0, 0 );
var px = ctx.getImageData(0, image.height-1, image.width, 1);
var currentChar = 0;
var currentWidth = 0;
for( var x = 0; x < image.width; x++ ) {
var index = x * 4 + 3; // alpha component of this pixel
if( px.data[index] != 0 ) {
currentWidth++;
}
else if( px.data[index] == 0 && currentWidth ) {
this.widthMap.push( currentWidth );
this.indices.push( x-currentWidth );
currentChar++;
currentWidth = 0;
}
}
this.widthMap.push( currentWidth );
this.indices.push( x-currentWidth );
}
});
ig.Font.ALIGN = {
LEFT: 0,
RIGHT: 1,
CENTER: 2
};
});

304
dev/lib/impact/game.js Executable file
View file

@ -0,0 +1,304 @@
ig.module(
'impact.game'
)
.requires(
'impact.impact',
'impact.entity',
'impact.collision-map',
'impact.background-map'
)
.defines(function(){
ig.Game = ig.Class.extend({
clearColor: '#000000',
gravity: 0,
screen: {x: 0, y: 0},
_rscreen: {x: 0, y: 0},
entities: [],
namedEntities: {},
collisionMap: ig.CollisionMap.staticNoCollision,
backgroundMaps: [],
backgroundAnims: {},
autoSort: false,
sortBy: null,
cellSize: 64,
_deferredKill: [],
_levelToLoad: null,
_doSortEntities: false,
staticInstantiate: function() {
this.sortBy = ig.Game.SORT.Z_INDEX;
ig.game = this;
return null;
},
loadLevel: function( data ) {
this.screen = {x: 0, y: 0};
// Entities
this.entities = [];
this.namedEntities = {};
for( var i = 0; i < data.entities.length; i++ ) {
var ent = data.entities[i];
this.spawnEntity( ent.type, ent.x, ent.y, ent.settings );
}
this.sortEntities();
// Map Layer
this.collisionMap = ig.CollisionMap.staticNoCollision;
this.backgroundMaps = [];
for( var i = 0; i < data.layer.length; i++ ) {
var ld = data.layer[i];
if( ld.name == 'collision' ) {
this.collisionMap = new ig.CollisionMap(ld.tilesize, ld.data );
}
else {
var newMap = new ig.BackgroundMap(ld.tilesize, ld.data, ld.tilesetName);
newMap.anims = this.backgroundAnims[ld.tilesetName] || {};
newMap.repeat = ld.repeat;
newMap.distance = ld.distance;
newMap.foreground = !!ld.foreground;
newMap.preRender = !!ld.preRender;
this.backgroundMaps.push( newMap );
}
}
// Call post-init ready function on all entities
for( var i = 0; i < this.entities.length; i++ ) {
this.entities[i].ready();
}
},
loadLevelDeferred: function( data ) {
this._levelToLoad = data;
},
getEntityByName: function( name ) {
return this.namedEntities[name];
},
getEntitiesByType: function( type ) {
var entityClass = typeof(type) === 'string'
? ig.global[type]
: type;
var a = [];
for( var i = 0; i < this.entities.length; i++ ) {
var ent = this.entities[i];
if( ent instanceof entityClass && !ent._killed ) {
a.push( ent );
}
}
return a;
},
spawnEntity: function( type, x, y, settings ) {
var entityClass = typeof(type) === 'string'
? ig.global[type]
: type;
if( !entityClass ) {
throw("Can't spawn entity of type " + type);
}
var ent = new (entityClass)( x, y, settings || {} );
this.entities.push( ent );
if( ent.name ) {
this.namedEntities[ent.name] = ent;
}
return ent;
},
sortEntities: function() {
this.entities.sort( this.sortBy );
},
sortEntitiesDeferred: function() {
this._doSortEntities = true;
},
removeEntity: function( ent ) {
// Remove this entity from the named entities
if( ent.name ) {
delete this.namedEntities[ent.name];
}
// We can not remove the entity from the entities[] array in the midst
// of an update cycle, so remember all killed entities and remove
// them later.
// Also make sure this entity doesn't collide anymore and won't get
// updated or checked
ent._killed = true;
ent.checkAgainst = ig.Entity.TYPE.NONE;
ent.collides = ig.Entity.COLLIDES.NEVER;
this._deferredKill.push( ent );
},
run: function() {
this.update();
this.draw();
},
update: function(){
// load new level?
if( this._levelToLoad ) {
this.loadLevel( this._levelToLoad );
this._levelToLoad = null;
}
// sort entities?
if( this._doSortEntities || this.autoSort ) {
this.sortEntities();
this._doSortEntities = false;
}
// update entities
this.updateEntities();
this.checkEntities();
// remove all killed entities
for( var i = 0; i < this._deferredKill.length; i++ ) {
this.entities.erase( this._deferredKill[i] );
}
this._deferredKill = [];
// update background animations
for( var tileset in this.backgroundAnims ) {
var anims = this.backgroundAnims[tileset];
for( var a in anims ) {
anims[a].update();
}
}
},
updateEntities: function() {
for( var i = 0; i < this.entities.length; i++ ) {
var ent = this.entities[i];
if( !ent._killed ) {
ent.update();
}
}
},
draw: function(){
if( this.clearColor ) {
ig.system.clear( this.clearColor );
}
this._rscreen.x = Math.round(this.screen.x * ig.system.scale)/ig.system.scale;
this._rscreen.y = Math.round(this.screen.y * ig.system.scale)/ig.system.scale;
var mapIndex;
for( mapIndex = 0; mapIndex < this.backgroundMaps.length; mapIndex++ ) {
var map = this.backgroundMaps[mapIndex];
if( map.foreground ) {
// All foreground layers are drawn after the entities
break;
}
map.setScreenPos( this.screen.x, this.screen.y );
map.draw();
}
this.drawEntities();
for( mapIndex; mapIndex < this.backgroundMaps.length; mapIndex++ ) {
var map = this.backgroundMaps[mapIndex];
map.setScreenPos( this.screen.x, this.screen.y );
map.draw();
}
},
drawEntities: function() {
for( var i = 0; i < this.entities.length; i++ ) {
this.entities[i].draw();
}
},
checkEntities: function() {
// Insert all entities into a spatial hash and check them against any
// other entity that already resides in the same cell. Entities that are
// bigger than a single cell, are inserted into each one they intersect
// with.
// A list of entities, which the current one was already checked with,
// is maintained for each entity.
var hash = {};
for( var e = 0; e < this.entities.length; e++ ) {
var entity = this.entities[e];
// Skip entities that don't check, don't get checked and don't collide
if(
entity.type == ig.Entity.TYPE.NONE &&
entity.checkAgainst == ig.Entity.TYPE.NONE &&
entity.collides == ig.Entity.COLLIDES.NEVER
) {
continue;
}
var checked = {},
xmin = Math.floor( entity.pos.x/this.cellSize ),
ymin = Math.floor( entity.pos.y/this.cellSize ),
xmax = Math.floor( (entity.pos.x+entity.size.x)/this.cellSize ) + 1,
ymax = Math.floor( (entity.pos.y+entity.size.y)/this.cellSize ) + 1;
for( var x = xmin; x < xmax; x++ ) {
for( var y = ymin; y < ymax; y++ ) {
// Current cell is empty - create it and insert!
if( !hash[x] ) {
hash[x] = {};
hash[x][y] = [entity];
}
else if( !hash[x][y] ) {
hash[x][y] = [entity];
}
// Check against each entity in this cell, then insert
else {
var cell = hash[x][y];
for( var c = 0; c < cell.length; c++ ) {
// Intersects and wasn't already checkd?
if( entity.touches(cell[c]) && !checked[cell[c].id] ) {
checked[cell[c].id] = true;
ig.Entity.checkPair( entity, cell[c] );
}
}
cell.push(entity);
}
} // end for y size
} // end for x size
} // end for entities
}
});
ig.Game.SORT = {
Z_INDEX: function( a, b ){ return a.zIndex - b.zIndex; },
POS_X: function( a, b ){ return a.pos.x - b.pos.x; },
POS_Y: function( a, b ){ return a.pos.y - b.pos.y; }
};
});

183
dev/lib/impact/image.js Executable file
View file

@ -0,0 +1,183 @@
ig.module(
'impact.image'
)
.defines(function(){
ig.Image = ig.Class.extend({
data: null,
width: 0,
height: 0,
loaded: false,
failed: false,
loadCallback: null,
path: '',
staticInstantiate: function( path ) {
return ig.Image.cache[path] || null;
},
init: function( path ) {
this.path = path;
this.load();
},
load: function( loadCallback ) {
if( this.loaded ) {
if( loadCallback ) {
loadCallback( this.path, true );
}
return;
}
else if( !this.loaded && ig.ready ) {
this.loadCallback = loadCallback || null;
this.data = new Image();
this.data.onload = this.onload.bind(this);
this.data.onerror = this.onerror.bind(this);
this.data.src = this.path + ig.nocache;
}
else {
ig.addResource( this );
}
ig.Image.cache[this.path] = this;
},
reload: function() {
this.loaded = false;
this.data = new Image();
this.data.onload = this.onload.bind(this);
this.data.src = this.path + '?' + Date.now();
},
onload: function( event ) {
this.width = this.data.width;
this.height = this.data.height;
if( ig.system.scale != 1 ) {
this.resize( ig.system.scale );
}
this.loaded = true;
if( this.loadCallback ) {
this.loadCallback( this.path, true );
}
},
onerror: function( event ) {
this.failed = true;
if( this.loadCallback ) {
this.loadCallback( this.path, false );
}
},
resize: function( scale ) {
// Nearest-Neighbor scaling
// The original image is drawn into an offscreen canvas of the same size
// and copied into another offscreen canvas with the new size.
// The scaled offscreen canvas becomes the image (data) of this object.
var widthScaled = this.width * scale;
var heightScaled = this.height * scale;
var orig = ig.$new('canvas');
orig.width = this.width;
orig.height = this.height;
var origCtx = orig.getContext('2d');
origCtx.drawImage( this.data, 0, 0, this.width, this.height, 0, 0, this.width, this.height );
var origPixels = origCtx.getImageData(0, 0, this.width, this.height);
var scaled = ig.$new('canvas');
scaled.width = widthScaled;
scaled.height = heightScaled;
var scaledCtx = scaled.getContext('2d');
var scaledPixels = scaledCtx.getImageData( 0, 0, widthScaled, heightScaled );
for( var y = 0; y < heightScaled; y++ ) {
for( var x = 0; x < widthScaled; x++ ) {
var index = (Math.floor(y / scale) * this.width + Math.floor(x / scale)) * 4;
var indexScaled = (y * widthScaled + x) * 4;
scaledPixels.data[ indexScaled ] = origPixels.data[ index ];
scaledPixels.data[ indexScaled+1 ] = origPixels.data[ index+1 ];
scaledPixels.data[ indexScaled+2 ] = origPixels.data[ index+2 ];
scaledPixels.data[ indexScaled+3 ] = origPixels.data[ index+3 ];
}
}
scaledCtx.putImageData( scaledPixels, 0, 0 );
this.data = scaled;
},
draw: function( targetX, targetY, sourceX, sourceY, width, height ) {
if( !this.loaded ) { return; }
var scale = ig.system.scale;
sourceX = sourceX ? sourceX * scale : 0;
sourceY = sourceY ? sourceY * scale : 0;
width = (width ? width : this.width) * scale;
height = (height ? height : this.height) * scale;
ig.system.context.drawImage(
this.data, sourceX, sourceY, width, height,
ig.system.getDrawPos(targetX),
ig.system.getDrawPos(targetY),
width, height
);
ig.Image.drawCount++;
},
drawTile: function( targetX, targetY, tile, tileWidth, tileHeight, flipX, flipY ) {
tileHeight = tileHeight ? tileHeight : tileWidth;
if( !this.loaded || tileWidth > this.width || tileHeight > this.height ) { return; }
var scale = ig.system.scale;
var tileWidthScaled = tileWidth * scale;
var tileHeightScaled = tileHeight * scale;
var scaleX = flipX ? -1 : 1;
var scaleY = flipY ? -1 : 1;
if( flipX || flipY ) {
ig.system.context.save();
ig.system.context.scale( scaleX, scaleY );
}
ig.system.context.drawImage(
this.data,
( Math.floor(tile * tileWidth) % this.width ) * scale,
( Math.floor(tile * tileWidth / this.width) * tileHeight ) * scale,
tileWidthScaled,
tileHeightScaled,
ig.system.getDrawPos(targetX) * scaleX - (flipX ? tileWidthScaled : 0),
ig.system.getDrawPos(targetY) * scaleY - (flipY ? tileHeightScaled : 0),
tileWidthScaled,
tileHeightScaled
);
if( flipX || flipY ) {
ig.system.context.restore();
}
ig.Image.drawCount++;
}
});
ig.Image.drawCount = 0;
ig.Image.cache = {};
ig.Image.reloadCache = function() {
for( path in ig.Image.cache ) {
ig.Image.cache[path].reload();
}
};
});

476
dev/lib/impact/impact.js Executable file
View file

@ -0,0 +1,476 @@
// -----------------------------------------------------------------------------
// Impact Game Library 1.19
// http://impactjs.com/
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// Native Object extensions
Number.prototype.map = function(istart, istop, ostart, ostop) {
return ostart + (ostop - ostart) * ((this - istart) / (istop - istart));
};
Number.prototype.limit = function(min, max) {
return Math.min(max, Math.max(min, this));
};
Number.prototype.round = function(precision) {
precision = Math.pow(10, precision || 0);
return Math.round(this * precision) / precision;
};
Number.prototype.floor = function() {
return Math.floor(this);
};
Number.prototype.ceil = function() {
return Math.ceil(this);
};
Number.prototype.toInt = function() {
return (this | 0);
};
Number.prototype.toRad = function() {
return (this / 180) * Math.PI;
};
Number.prototype.toDeg = function() {
return (this * 180) / Math.PI;
};
Array.prototype.erase = function(item) {
for( var i = this.length; i--; ) {
if( this[i] === item ) {
this.splice(i, 1);
}
}
return this;
};
Array.prototype.random = function() {
return this[ Math.floor(Math.random() * this.length) ];
};
Function.prototype.bind = function(bind) {
var self = this;
return function(){
var args = Array.prototype.slice.call(arguments);
return self.apply(bind || null, args);
};
};
// -----------------------------------------------------------------------------
// ig Namespace
(function(window){
window.ig = {
game: null,
debug: null,
version: '1.19',
global: window,
modules: {},
resources: [],
ready: false,
baked: false,
nocache: '',
ua: {},
lib: 'lib/',
_current: null,
_loadQueue: [],
_waitForOnload: 0,
$: function( selector ) {
return selector.charAt(0) == '#'
? document.getElementById( selector.substr(1) )
: document.getElementsByTagName( selector );
},
$new: function( name ) {
return document.createElement( name );
},
copy: function( object ) {
if(
!object || typeof(object) != 'object' ||
object instanceof HTMLElement ||
object instanceof ig.Class
) {
return object;
}
else if( object instanceof Array ) {
var c = [];
for( var i = 0, l = object.length; i < l; i++) {
c[i] = ig.copy(object[i]);
}
return c;
}
else {
var c = {};
for( var i in object ) {
c[i] = ig.copy(object[i]);
}
return c;
}
},
merge: function( original, extended ) {
for( var key in extended ) {
var ext = extended[key];
if(
typeof(ext) != 'object' ||
ext instanceof HTMLElement ||
ext instanceof ig.Class
) {
original[key] = ext;
}
else {
if( !original[key] || typeof(original[key]) != 'object' ) {
original[key] = (ext instanceof Array) ? [] : {};
}
ig.merge( original[key], ext );
}
}
return original;
},
ksort: function( obj ) {
if( !obj || typeof(obj) != 'object' ) {
return [];
}
var keys = [], values = [];
for( var i in obj ) {
keys.push(i);
}
keys.sort();
for( var i = 0; i < keys.length; i++ ) {
values.push( obj[keys[i]] );
}
return values;
},
module: function( name ) {
if( ig._current ) {
throw( "Module '"+ig._current.name+"' defines nothing" );
}
if( ig.modules[name] && ig.modules[name].body ) {
throw( "Module '"+name+"' is already defined" );
}
ig._current = {name: name, requires: [], loaded: false, body: null};
ig.modules[name] = ig._current;
ig._loadQueue.push(ig._current);
ig._initDOMReady();
return ig;
},
requires: function() {
ig._current.requires = Array.prototype.slice.call(arguments);
return ig;
},
defines: function( body ) {
name = ig._current.name;
ig._current.body = body;
ig._current = null;
ig._execModules();
},
addResource: function( resource ) {
ig.resources.push( resource );
},
setNocache: function( set ) {
ig.nocache = set
? '?' + Date.now()
: '';
},
// Stubs for ig.Debug
log: function() {},
show: function( name, number ) {},
mark: function( msg, color ) {},
_loadScript: function( name, requiredFrom ) {
ig.modules[name] = {name: name, requires:[], loaded: false, body: null};
ig._waitForOnload++;
var path = ig.lib + name.replace(/\./g, '/') + '.js' + ig.nocache;
var script = ig.$new('script');
script.type = 'text/javascript';
script.src = path;
script.onload = function() {
ig._waitForOnload--;
ig._execModules();
};
script.onerror = function() {
throw(
'Failed to load module '+name+' at ' + path + ' ' +
'required from ' + requiredFrom
);
};
ig.$('head')[0].appendChild(script);
},
_execModules: function() {
var modulesLoaded = false;
for( var i = 0; i < ig._loadQueue.length; i++ ) {
var m = ig._loadQueue[i];
var dependenciesLoaded = true;
for( var j = 0; j < m.requires.length; j++ ) {
var name = m.requires[j];
if( !ig.modules[name] ) {
dependenciesLoaded = false;
ig._loadScript( name, m.name );
}
else if( !ig.modules[name].loaded ) {
dependenciesLoaded = false;
}
}
if( dependenciesLoaded && m.body ) {
ig._loadQueue.splice(i, 1);
m.loaded = true;
m.body();
modulesLoaded = true;
i--;
}
}
if( modulesLoaded ) {
ig._execModules();
}
// No modules executed, no more files to load but loadQueue not empty?
// Must be some unresolved dependencies!
else if( !ig.baked && ig._waitForOnload == 0 && ig._loadQueue.length != 0 ) {
var unresolved = [];
for( var i = 0; i < ig._loadQueue.length; i++ ) {
// Which dependencies aren't loaded?
var unloaded = [];
var requires = ig._loadQueue[i].requires;
for( var j = 0; j < requires.length; j++ ) {
var m = ig.modules[ requires[j] ];
if( !m || !m.loaded ) {
unloaded.push( requires[j] );
}
}
unresolved.push( ig._loadQueue[i].name + ' (requires: ' + unloaded.join(', ') + ')');
}
throw(
'Unresolved (circular?) dependencies. ' +
"Most likely there's a name/path mismatch for one of the listed modules:\n" +
unresolved.join('\n')
);
}
},
_DOMReady: function() {
if( !ig.modules['dom.ready'].loaded ) {
if ( !document.body ) {
return setTimeout( ig._DOMReady, 13 );
}
ig.modules['dom.ready'].loaded = true;
ig._waitForOnload--;
ig._execModules();
}
return 0;
},
_boot: function() {
if( document.location.href.match(/\?nocache/) ) {
ig.setNocache( true );
}
// Probe user agent string
ig.ua.pixelRatio = window.devicePixelRatio || 1;
ig.ua.viewport = {
width: window.innerWidth,
height: window.innerHeight
};
ig.ua.screen = {
width: window.screen.availWidth * ig.ua.pixelRatio,
height: window.screen.availHeight * ig.ua.pixelRatio
};
ig.ua.iPhone = /iPhone/i.test(navigator.userAgent);
ig.ua.iPhone4 = (ig.ua.iPhone && ig.ua.pixelRatio == 2);
ig.ua.iPad = /iPad/i.test(navigator.userAgent);
ig.ua.android = /android/i.test(navigator.userAgent);
ig.ua.iOS = ig.ua.iPhone || ig.ua.iPad;
ig.ua.mobile = ig.ua.iOS || ig.ua.android;
},
_initDOMReady: function() {
if( ig.modules['dom.ready'] ) { return; }
ig._boot();
ig.modules['dom.ready'] = { requires: [], loaded: false, body: null };
ig._waitForOnload++;
if ( document.readyState === 'complete' ) {
ig._DOMReady();
}
else {
document.addEventListener( 'DOMContentLoaded', ig._DOMReady, false );
window.addEventListener( 'load', ig._DOMReady, false );
}
}
};
// -----------------------------------------------------------------------------
// Class object based on John Resigs code; inspired by base2 and Prototype
// http://ejohn.org/blog/simple-javascript-inheritance/
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\bparent\b/ : /.*/;
window.ig.Class = function(){};
var inject = function(prop) {
var proto = this.prototype;
var parent = {};
for( var name in prop ) {
if(
typeof(prop[name]) == "function" &&
typeof(proto[name]) == "function" &&
fnTest.test(prop[name])
) {
parent[name] = proto[name]; // save original function
proto[name] = (function(name, fn){
return function() {
var tmp = this.parent;
this.parent = parent[name];
var ret = fn.apply(this, arguments);
this.parent = tmp;
return ret;
};
})( name, prop[name] );
}
else {
proto[name] = prop[name];
}
}
};
window.ig.Class.extend = function(prop) {
var parent = this.prototype;
initializing = true;
var prototype = new this();
initializing = false;
for( var name in prop ) {
if(
typeof(prop[name]) == "function" &&
typeof(parent[name]) == "function" &&
fnTest.test(prop[name])
) {
prototype[name] = (function(name, fn){
return function() {
var tmp = this.parent;
this.parent = parent[name];
var ret = fn.apply(this, arguments);
this.parent = tmp;
return ret;
};
})( name, prop[name] );
}
else {
prototype[name] = prop[name];
}
}
function Class() {
if( !initializing ) {
// If this class has a staticInstantiate method, invoke it
// and check if we got something back. If not, the normal
// constructor (init) is called.
if( this.staticInstantiate ) {
var obj = this.staticInstantiate.apply(this, arguments);
if( obj ) {
return obj;
}
}
for( var p in this ) {
if( typeof(this[p]) == 'object' ) {
this[p] = ig.copy(this[p]); // deep copy!
}
}
if( this.init ) {
this.init.apply(this, arguments);
}
}
return this;
}
Class.prototype = prototype;
Class.constructor = Class;
Class.extend = arguments.callee;
Class.inject = inject;
return Class;
};
})(window);
// -----------------------------------------------------------------------------
// The main() function creates the system, input, sound and game objects,
// creates a preloader and starts the run loop
ig.module(
'impact.impact'
)
.requires(
'dom.ready',
'impact.loader',
'impact.system',
'impact.input',
'impact.sound'
)
.defines(function(){
ig.main = function( canvasId, gameClass, fps, width, height, scale, loaderClass ) {
ig.system = new ig.System( canvasId, fps, width, height, scale || 1 );
ig.input = new ig.Input();
ig.soundManager = new ig.SoundManager();
ig.music = new ig.Music();
ig.ready = true;
var loader = new (loaderClass || ig.Loader)( gameClass, ig.resources );
loader.load();
};
});

308
dev/lib/impact/input.js Executable file
View file

@ -0,0 +1,308 @@
ig.module(
'impact.input'
)
.defines(function(){
ig.KEY = {
'MOUSE1': -1,
'MOUSE2': -3,
'MWHEEL_UP': -4,
'MWHEEL_DOWN': -5,
'BACKSPACE': 8,
'TAB': 9,
'ENTER': 13,
'PAUSE': 19,
'CAPS': 20,
'ESC': 27,
'SPACE': 32,
'PAGE_UP': 33,
'PAGE_DOWN': 34,
'END': 35,
'HOME': 36,
'LEFT_ARROW': 37,
'UP_ARROW': 38,
'RIGHT_ARROW': 39,
'DOWN_ARROW': 40,
'INSERT': 45,
'DELETE': 46,
'_0': 48,
'_1': 49,
'_2': 50,
'_3': 51,
'_4': 52,
'_5': 53,
'_6': 54,
'_7': 55,
'_8': 56,
'_9': 57,
'A': 65,
'B': 66,
'C': 67,
'D': 68,
'E': 69,
'F': 70,
'G': 71,
'H': 72,
'I': 73,
'J': 74,
'K': 75,
'L': 76,
'M': 77,
'N': 78,
'O': 79,
'P': 80,
'Q': 81,
'R': 82,
'S': 83,
'T': 84,
'U': 85,
'V': 86,
'W': 87,
'X': 88,
'Y': 89,
'Z': 90,
'NUMPAD_0': 96,
'NUMPAD_1': 97,
'NUMPAD_2': 98,
'NUMPAD_3': 99,
'NUMPAD_4': 100,
'NUMPAD_5': 101,
'NUMPAD_6': 102,
'NUMPAD_7': 103,
'NUMPAD_8': 104,
'NUMPAD_9': 105,
'MULTIPLY': 106,
'ADD': 107,
'SUBSTRACT': 109,
'DECIMAL': 110,
'DIVIDE': 111,
'F1': 112,
'F2': 113,
'F3': 114,
'F4': 115,
'F5': 116,
'F6': 117,
'F7': 118,
'F8': 119,
'F9': 120,
'F10': 121,
'F11': 122,
'F12': 123,
'SHIFT': 16,
'CTRL': 17,
'ALT': 18,
'PLUS': 187,
'COMMA': 188,
'MINUS': 189,
'PERIOD': 190
};
ig.Input = ig.Class.extend({
bindings: {},
actions: {},
presses: {},
locks: {},
delayedKeyup: {},
isUsingMouse: false,
isUsingKeyboard: false,
isUsingAccelerometer: false,
mouse: {x: 0, y: 0},
accel: {x: 0, y: 0, z: 0},
initMouse: function() {
if( this.isUsingMouse ) { return; }
this.isUsingMouse = true;
window.addEventListener('mousewheel', this.mousewheel.bind(this), false );
ig.system.canvas.addEventListener('contextmenu', this.contextmenu.bind(this), false );
ig.system.canvas.addEventListener('mousedown', this.keydown.bind(this), false );
ig.system.canvas.addEventListener('mouseup', this.keyup.bind(this), false );
ig.system.canvas.addEventListener('mousemove', this.mousemove.bind(this), false );
ig.system.canvas.addEventListener('touchstart', this.keydown.bind(this), false );
ig.system.canvas.addEventListener('touchend', this.keyup.bind(this), false );
ig.system.canvas.addEventListener('touchmove', this.mousemove.bind(this), false );
},
initKeyboard: function() {
if( this.isUsingKeyboard ) { return; }
this.isUsingKeyboard = true;
window.addEventListener('keydown', this.keydown.bind(this), false );
window.addEventListener('keyup', this.keyup.bind(this), false );
},
initAccelerometer: function() {
if( this.isUsingAccelerometer ) { return; }
window.addEventListener('devicemotion', this.devicemotion.bind(this), false );
},
mousewheel: function( event ) {
var code = event.wheel > 0 ? ig.KEY.MWHEEL_UP : ig.KEY.MWHEEL_DOWN;
var action = this.bindings[code];
if( action ) {
this.actions[action] = true;
this.presses[action] = true;
event.stopPropagation();
this.delayedKeyup[action] = true;
}
},
mousemove: function( event ) {
var el = ig.system.canvas;
var pos = {left: 0, top: 0};
while( el != null ) {
pos.left += el.offsetLeft;
pos.top += el.offsetTop;
el = el.offsetParent;
}
var tx = event.pageX;
var ty = event.pageY;
if( event.touches ) {
tx = event.touches[0].clientX;
ty = event.touches[0].clientY;
}
this.mouse.x = (tx - pos.left) / ig.system.scale;
this.mouse.y = (ty - pos.top) / ig.system.scale;
},
contextmenu: function( event ) {
if( this.bindings[ig.KEY.MOUSE2] ) {
event.stopPropagation();
event.preventDefault();
}
},
keydown: function( event ) {
if( event.target.type == 'text' ) { return; }
var code = event.type == 'keydown'
? event.keyCode
: (event.button == 2 ? ig.KEY.MOUSE2 : ig.KEY.MOUSE1);
if( event.type == 'touchstart' || event.type == 'mousedown' ) {
this.mousemove( event );
}
var action = this.bindings[code];
if( action ) {
this.actions[action] = true;
if( !this.locks[action] ) {
this.presses[action] = true;
this.locks[action] = true;
}
event.stopPropagation();
event.preventDefault();
}
},
keyup: function( event ) {
if( event.target.type == 'text' ) { return; }
var code = event.type == 'keyup'
? event.keyCode
: (event.button == 2 ? ig.KEY.MOUSE2 : ig.KEY.MOUSE1);
var action = this.bindings[code];
if( action ) {
this.delayedKeyup[action] = true;
event.stopPropagation();
event.preventDefault();
}
},
devicemotion: function( event ) {
this.accel = event.accelerationIncludingGravity;
},
bind: function( key, action ) {
if( key < 0 ) { this.initMouse(); }
else if( key > 0 ) { this.initKeyboard(); }
this.bindings[key] = action;
},
bindTouch: function( selector, action ) {
var element = ig.$( selector );
var that = this;
element.addEventListener('touchstart', function(ev) {
that.touchStart( ev, action );
}, false);
element.addEventListener('touchend', function(ev) {
that.touchEnd( ev, action );
}, false);
},
unbind: function( key ) {
var action = this.bindings[key];
this.delayedKeyup[action] = true;
this.bindings[key] = null;
},
unbindAll: function() {
this.bindings = {};
this.actions = {};
this.presses = {};
this.locks = {};
this.delayedKeyup = {};
},
state: function( action ) {
return this.actions[action];
},
pressed: function( action ) {
return this.presses[action];
},
released: function( action ) {
return this.delayedKeyup[action];
},
clearPressed: function() {
for( var action in this.delayedKeyup ) {
this.actions[action] = false;
this.locks[action] = false;
}
this.delayedKeyup = {};
this.presses = {};
},
touchStart: function( event, action ) {
this.actions[action] = true;
this.presses[action] = true;
event.stopPropagation();
event.preventDefault();
return false;
},
touchEnd: function( event, action ) {
this.delayedKeyup[action] = true;
event.stopPropagation();
event.preventDefault();
return false;
}
});
});

101
dev/lib/impact/loader.js Executable file
View file

@ -0,0 +1,101 @@
ig.module(
'impact.loader'
)
.requires(
'impact.image',
'impact.font',
'impact.sound'
)
.defines(function(){
ig.Loader = ig.Class.extend({
resources: [],
gameClass: null,
status: 0,
done: false,
_unloaded: [],
_drawStatus: 0,
_intervalId: 0,
_loadCallbackBound: null,
init: function( gameClass, resources ) {
this.gameClass = gameClass;
this.resources = resources;
this._loadCallbackBound = this._loadCallback.bind(this);
for( var i = 0; i < this.resources.length; i++ ) {
this._unloaded.push( this.resources[i].path );
}
},
load: function() {
ig.system.clear( '#000' );
if( !this.resources.length ) {
this.end();
return;
}
for( var i = 0; i < this.resources.length; i++ ) {
this.loadResource( this.resources[i] );
}
this._intervalId = setInterval( this.draw.bind(this), 16 );
},
loadResource: function( res ) {
res.load( this._loadCallbackBound );
},
end: function() {
if( this.done ) { return; }
this.done = true;
clearInterval( this._intervalId );
ig.system.setGame( this.gameClass );
},
draw: function() {
this._drawStatus += (this.status - this._drawStatus)/5;
var s = ig.system.scale;
var w = ig.system.width * 0.6;
var h = ig.system.height * 0.1;
var x = ig.system.width * 0.5-w/2;
var y = ig.system.height * 0.5-h/2;
ig.system.context.fillStyle = '#000';
ig.system.context.fillRect( 0, 0, 480, 320 );
ig.system.context.fillStyle = '#fff';
ig.system.context.fillRect( x*s, y*s, w*s, h*s );
ig.system.context.fillStyle = '#000';
ig.system.context.fillRect( x*s+s, y*s+s, w*s-s-s, h*s-s-s );
ig.system.context.fillStyle = '#fff';
ig.system.context.fillRect( x*s, y*s, w*s*this._drawStatus, h*s );
},
_loadCallback: function( path, status ) {
if( status ) {
this._unloaded.erase( path );
}
else {
throw( 'Failed to load resource: ' + path );
}
this.status = 1 - (this._unloaded.length / this.resources.length);
if( this._unloaded.length == 0 ) { // all done?
setTimeout( this.end.bind(this), 250 );
}
}
});
});

48
dev/lib/impact/map.js Executable file
View file

@ -0,0 +1,48 @@
ig.module(
'impact.map'
)
.defines(function(){
ig.Map = ig.Class.extend({
tilesize: 8,
width: 1,
height: 1,
data: [[]],
init: function( tilesize, data ) {
this.tilesize = tilesize;
this.data = data;
this.height = data.length;
this.width = data[0].length;
},
getTile: 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.data[ty][tx];
}
else {
return 0;
}
},
setTile: function( x, y, tile ) {
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)
) {
this.data[ty][tx] = tile;
}
}
});
});

333
dev/lib/impact/sound.js Executable file
View file

@ -0,0 +1,333 @@
ig.module(
'impact.sound'
)
.defines(function(){
ig.SoundManager = ig.Class.extend({
clips: {},
volume: 1,
format: null,
init: function() {
// Probe sound formats and determine the file extension to load
var probe = new Audio();
for( var i = 0; i < ig.Sound.use.length; i++ ) {
var format = ig.Sound.use[i];
if( probe.canPlayType(format.mime) ) {
this.format = format;
break;
}
}
// No compatible format found? -> Disable sound
if( !this.format ) {
ig.Sound.enabled = false;
}
},
load: function( path, multiChannel, loadCallback ) {
// Path to the soundfile with the right extension (.ogg or .mp3)
var realPath = path.match(/^(.*)\.[^\.]+$/)[1] + '.' + this.format.ext + ig.nocache;
// Sound file already loaded?
if( this.clips[path] ) {
// Only loaded as single channel and now requested as multichannel?
if( multiChannel && this.clips[path].length < ig.Sound.channels ) {
for( var i = this.clips[path].length; i < ig.Sound.channels; i++ ) {
var a = new Audio( realPath );
a.load();
this.clips[path].push( a );
}
}
return this.clips[path][0];
}
var clip = new Audio( realPath );
if( loadCallback ) {
// The canplaythrough event is dispatched when the browser determines
// that the sound can be played without interuption, provided the
// download rate doesn't change.
// FIXME: Mobile Safari doesn't seem to dispatch this event at all?
clip.addEventListener( 'canplaythrough', function(ev){
this.removeEventListener('canplaythrough', arguments.callee, false);
loadCallback( path, true, ev );
}, false );
// FIXME: Sometimes Firefox aborts loading sounds for no reason(?),
// tell the callback that everything went fine anyway
// Haven't been able to determine when or why this happens :/
// Update: Firefox4 doesn't have this problem anymore, but
// now IE9 does :(
clip.addEventListener( 'error', function(ev){
loadCallback( path, true, ev ); // should pass 'false'
}, false);
}
clip.load();
this.clips[path] = [clip];
if( multiChannel ) {
for( var i = 1; i < ig.Sound.channels; i++ ) {
var a = new Audio(realPath);
a.load();
this.clips[path].push( a );
}
}
return clip;
},
get: function( path ) {
// Find and return a channel that is not currently playing
var channels = this.clips[path];
for( var i = 0, clip; clip = channels[i++]; ) {
if( clip.paused || clip.ended ) {
if( clip.ended ) {
clip.currentTime = 0;
}
return clip;
}
}
// Still here? Pause and rewind the first channel
channels[0].pause();
channels[0].currentTime = 0;
return channels[0];
}
});
ig.Music = ig.Class.extend({
tracks: [],
namedTracks: {},
currentTrack: null,
currentIndex: 0,
random: false,
_volume: 1,
_loop: false,
_fadeInterval: 0,
_fadeTimer: null,
_endedCallbackBound: null,
init: function() {
this._endedCallbackBound = this._endedCallback.bind(this);
if( Object.defineProperty ) { // Standard
Object.defineProperty(this,"volume", {
get: this.getVolume.bind(this),
set: this.setVolume.bind(this)
});
Object.defineProperty(this,"loop", {
get: this.getLooping.bind(this),
set: this.setLooping.bind(this)
});
}
else if( this.__defineGetter__ ) { // Non-standard
this.__defineGetter__('volume', this.getVolume.bind(this));
this.__defineSetter__('volume', this.setVolume.bind(this));
this.__defineGetter__('loop', this.getLooping.bind(this));
this.__defineSetter__('loop', this.setLooping.bind(this));
}
},
add: function( music, name ) {
if( !ig.Sound.enabled ) {
return;
}
var path = music instanceof ig.Sound ? music.path : music;
var track = ig.soundManager.load(path, false);
track.loop = this._loop;
track.volume = this._volume;
track.addEventListener( 'ended', this._endedCallbackBound, false );
this.tracks.push( track );
if( name ) {
this.namedTracks[name] = track;
}
if( !this.currentTrack ) {
this.currentTrack = track;
}
},
next: function() {
if( !this.tracks.length ) { return; }
this.stop();
this.currentIndex = this.random
? Math.floor(Math.random() * this.tracks.length)
: (this.currentIndex + 1) % this.tracks.length;
this.currentTrack = this.tracks[this.currentIndex];
this.play();
},
pause: function() {
if( !this.currentTrack ) { return; }
this.currentTrack.pause();
},
stop: function() {
if( !this.currentTrack ) { return; }
this.currentTrack.pause();
this.currentTrack.currentTime = 0;
},
play: function( name ) {
// If a name was provided, stop playing the current track (if any)
// and play the named track
if( name && this.namedTracks[name] ) {
var newTrack = this.namedTracks[name];
if( newTrack != this.currentTrack ) {
this.stop();
this.currentTrack = newTrack;
}
}
else if( !this.currentTrack ) {
return;
}
this.currentTrack.play();
},
getLooping: function() {
return this._loop;
},
setLooping: function( l ) {
this._loop = l;
for( var i in this.tracks ) {
this.tracks[i].loop = l;
}
},
getVolume: function() {
return this._volume;
},
setVolume: function( v ) {
this._volume = v.limit(0,1);
for( var i in this.tracks ) {
this.tracks[i].volume = this._volume;
}
},
fadeOut: function( time ) {
if( !this.currentTrack ) { return; }
clearInterval( this._fadeInterval );
this.fadeTimer = new ig.Timer( time );
this._fadeInterval = setInterval( this._fadeStep.bind(this), 50 );
},
_fadeStep: function() {
var v = this.fadeTimer.delta()
.map(-this.fadeTimer.target, 0, 1, 0)
.limit( 0, 1 )
* this._volume;
if( v <= 0.01 ) {
this.stop();
this.currentTrack.volume = this._volume;
clearInterval( this._fadeInterval );
}
else {
this.currentTrack.volume = v;
}
},
_endedCallback: function() {
if( this._loop ) {
this.play();
}
else {
this.next();
}
}
});
ig.Sound = ig.Class.extend({
path: '',
volume: 1,
currentClip: null,
multiChannel: true,
init: function( path, multiChannel ) {
this.path = path;
this.multiChannel = (multiChannel !== false);
this.load();
},
load: function( loadCallback ) {
if( !ig.Sound.enabled ) {
if( loadCallback ) {
loadCallback( this.path, true );
}
return;
}
if( ig.ready ) {
ig.soundManager.load( this.path, this.multiChannel, loadCallback );
}
else {
ig.addResource( this );
}
},
play: function() {
if( !ig.Sound.enabled ) {
return;
}
this.currentClip = ig.soundManager.get( this.path );
this.currentClip.volume = ig.soundManager.volume * this.volume;
this.currentClip.play();
},
stop: function() {
if( this.currentClip ) {
this.currentClip.pause();
this.currentClip.currentTime = 0;
}
}
});
ig.Sound.FORMAT = {
MP3: {ext: 'mp3', mime: 'audio/mpeg'},
M4A: {ext: 'm4a', mime: 'audio/mp4; codecs=mp4a'},
OGG: {ext: 'ogg', mime: 'audio/ogg; codecs=vorbis'},
WEBM: {ext: 'webm', mime: 'audio/webm; codecs=vorbis'},
CAF: {ext: 'caf', mime: 'audio/x-caf'}
};
ig.Sound.use = [ig.Sound.FORMAT.OGG, ig.Sound.FORMAT.MP3];
ig.Sound.channels = 4;
ig.Sound.enabled = true;
});

116
dev/lib/impact/system.js Executable file
View file

@ -0,0 +1,116 @@
ig.module(
'impact.system'
)
.requires(
'impact.timer',
'impact.image'
)
.defines(function(){
ig.System = ig.Class.extend({
fps: 30,
width: 320,
height: 240,
realWidth: 320,
realHeight: 240,
scale: 1,
tick: 0,
intervalId: 0,
newGameClass: null,
running: false,
delegate: null,
clock: null,
canvas: null,
context: null,
smoothPositioning: true,
init: function( canvasId, fps, width, height, scale ) {
this.fps = fps;
this.clock = new ig.Timer();
this.canvas = ig.$(canvasId);
this.resize( width, height, scale );
this.context = this.canvas.getContext('2d');
},
resize: function( width, height, scale ) {
this.width = width;
this.height = height;
this.scale = scale || this.scale;
this.realWidth = this.width * this.scale;
this.realHeight = this.height * this.scale;
this.canvas.width = this.realWidth;
this.canvas.height = this.realHeight;
},
setGame: function( gameClass ) {
if( this.running ) {
this.newGameClass = gameClass;
}
else {
this.setGameNow( gameClass );
}
},
setGameNow: function( gameClass ) {
ig.game = new (gameClass)();
ig.system.setDelegate( ig.game );
},
setDelegate: function( object ) {
if( typeof(object.run) == 'function' ) {
this.delegate = object;
this.startRunLoop();
} else {
throw( 'System.setDelegate: No run() function in object' );
}
},
stopRunLoop: function() {
clearInterval( this.intervalId );
this.running = false;
},
startRunLoop: function() {
this.stopRunLoop();
this.intervalId = setInterval( this.run.bind(this), 1000 / this.fps );
this.running = true;
},
clear: function( color ) {
this.context.fillStyle = color;
this.context.fillRect( 0, 0, this.realWidth, this.realHeight );
},
run: function() {
ig.Timer.step();
this.tick = this.clock.tick();
this.delegate.run();
ig.input.clearPressed();
if( this.newGameClass ) {
this.setGameNow( this.newGameClass );
this.newGameClass = null;
}
},
getDrawPos: function( p ) {
return this.smoothPositioning ? Math.round(p * this.scale) : Math.round(p) * this.scale;
}
});
});

54
dev/lib/impact/timer.js Executable file
View file

@ -0,0 +1,54 @@
ig.module(
'impact.timer'
)
.defines(function(){
ig.Timer = ig.Class.extend({
target: 0,
base: 0,
last: 0,
init: function( seconds ) {
this.base = ig.Timer.time;
this.last = ig.Timer.time;
this.target = seconds || 0;
},
set: function( seconds ) {
this.target = seconds || 0;
this.base = ig.Timer.time;
},
reset: function() {
this.base = ig.Timer.time;
},
tick: function() {
var delta = ig.Timer.time - this.last;
this.last = ig.Timer.time;
return delta;
},
delta: function() {
return ig.Timer.time - this.base - this.target;
}
});
ig.Timer._last = 0;
ig.Timer.time = 0;
ig.Timer.timeScale = 1;
ig.Timer.maxStep = 0.05;
ig.Timer.step = function() {
var current = Date.now();
var delta = (current - ig.Timer._last) / 1000;
ig.Timer.time += Math.min(delta, ig.Timer.maxStep) * ig.Timer.timeScale;
ig.Timer._last = current;
};
});

View file

@ -0,0 +1,37 @@
<?php
require_once( 'config.php' );
$dir = WM_Config::$fileRoot . str_replace( '..', '', $_GET['dir'] );
if( $dir{strlen($dir)-1} != '/' ) {
$dir .= '/';
}
$find = '*.*';
switch( $_GET['type'] ) {
case 'images':
$find = '*.{png,gif,jpg,jpeg}';
break;
case 'scripts':
$find = '*.js';
break;
}
$dirs = (array)glob( $dir.'*', GLOB_ONLYDIR );
$files = (array)glob( $dir.$find, GLOB_BRACE );
$fileRootLength = strlen( WM_Config::$fileRoot );
foreach( $files as $i => $f ) {
$files[$i] = substr( $f, $fileRootLength );
}
foreach( $dirs as $i => $d ) {
$dirs[$i] = substr( $d, $fileRootLength );
}
$parent = substr($_GET['dir'], 0, strrpos($_GET['dir'], '/'));
echo json_encode( array(
'parent' => (empty($_GET['dir']) ? false : $parent),
'dirs' => $dirs,
'files' => $files
));
?>

View file

@ -0,0 +1,22 @@
<?php
class WM_Config {
public static $fileRoot = '../../../';
}
function stripslashes_deep($value)
{
$value = is_array($value) ?
array_map( 'stripslashes_deep', $value ) :
stripslashes($value);
return $value;
}
// revert magic quotes
if( function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc() ) {
$_GET = array_map( 'stripslashes_deep', $_GET );
$_POST = array_map( 'stripslashes_deep', $_POST );
}
?>

View file

@ -0,0 +1,18 @@
<?php
require_once( 'config.php' );
$globs = is_array($_GET['glob']) ? $_GET['glob'] : array($_GET['glob']);
$files = array();
foreach( $globs as $glob ) {
$pattern = WM_Config::$fileRoot . str_replace( '..', '', $glob );
$files = array_merge( $files, (array)glob( $pattern ) );
}
$fileRootLength = strlen( WM_Config::$fileRoot );
foreach( $files as $i => $f ) {
$files[$i] = substr( $f, $fileRootLength );
}
echo json_encode( $files );
?>

View file

@ -0,0 +1,34 @@
<?php
require_once( 'config.php' );
$result = array('error' => 0);
if( !empty($_POST['path']) && !empty($_POST['data']) ) {
$path = WM_Config::$fileRoot . str_replace( '..', '', $_POST['path'] );
if( preg_match('/\.js$/', $path) ) {
$success = @file_put_contents( $path, $_POST['data'] );
if( $success === false ) {
$result = array(
'error' => '2',
'msg' => "Couldn't write to file: $path"
);
}
}
else {
$result = array(
'error' => '3',
'msg' => "File must have a .js suffix"
);
}
}
else {
$result = array(
'error' => '1',
'msg' => "No Data or Path specified"
);
}
echo json_encode($result);
?>

BIN
dev/lib/weltmeister/arrow.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

72
dev/lib/weltmeister/config.js Executable file
View file

@ -0,0 +1,72 @@
ig.module(
'weltmeister.config'
)
.defines(function(){
wm.config = {
project: {
'modulePath': 'lib/',
'entityFiles': 'lib/game/entities/*.js',
'levelPath': 'lib/game/levels/',
'outputFormat': 'module', // 'module' or 'json'
'prettyPrint': false
},
'layerDefaults': {
'width': 30,
'height': 20,
'tilesize': 8
},
'askBeforeClose': true,
'loadLastLevel': true,
'entityGrid': 4,
'undoLevels': 50,
'binds': {
'MOUSE1': 'draw',
'MOUSE2': 'drag',
'SHIFT': 'select',
'CTRL': 'drag',
'SPACE': 'menu',
'DELETE': 'delete',
'BACKSPACE': 'delete',
'G': 'grid',
'C': 'clone',
'Z': 'undo',
'Y': 'redo'
},
'view': {
'zoom': 2,
'grid': false
},
'labels': {
'draw': true,
'step': 32,
'font': '10px Bitstream Vera Sans Mono, Monaco, sans-serif'
},
'colors': {
'clear': '#000000',
'highlight': '#ceff36',
'primary': '#ffffff',
'secondary': '#555555',
'selection': '#ff9933'
},
'collisionTiles': {
'path': 'lib/weltmeister/collisiontiles-64.png',
'tilesize': 64
},
'api': {
'save': 'lib/weltmeister/api/save.php',
'browse': 'lib/weltmeister/api/browse.php',
'glob': 'lib/weltmeister/api/glob.php'
}
};
});

View file

@ -0,0 +1,667 @@
ig.module(
'weltmeister.edit-entities'
)
.requires(
'impact.background-map',
'weltmeister.config',
'weltmeister.tile-select',
'weltmeister.entities'
)
.defines(function(){
wm.EditEntities = ig.Class.extend({
visible: true,
active: true,
div: null,
currentTile: 0,
hotkey: -1,
ignoreLastClick: false,
name: 'entities',
entities: [],
namedEntities: {},
selectedEntity: null,
entityClasses: {},
menuDiv: null,
selector: {size:{x:2, y:2}, pos:{x:0,y:0}, offset:{x:0,y:0}},
wasSelectedOnScaleBorder: false,
gridSize: wm.config.entityGrid,
entityDefinitions: null,
init: function( div ) {
this.div = div;
div.bind( 'mouseup', this.click.bind(this) );
this.div.children('.visible').bind( 'mousedown', this.toggleVisibilityClick.bind(this) );
this.menu = $('#entityMenu');
this.importEntityClass( wm.entityModules );
this.entityDefinitions = $('#entityDefinitions');
$('#entityKey').bind( 'keydown', function(ev){
if( ev.which == 13 ){
$('#entityValue').focus();
return false;
}
return true;
});
$('#entityValue').bind( 'keydown', this.setEntitySetting.bind(this) );
},
clear: function() {
this.entities = [];
this.selectEntity( null );
},
// -------------------------------------------------------------------------
// Loading, Saving
fileNameToClassName: function( name ) {
var typeName = '-' + name.replace(/^.*\/|\.js/g,'');
typeName = typeName.replace(/-(\w)/g, function( m, a ) {
return a.toUpperCase();
});
return 'Entity' + typeName;
},
importEntityClass: function( modules ) {
var unloadedClasses = [];
for( var m in modules ) {
var className = this.fileNameToClassName(modules[m]);
var entityName = className.replace(/^Entity/, '');
// ig.global[className] should be the actual class object
if( className && ig.global[className] ) {
var a = $( '<div/>', {
'id': className,
'href': '#',
'html': entityName,
'mouseup': this.newEntityClick.bind(this)
});
this.menu.append( a );
this.entityClasses[className] = m;
}
else {
unloadedClasses.push( modules[m] + ' (expected name: ' + className + ')' );
}
}
if( unloadedClasses.length > 0 ) {
var warning = 'The following entity classes were not loaded due to\n'
+ 'file and class name mismatches: \n\n'
+ unloadedClasses.join( '\n' );
alert( warning );
}
},
getEntityByName: function( name ) {
return this.namedEntities[name];
},
getSaveData: function() {
var ents = [];
for( var i = 0; i < this.entities.length; i++ ) {
var ent = this.entities[i];
var type = ent._wmClassName;
var data = {type:type,x:ent.pos.x,y:ent.pos.y};
var hasSettings = false;
for( p in ent._wmSettings ) {
hasSettings = true;
}
if( hasSettings ) {
data.settings = ent._wmSettings;
}
ents.push( data );
}
return ents;
},
// -------------------------------------------------------------------------
// Selecting
selectEntityAt: function( x, y ) {
this.selector.pos = { x: x, y: y };
for( var i = 0; i < this.entities.length; i++ ) {
var ent = this.entities[i];
if( ent.touches(this.selector) ) {
this.selector.offset = {x: (x - ent.pos.x + ent.offset.x), y: (y - ent.pos.y + ent.offset.y)};
this.selectEntity( ent );
this.wasSelectedOnScaleBorder = this.isOnScaleBorder( ent, this.selector );
return ent;
}
}
this.selectEntity( null );
return false;
},
selectEntity: function( entity ) {
if( entity && entity != this.selectedEntity ) {
this.selectedEntity = entity;
$('#entitySettings').fadeOut(100,(function(){
this.loadEntitySettings();
$('#entitySettings').fadeIn(100);
}).bind(this));
}
else if( !entity ) {
$('#entitySettings').fadeOut(100);
}
this.selectedEntity = entity;
$('#entityKey').val('');
$('#entityValue').val('');
},
// -------------------------------------------------------------------------
// Creating, Deleting, Moving
deleteSelectedEntity: function() {
if( !this.selectedEntity ) {
return false;
}
ig.game.undo.commitEntityDelete( this.selectedEntity );
this.removeEntity( this.selectedEntity );
this.selectEntity( null );
return true;
},
removeEntity: function( ent ) {
if( ent.name ) {
delete this.namedEntities[ent.name];
}
this.entities.erase( ent );
},
cloneSelectedEntity: function() {
if( !this.selectedEntity ) {
return false;
}
var className = this.selectedEntity._wmClassName;
var settings = ig.copy(this.selectedEntity._wmSettings);
if( settings.name ) {
settings.name = settings.name + '_clone';
}
var x = this.selectedEntity.pos.x + this.gridSize;
var y = this.selectedEntity.pos.y;
var newEntity = this.spawnEntity( className, x, y, settings );
newEntity._wmSettings = settings;
this.selectEntity( newEntity );
ig.game.undo.commitEntityCreate( newEntity );
return true;
},
dragOnSelectedEntity: function( x, y ) {
if( !this.selectedEntity ) {
return false;
}
// scale or move?
if( this.selectedEntity._wmScalable && this.wasSelectedOnScaleBorder ) {
this.scaleSelectedEntity( x, y );
}
else {
this.moveSelectedEntity( x, y )
}
ig.game.undo.pushEntityEdit( this.selectedEntity );
return true;
},
moveSelectedEntity: function( x, y ) {
x =
Math.round( (x - this.selector.offset.x ) / this.gridSize )
* this.gridSize + this.selectedEntity.offset.x;
y =
Math.round( (y - this.selector.offset.y ) / this.gridSize )
* this.gridSize + this.selectedEntity.offset.y;
// new position?
if( this.selectedEntity.pos.x != x || this.selectedEntity.pos.y != y ) {
$('#entityDefinitionPosX').text( x );
$('#entityDefinitionPosY').text( y );
this.selectedEntity.pos.x = x;
this.selectedEntity.pos.y = y;
}
},
scaleSelectedEntity: function( x, y ) {
var scale = this.wasSelectedOnScaleBorder;
var w = Math.round( x / this.gridSize ) * this.gridSize - this.selectedEntity.pos.x;
if( !this.selectedEntity._wmSettings.size ) {
this.selectedEntity._wmSettings.size = {};
}
if( scale == 'n' ) {
var h = this.selectedEntity.pos.y - Math.round( y / this.gridSize ) * this.gridSize;
if( this.selectedEntity.size.y + h <= this.gridSize ) {
h = (this.selectedEntity.size.y - this.gridSize) * -1;
}
this.selectedEntity.size.y += h;
this.selectedEntity.pos.y -= h;
}
else if( scale == 's' ) {
var h = Math.round( y / this.gridSize ) * this.gridSize - this.selectedEntity.pos.y;
this.selectedEntity.size.y = Math.max( this.gridSize, h );
}
else if( scale == 'e' ) {
var w = Math.round( x / this.gridSize ) * this.gridSize - this.selectedEntity.pos.x;
this.selectedEntity.size.x = Math.max( this.gridSize, w );
}
else if( scale == 'w' ) {
var w = this.selectedEntity.pos.x - Math.round( x / this.gridSize ) * this.gridSize;
if( this.selectedEntity.size.x + w <= this.gridSize ) {
w = (this.selectedEntity.size.x - this.gridSize) * -1;
}
this.selectedEntity.size.x += w;
this.selectedEntity.pos.x -= w;
}
this.selectedEntity._wmSettings.size.x = this.selectedEntity.size.x;
this.selectedEntity._wmSettings.size.y = this.selectedEntity.size.y;
this.loadEntitySettings();
},
newEntityClick: function( ev ) {
this.hideMenu();
var newEntity = this.spawnEntity( ev.target.id, 0, 0, {} );
this.selectEntity( newEntity );
this.moveSelectedEntity( this.selector.pos.x, this.selector.pos.y );
ig.editor.setModified();
ig.game.undo.commitEntityCreate( newEntity );
},
spawnEntity: function( className, x, y, settings ) {
settings = settings || {};
var entityClass = ig.global[ className ];
if( entityClass ) {
var newEntity = new (entityClass)( x, y, settings );
newEntity._wmInEditor = true;
newEntity._wmClassName = className;
newEntity._wmSettings = {};
for( s in settings ) {
newEntity._wmSettings[s] = settings[s];
}
this.entities.push( newEntity );
if( settings.name ) {
this.namedEntities[settings.name] = newEntity;
}
return newEntity;
}
return null;
},
isOnScaleBorder: function( entity, selector ) {
var border = 2;
var w = selector.pos.x - entity.pos.x;
var h = selector.pos.y - entity.pos.y;
if( w < border ) return 'w';
if( w > entity.size.x - border ) return 'e';
if( h < border ) return 'n';
if( h > entity.size.y - border ) return 's';
return false;
},
// -------------------------------------------------------------------------
// Settings
loadEntitySettings: function(ent) {
if( !this.selectedEntity ) {
return;
}
var html =
'<div class="entityDefinition"><span class="key">x</span>:<span class="value" id="entityDefinitionPosX">'+this.selectedEntity.pos.x+'</span></div>'
+ '<div class="entityDefinition"><span class="key">y</span>:<span class="value" id="entityDefinitionPosY">'+this.selectedEntity.pos.y+'</span></div>';
html += this.loadEntitySettingsRecursive( this.selectedEntity._wmSettings );
this.entityDefinitions.html( html );
var className = this.selectedEntity._wmClassName.replace(/^Entity/, '');
$('#entityClass').text( className );
$('.entityDefinition').bind( 'mouseup', this.selectEntitySetting );
},
loadEntitySettingsRecursive: function( settings, path ) {
path = path || "";
var html = "";
for( key in settings ) {
var value = settings[key];
if( typeof(value) == 'object' ) {
html += this.loadEntitySettingsRecursive( value, path + key + "." );
}
else {
html += '<div class="entityDefinition"><span class="key">'+path+key+'</span>:<span class="value">'+value+'</span></div>';
}
}
return html;
},
setEntitySetting: function( ev ) {
if( ev.which != 13 ) {
return true;
}
var key = $('#entityKey').val();
var value = $('#entityValue').val();
var floatVal = parseFloat(value);
if( value == floatVal ) {
value = floatVal;
}
if( key == 'name' ) {
if( this.selectedEntity.name ) {
delete this.namedEntities[this.selectedEntity.name];
}
this.namedEntities[ value ] = this.selectedEntity;
}
if( key == 'x' ) {
this.selectedEntity.pos.x = Math.round(value);
}
else if( key == 'y' ) {
this.selectedEntity.pos.y = Math.round(value);
}
else {
this.writeSettingAtPath( this.selectedEntity._wmSettings, key, value );
ig.merge( this.selectedEntity, this.selectedEntity._wmSettings );
}
ig.game.setModified();
ig.game.draw();
$('#entityKey').val('');
$('#entityValue').val('');
$('#entityValue').blur();
this.loadEntitySettings();
$('#entityKey').focus();
return false;
},
writeSettingAtPath: function( root, path, value ) {
path = path.split('.');
var cur = root;
for( var i = 0; i < path.length; i++ ) {
var n = path[i];
if( i < path.length-1 && typeof(cur[n]) != 'object' ) {
cur[n] = {};
}
if( i == path.length-1 ) {
cur[n] = value;
}
cur = cur[n];
}
this.trimObject( root );
},
trimObject: function( obj ) {
var isEmpty = true;
for( var i in obj ) {
if(
(obj[i] === "") ||
(typeof(obj[i]) == 'object' && this.trimObject(obj[i]))
) {
delete obj[i];
}
if( typeof(obj[i]) != 'undefined' ) {
isEmpty = false;
}
}
return isEmpty;
},
selectEntitySetting: function( ev ) {
$('#entityKey').val( $(this).children('.key').text() );
$('#entityValue').val( $(this).children('.value').text() );
$('#entityValue').select();
},
// -------------------------------------------------------------------------
// UI
setHotkey: function( hotkey ) {
this.hotkey = hotkey;
this.div.attr('title', 'Select Layer ('+this.hotkey+')' );
},
showMenu: function( x, y ) {
this.selector.pos = {
x: Math.round( (x + ig.editor.screen.x) / this.gridSize ) * this.gridSize,
y: Math.round( (y + ig.editor.screen.y) / this.gridSize ) * this.gridSize
};
this.menu.css({top: (y * ig.system.scale + 2), left: (x * ig.system.scale + 2) });
this.menu.show();
},
hideMenu: function( x, y ) {
ig.editor.mode = ig.editor.MODE.DEFAULT;
this.menu.hide();
},
setActive: function( active ) {
this.active = active;
if( active ) {
this.div.addClass( 'layerActive' );
} else {
this.div.removeClass( 'layerActive' );
}
},
toggleVisibility: function() {
this.visible ^= 1;
if( this.visible ) {
this.div.children('.visible').addClass('checkedVis');
} else {
this.div.children('.visible').removeClass('checkedVis');
}
ig.game.draw();
},
toggleVisibilityClick: function( ev ) {
if( !this.active ) {
this.ignoreLastClick = true;
}
this.toggleVisibility()
},
click: function() {
if( this.ignoreLastClick ) {
this.ignoreLastClick = false;
return;
}
ig.editor.setActiveLayer( 'entities' );
},
mousemove: function( x, y ) {
this.selector.pos = { x: x, y: y };
if( this.selectedEntity ) {
if( this.selectedEntity._wmScalable && this.selectedEntity.touches(this.selector) ) {
var scale = this.isOnScaleBorder( this.selectedEntity, this.selector );
if( scale == 'n' || scale == 's' ) {
$('body').css('cursor', 'n-resize');
return;
}
else if( scale == 'e' || scale == 'w' ) {
$('body').css('cursor', 'e-resize');
return;
}
}
}
$('body').css('cursor', 'default');
},
// -------------------------------------------------------------------------
// Drawing
draw: function() {
if( this.visible ) {
for( var i = 0; i < this.entities.length; i++ ) {
this.drawEntity( this.entities[i] );
}
}
},
drawEntity: function( ent ) {
// entity itself
ent.draw();
// box
if( ent._wmDrawBox ) {
ig.system.context.fillStyle = ent._wmBoxColor || 'rgba(128, 128, 128, 0.9)';
ig.system.context.fillRect(
ig.system.getDrawPos(ent.pos.x - ig.game.screen.x),
ig.system.getDrawPos(ent.pos.y - ig.game.screen.y),
ent.size.x * ig.system.scale,
ent.size.y * ig.system.scale
);
}
if( wm.config.labels.draw ) {
// description
var className = ent._wmClassName.replace(/^Entity/, '');
var description = className + (ent.name ? ': ' + ent.name : '' );
// text-shadow
ig.system.context.fillStyle = 'rgba(0,0,0,0.4)';
ig.system.context.fillText(
description,
ig.system.getDrawPos(ent.pos.x - ig.game.screen.x),
ig.system.getDrawPos(ent.pos.y - ig.game.screen.y + 0.5)
);
// text
ig.system.context.fillStyle = wm.config.colors.primary;
ig.system.context.fillText(
description,
ig.system.getDrawPos(ent.pos.x - ig.game.screen.x),
ig.system.getDrawPos(ent.pos.y - ig.game.screen.y)
);
}
// line to targets
if( typeof(ent.target) == 'object' ) {
for( var t in ent.target ) {
this.drawLineToTarget( ent, ent.target[t] );
}
}
},
drawLineToTarget: function( ent, target ) {
target = ig.game.getEntityByName( target );
if( !target ) {
return;
}
ig.system.context.strokeStyle = '#fff';
ig.system.context.lineWidth = 1;
ig.system.context.beginPath();
ig.system.context.moveTo(
ig.system.getDrawPos(ent.pos.x + ent.size.x/2 - ig.game.screen.x),
ig.system.getDrawPos(ent.pos.y + ent.size.y/2 - ig.game.screen.y)
);
ig.system.context.lineTo(
ig.system.getDrawPos(target.pos.x + target.size.x/2 - ig.game.screen.x),
ig.system.getDrawPos(target.pos.y + target.size.y/2 - ig.game.screen.y)
);
ig.system.context.stroke();
ig.system.context.closePath();
},
drawCursor: function( x, y ) {
if( this.selectedEntity ) {
ig.system.context.lineWidth = 1;
ig.system.context.strokeStyle = wm.config.colors.highlight;
ig.system.context.strokeRect(
ig.system.getDrawPos(this.selectedEntity.pos.x - ig.editor.screen.x) - 0.5,
ig.system.getDrawPos(this.selectedEntity.pos.y - ig.editor.screen.y) - 0.5,
this.selectedEntity.size.x * ig.system.scale + 1,
this.selectedEntity.size.y * ig.system.scale + 1
);
}
}
});
});

383
dev/lib/weltmeister/edit-map.js Executable file
View file

@ -0,0 +1,383 @@
ig.module(
'weltmeister.edit-map'
)
.requires(
'impact.background-map',
'weltmeister.tile-select'
)
.defines(function(){
wm.EditMap = ig.BackgroundMap.extend({
name: '',
visible: true,
active: true,
linkWithCollision: false,
div: null,
currentTile: 0,
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
draw: function() {
if( this.visible ) {
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 * ig.system.scale;
scaled.height = this.height * ig.system.scale;
var scaledCtx = scaled.getContext('2d');
scaledCtx.drawImage( this.data, 0, 0, this.data.width, this.data.height, 0, 0, scaled.width , scaled.height );
this.data = scaled;
}
this.loaded = true;
if( this.loadCallback ) {
this.loadCallback( this.path, true );
}
}
});
});

56
dev/lib/weltmeister/entities.js Executable file
View file

@ -0,0 +1,56 @@
ig.module(
'weltmeister.entityLoader'
)
.requires(
'weltmeister.config'
)
.defines(function(){
// Load the list of entity files via AJAX PHP glob
var path = wm.config.api.glob + '?',
globs = typeof wm.config.project.entityFiles == 'string' ?
[wm.config.project.entityFiles] :
wm.config.project.entityFiles;
for (var i = 0; i < globs.length; i++) {
path += 'glob[]=' + encodeURIComponent(globs[i]) + '&';
}
path += 'nocache=' + Math.random();
var req = $.ajax({
url: path,
method: 'get',
dataType: 'json',
// MUST load synchronous, as the engine would otherwise determine that it
// can't resolve dependencies to weltmeister.entities when there are
// no more files to load and weltmeister.entities is still not defined
// because the ajax request hasn't finished yet.
// FIXME FFS!
async: false,
success: function(files) {
// File names to Module names
var moduleNames = [];
var modules = {};
for( var i = 0; i < files.length; i++ ) {
var name = files[i].replace(/^lib\/|\.js$/g,'').replace(/\//g, '.');
moduleNames.push( name );
modules[name] = files[i];
}
// Define a Module that requires all entity Modules
ig.module('weltmeister.entities')
.requires.apply(ig, moduleNames)
.defines(function(){ wm.entityModules = modules; });
},
error: function( xhr, status, error ){
throw(
"Failed to load entity list via glob.php: " + error + "\n" +
xhr.responseText
);
}
});
});

View file

@ -0,0 +1,62 @@
ig.module(
'weltmeister.evented-input'
)
.requires(
'impact.input'
)
.defines(function(){
wm.EventedInput = ig.Input.extend({
mousemoveCallback: null,
keyupCallback: null,
keydownCallback: null,
delayedKeyup: {push:function(){},length: 0},
keydown: function( event ) {
if( event.target.type == 'text' ) { return; }
var code = event.type == 'keydown'
? event.keyCode
: (event.button == 2 ? ig.KEY.MOUSE2 : ig.KEY.MOUSE1);
var action = this.bindings[code];
if( action ) {
if( !this.actions[action] ) {
this.actions[action] = true;
if( this.keydownCallback ) {
this.keydownCallback( action );
}
}
event.stopPropagation();
event.preventDefault();
}
},
keyup: function( event ) {
if( event.target.type == 'text' ) { return; }
var code = event.type == 'keyup'
? event.keyCode
: (event.button == 2 ? ig.KEY.MOUSE2 : ig.KEY.MOUSE1);
var action = this.bindings[code];
if( action ) {
this.actions[action] = false;
if( this.keyupCallback ) {
this.keyupCallback( action );
}
event.stopPropagation();
event.preventDefault();
}
},
mousemove: function( event ) {
this.parent( event );
if( this.mousemoveCallback ) {
this.mousemoveCallback();
}
}
});
});

405
dev/lib/weltmeister/jquery-1.4.2.min.js vendored Executable file
View file

@ -0,0 +1,405 @@
/*!
* jQuery JavaScript Library v1.4.2
* http://jquery.com/
*
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* Includes Sizzle.js
* http://sizzlejs.com/
* Copyright 2010, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
*
* Date: Sat Feb 13 22:33:48 2010 -0500
*/
(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
(function ($) {
var m = {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
},
s = {
'array': function (x) {
var a = ['['], b, f, i, l = x.length, v;
for (i = 0; i < l; i += 1) {
v = x[i];
f = s[typeof v];
if (f) {
v = f(v);
if (typeof v == 'string') {
if (b) {
a[a.length] = ',';
}
a[a.length] = v;
b = true;
}
}
}
a[a.length] = ']';
return a.join('');
},
'boolean': function (x) {
return String(x);
},
'null': function (x) {
return "null";
},
'number': function (x) {
return isFinite(x) ? String(x) : 'null';
},
'object': function (x) {
if (x) {
if (x instanceof Array) {
return s.array(x);
}
var a = ['{'], b, f, i, v;
for (i in x) {
v = x[i];
f = s[typeof v];
if (f) {
v = f(v);
if (typeof v == 'string') {
if (b) {
a[a.length] = ',';
}
a.push(s.string(i), ':', v);
b = true;
}
}
}
a[a.length] = '}';
return a.join('');
}
return 'null';
},
'string': function (x) {
if (/["\\\x00-\x1f]/.test(x)) {
x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) {
var c = m[b];
if (c) {
return c;
}
c = b.charCodeAt();
return '\\u00' +
Math.floor(c / 16).toString(16) +
(c % 16).toString(16);
});
}
return '"' + x + '"';
}
};
$.toJSON = function(v) {
var f = isNaN(v) ? s[typeof v] : s['number'];
if (f) return f(v);
};
$.parseJSON = function(v, safe) {
if (safe === undefined) safe = $.parseJSON.safe;
if (safe && !/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(v))
return undefined;
return eval('('+v+')');
};
$.parseJSON.safe = false;
})(jQuery);
(function(window) {
var p = [],
push = function( m ) { return '\\' + p.push( m ) + '\\'; };
pop = function( m, i ) { return p[i-1] };
tabs = function( count ) { return new Array( count + 1 ).join( '\t' ); };
window.JSONFormat = function( json ) {
p = [];
var out = "",
indent = 0;
// Extract backslashes and strings
json = json
.replace( /\\./g, push )
.replace( /(".*?"|'.*?')/g, push )
.replace( /\s+/, '' );
// Indent and insert newlines
for( var i = 0; i < json.length; i++ ) {
var c = json.charAt(i);
switch(c) {
case '{':
case '[':
out += c + "\n" + tabs(++indent);
break;
case '}':
case ']':
out += "\n" + tabs(--indent) + c;
break;
case ',':
out += ",\n" + tabs(indent);
break;
case ':':
out += ": ";
break;
default:
out += c;
break;
}
}
// Strip whitespace from numeric arrays and put backslashes
// and strings back in
out = out
.replace( /\[[\d,\s]+?\]/g, function(m){ return m.replace(/\s/g,''); } )
.replace( /\\(\d+)\\/g, pop );
return out;
};
})(window);
/**
* Cookie plugin
*
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/
/**
* Create a cookie with the given name and value and other optional parameters.
*
* @example $.cookie('the_cookie', 'the_value');
* @desc Set the value of a cookie.
* @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
* @desc Create a cookie with all available options.
* @example $.cookie('the_cookie', 'the_value');
* @desc Create a session cookie.
* @example $.cookie('the_cookie', null);
* @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
* used when the cookie was set.
*
* @param String name The name of the cookie.
* @param String value The value of the cookie.
* @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
* @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
* If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
* If set to null or omitted, the cookie will be a session cookie and will not be retained
* when the the browser exits.
* @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
* @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
* @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
* require a secure protocol (like HTTPS).
* @type undefined
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/
/**
* Get the value of a cookie with the given name.
*
* @example $.cookie('the_cookie');
* @desc Get the value of a cookie.
*
* @param String name The name of the cookie.
* @return The value of the cookie.
* @type String
*
* @name $.cookie
* @cat Plugins/Cookie
* @author Klaus Hartl/klaus.hartl@stilbuero.de
*/
jQuery.cookie = function(name, value, options) {
if (typeof value != 'undefined') { // name and value given, set cookie
options = options || {};
if (value === null) {
value = '';
options.expires = -1;
}
var expires = '';
if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
var date;
if (typeof options.expires == 'number') {
date = new Date();
date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
} else {
date = options.expires;
}
expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
}
// CAUTION: Needed to parenthesize options.path and options.domain
// in the following expressions, otherwise they evaluate to undefined
// in the packed version for some reason...
var path = options.path ? '; path=' + (options.path) : '';
var domain = options.domain ? '; domain=' + (options.domain) : '';
var secure = options.secure ? '; secure' : '';
document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
} else { // only name given, get cookie
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
};

View file

@ -0,0 +1,107 @@
/*!
* jQuery UI 1.8.1
*
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI
*/
jQuery.ui||function(c){c.ui={version:"1.8.1",plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&&a.element[0].parentNode)for(var e=0;e<b.length;e++)a.options[b[e][0]]&&b[e][1].apply(a.element,d)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")=="hidden")return false;
b=b&&b=="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,f,g){return c.ui.isOverAxis(a,d,f)&&c.ui.isOverAxis(b,e,g)},keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,
PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38}};c.fn.extend({_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d=this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none")},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||
/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==
undefined)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b=="absolute"||b=="relative"||b=="fixed"){b=parseInt(a.css("zIndex"));if(!isNaN(b)&&b!=0)return b}a=a.parent()}}return 0}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){var b=a.nodeName.toLowerCase(),d=c.attr(a,"tabindex");return(/input|select|textarea|button|object/.test(b)?!a.disabled:"a"==b||"area"==b?a.href||!isNaN(d):!isNaN(d))&&
!c(a)["area"==b?"parents":"closest"](":hidden").length},tabbable:function(a){var b=c.attr(a,"tabindex");return(isNaN(b)||b>=0)&&c(a).is(":focusable")}})}(jQuery);
;/*!
* jQuery UI Widget 1.8.1
*
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Widget
*/
(function(b){var j=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add(this).each(function(){b(this).triggerHandler("remove")});return j.call(b(this),a,c)})};b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h,a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend({},c.options);b[e][a].prototype=
b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.substring(0,1)==="_")return h;e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==undefined){h=i;return false}}):this.each(function(){var g=
b.data(this,a);if(g){d&&g.option(d);g._init()}else b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){this.element=b(c).data(this.widgetName,this);this.options=b.extend(true,{},this.options,b.metadata&&b.metadata.get(c)[this.widgetName],a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create();
this._init()},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")},widget:function(){return this.element},option:function(a,c){var d=a,e=this;if(arguments.length===0)return b.extend({},e.options);if(typeof a==="string"){if(c===undefined)return this.options[a];d={};d[a]=c}b.each(d,function(f,
h){e._setOption(f,h)});return e},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this},enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=
b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery);
;/*!
* jQuery UI Mouse 1.8.1
*
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Mouse
*
* Depends:
* jquery.ui.widget.js
*/
(function(c){c.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(b){return a._mouseDown(b)}).bind("click."+this.widgetName,function(b){if(a._preventClickEvent){a._preventClickEvent=false;b.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(a){a.originalEvent=a.originalEvent||{};if(!a.originalEvent.mouseHandled){this._mouseStarted&&
this._mouseUp(a);this._mouseDownEvent=a;var b=this,e=a.which==1,f=typeof this.options.cancel=="string"?c(a.target).parents().add(a.target).filter(this.options.cancel).length:false;if(!e||f||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){b.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=this._mouseStart(a)!==false;if(!this._mouseStarted){a.preventDefault();
return true}}this._mouseMoveDelegate=function(d){return b._mouseMove(d)};this._mouseUpDelegate=function(d){return b._mouseUp(d)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);c.browser.safari||a.preventDefault();return a.originalEvent.mouseHandled=true}},_mouseMove:function(a){if(c.browser.msie&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&
this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=a.target==this._mouseDownEvent.target;this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-
a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery);
;/*
* jQuery UI Sortable 1.8.1
*
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Sortables
*
* Depends:
* jquery.ui.core.js
* jquery.ui.mouse.js
* jquery.ui.widget.js
*/
(function(d){d.widget("ui.sortable",d.ui.mouse,{widgetEventPrefix:"sort",options:{appendTo:"parent",axis:false,connectWith:false,containment:false,cursor:"auto",cursorAt:false,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){this.containerCache={};this.element.addClass("ui-sortable");
this.refresh();this.floating=this.items.length?/left|right/.test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a==="disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(self,
arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&&!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=
c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,
{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();
if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",
a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a);return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");
if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop+b.scrollSpeed;else if(a.pageY-this.overflowOffset.top<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop-b.scrollSpeed;if(this.overflowOffset.left+
this.scrollParent[0].offsetWidth-a.pageX<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft+b.scrollSpeed;else if(a.pageX-this.overflowOffset.left<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft-b.scrollSpeed}else{if(a.pageY-d(document).scrollTop()<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()-b.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()+
b.scrollSpeed);if(a.pageX-d(document).scrollLeft()<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()-b.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()+b.scrollSpeed)}c!==false&&d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+
"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(b=this.items.length-1;b>=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0],e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,
c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset();c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==
document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp();this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate",
null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):
d(this.domPosition.parent).prepend(this.currentItem);return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});return c.join("&")},toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c},
_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+j<k&&b+l>g&&b+l<h;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?j:g<b+this.helperProportions.width/
2&&c-this.helperProportions.width/2<h&&i<e+this.helperProportions.height/2&&f-this.helperProportions.height/2<k},_intersectsWithPointer:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left,a.width);b=b&&a;a=this._getDragVerticalDirection();var c=this._getDragHorizontalDirection();if(!b)return false;return this.floating?c&&c=="right"||a=="down"?2:1:a&&(a=="down"?2:1)},_intersectsWithSides:function(a){var b=
d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top+a.height/2,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left+a.width/2,a.width);var c=this._getDragVerticalDirection(),e=this._getDragHorizontalDirection();return this.floating&&e?e=="right"&&a||e=="left"&&!a:c&&(c=="down"&&b||c=="up"&&!b)},_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},_getDragHorizontalDirection:function(){var a=
this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith();if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?
h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"),
b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(a){this.items=[];this.containers=[this];var b=this.items,c=[[d.isFunction(this.options.items)?this.options.items.call(this.element[0],a,{item:this.currentItem}):d(this.options.items,this.element),this]],e=this._connectWith();if(e)for(var f=e.length-1;f>=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?
i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h<g;h++){i=d(e[h]);i.data("sortable-item",a);b.push({item:i,instance:a,width:0,height:0,left:0,top:0})}}},refreshPositions:function(a){if(this.offsetParent&&this.helper)this.offset.parent=this._getParentOffset();for(var b=this.items.length-1;b>=0;b--){var c=this.items[b],e=this.options.toleranceElement?d(this.options.toleranceElement,
c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b=this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height=
this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f=d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-
parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],
this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out",a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=
1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h-f)<b){b=Math.abs(h-f);e=this.items[g]}}if(e||this.options.dropOnEmpty){this.currentContainer=this.containers[c];e?this._rearrange(a,e,null,true):this._rearrange(a,null,this.containers[c].element,true);this._trigger("change",a,this._uiHash());this.containers[c]._trigger("change",
a,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder);this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}}},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a,this.currentItem])):b.helper=="clone"?this.currentItem.clone():this.currentItem;a.parents("body").length||d(b.appendTo!="parent"?b.appendTo:this.currentItem[0].parentNode)[0].appendChild(a[0]);if(a[0]==
this.currentItem[0])this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")};if(a[0].style.width==""||b.forceHelperSize)a.width(this.currentItem.width());if(a[0].style.height==""||b.forceHelperSize)a.height(this.currentItem.height());return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||
0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.currentItem.position();return{top:a.top-
(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;
if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)){var b=
d(a.containment)[0];a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-
this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);return{top:b.top+
this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],
this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0]))this.offset.relative=this._getRelativeOffset();var f=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])f=this.containment[0]+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+this.offset.click.top;
if(a.pageX-this.offset.click.left>this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g-this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;f=this.originalPageX+Math.round((f-
this.originalPageX)/b.grid[0])*b.grid[0];f=this.containment?!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:!(f-this.offset.click.left<this.containment[0])?f-b.grid[0]:f+b.grid[0]:f}}return{top:g-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+
(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())}},_rearrange:function(a,b,c,e){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?b.item[0]:b.item[0].nextSibling);this.counter=this.counter?++this.counter:1;var f=this,g=this.counter;window.setTimeout(function(){g==f.counter&&f.refreshPositions(!e)},0)},_clear:function(a,b){this.reverting=false;var c=[];!this._noFinalSort&&
this.currentItem[0].parentNode&&this.placeholder.before(this.currentItem);this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var e in this._storedCSS)if(this._storedCSS[e]=="auto"||this._storedCSS[e]=="static")this._storedCSS[e]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!b&&c.push(function(f){this._trigger("receive",f,this._uiHash(this.fromOutside))});if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||
this.domPosition.parent!=this.currentItem.parent()[0])&&!b)c.push(function(f){this._trigger("update",f,this._uiHash())});if(!d.ui.contains(this.element[0],this.currentItem[0])){b||c.push(function(f){this._trigger("remove",f,this._uiHash())});for(e=this.containers.length-1;e>=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",
g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this,this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",
this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop",a,this._uiHash());for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}return false}b||this._trigger("beforeStop",a,this._uiHash());this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.helper[0]!=this.currentItem[0]&&this.helper.remove();this.helper=null;if(!b){for(e=
0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){d.Widget.prototype._trigger.apply(this,arguments)===false&&this.cancel()},_uiHash:function(a){var b=a||this;return{helper:b.helper,placeholder:b.placeholder||d([]),position:b.position,originalPosition:b.originalPosition,offset:b.positionAbs,item:b.currentItem,sender:a?a.element:null}}});d.extend(d.ui.sortable,{version:"1.8.1"})})(jQuery);
;

View file

@ -0,0 +1,108 @@
ig.module(
'weltmeister.modal-dialogs'
)
.requires(
'weltmeister.select-file-dropdown'
)
.defines(function(){
wm.ModalDialog = ig.Class.extend({
onOk: null,
onCancel: null,
text: '',
okText: '',
cancelText: '',
background: null,
dialogBox: null,
buttonDiv: null,
init: function( text, okText, cancelText ) {
this.text = text;
this.okText = okText || 'OK';
this.cancelText = cancelText || 'Cancel';
this.background = $('<div/>', {'class':'modalDialogBackground'});
this.dialogBox = $('<div/>', {'class':'modalDialogBox'});
this.background.append( this.dialogBox );
$('body').append( this.background );
this.initDialog( text );
},
initDialog: function() {
this.buttonDiv = $('<div/>', {'class': 'modalDialogButtons'} );
var okButton = $('<input/>', {'type': 'button', 'class':'button', 'value': this.okText});
var cancelButton = $('<input/>', {'type': 'button', 'class':'button', 'value': this.cancelText});
okButton.bind( 'click', this.clickOk.bind(this) );
cancelButton.bind( 'click', this.clickCancel.bind(this) );
this.buttonDiv.append( okButton ).append( cancelButton );
this.dialogBox.html('<div class="modalDialogText">' + this.text + '</div>' );
this.dialogBox.append( this.buttonDiv );
},
clickOk: function() {
if( this.onOk ) { this.onOk(this); }
this.close();
},
clickCancel: function() {
if( this.onCancel ) { this.onCancel(this); }
this.close();
},
open: function() {
this.background.fadeIn(100);
},
close: function() {
this.background.fadeOut(100);
}
});
wm.ModalDialogPathSelect = wm.ModalDialog.extend({
pathDropdown: null,
pathInput: null,
fileType: '',
init: function( text, okText, type ) {
this.fileType = type || '';
this.parent( text, (okText || 'Select') );
},
setPath: function( path ) {
var dir = path.replace(/\/[^\/]*$/, '');
this.pathInput.val( path );
this.pathDropdown.loadDir( dir );
},
initDialog: function() {
this.parent();
this.pathInput = $('<input/>', {'type': 'text', 'class': 'modalDialogPath'} );
this.buttonDiv.before( this.pathInput );
this.pathDropdown = new wm.SelectFileDropdown( this.pathInput, wm.config.api.browse, this.fileType );
},
clickOk: function() {
if( this.onOk ) {
this.onOk(this, this.pathInput.val());
}
this.close();
}
});
});

View file

@ -0,0 +1,99 @@
ig.module(
'weltmeister.select-file-dropdown'
)
.defines(function(){
wm.SelectFileDropdown = ig.Class.extend({
input: null,
boundShow: null,
div: null,
filelistPHP: '',
filetype: '',
init: function( elementId, filelistPHP, filetype ) {
this.filetype = filetype || '';
this.filelistPHP = filelistPHP;
this.input = $(elementId);
this.boundHide = this.hide.bind(this);
this.input.bind('focus', this.show.bind(this) );
this.div = $('<div/>', {'class':'selectFileDialog'});
this.input.after( this.div );
this.div.bind('mousedown', this.noHide.bind(this) );
this.loadDir( '' );
},
loadDir: function( dir ) {
var path = this.filelistPHP + '?dir=' + encodeURIComponent( dir || '' ) + '&type=' + this.filetype;
var req = $.ajax({
url:path,
dataType: 'json',
async: false,
success:this.showFiles.bind(this)
});
},
selectDir: function( event ) {
this.loadDir( $(event.target).attr('href') );
return false;
},
selectFile: function( event ) {
this.input.val( $(event.target).attr('href') );
this.input.blur();
this.hide();
return false;
},
showFiles: function( data ) {
this.div.empty();
if( data.parent !== false ) {
var parentDir = $('<a/>', {'class':'dir', href:data.parent, html: '&hellip;parent directory'});
parentDir.bind( 'click', this.selectDir.bind(this) );
this.div.append( parentDir );
}
for( var i = 0; i < data.dirs.length; i++ ) {
var name = data.dirs[i].match(/[^\/]*$/)[0] + '/';
var dir = $('<a/>', {'class':'dir', href:data.dirs[i], html: name, title: name});
dir.bind( 'click', this.selectDir.bind(this) );
this.div.append( dir );
}
for( var i = 0; i < data.files.length; i++ ) {
var name = data.files[i].match(/[^\/]*$/)[0];
var file = $('<a/>', {'class':'file', href:data.files[i], html: name, title: name});
file.bind( 'click', this.selectFile.bind(this) );
this.div.append( file );
}
},
noHide: function(event) {
event.stopPropagation();
},
show: function( event ) {
var inputPos = this.input.position();//this.input.getPosition(this.input.getOffsetParent());
var inputHeight = parseInt(this.input.innerHeight()) + parseInt(this.input.css('margin-top'));
var inputWidth = this.input.innerWidth();
$(document).bind( 'mousedown', this.boundHide );
this.div.css({
'top': inputPos.top + inputHeight + 1,
'left': inputPos.left,
'width': inputWidth
}).slideDown(100);
},
hide: function() {
$(document).unbind( 'mousedown', this.boundHide );
this.div.slideUp(100);
}
});
});

View file

@ -0,0 +1,144 @@
ig.module(
'weltmeister.tile-select'
)
.defines(function(){
wm.TileSelect = ig.Class.extend({
pos: {x:0, y:0},
layer: null,
selectionBegin: null,
init: function( layer ) {
this.layer = layer;
},
setPosition: function( x, y ) {
this.selectionBegin = null;
var tile = this.layer.currentTile - 1;
this.pos.x =
Math.floor( x / this.layer.tilesize ) * this.layer.tilesize
- Math.floor( tile * this.layer.tilesize ) % this.layer.tiles.width;
this.pos.y =
Math.floor( y / this.layer.tilesize ) * this.layer.tilesize
- Math.floor( tile * this.layer.tilesize / this.layer.tiles.width ) * this.layer.tilesize
- (tile == -1 ? this.layer.tilesize : 0);
this.pos.x = this.pos.x.limit( 0, ig.system.width - this.layer.tiles.width - (ig.system.width % this.layer.tilesize) );
this.pos.y = this.pos.y.limit( 0, ig.system.height - this.layer.tiles.height - (ig.system.height % this.layer.tilesize) );
},
beginSelecting: function( x, y ) {
this.selectionBegin = {x:x, y:y};
},
endSelecting: function( x, y ) {
var r = this.getSelectionRect( x, y);
var mw = Math.floor( this.layer.tiles.width / this.layer.tilesize );
var mh = Math.floor( this.layer.tiles.height / this.layer.tilesize );
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 >= mw || ty >= mh) {
row.push( 0 );
}
else {
row.push( ty * Math.floor(this.layer.tiles.width / this.layer.tilesize) + tx + 1 );
}
}
brush.push( row );
}
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.pos.x) / this.layer.tilesize ),
tyb = Math.floor( (sy - this.pos.y) / this.layer.tilesize ),
txe = Math.floor( (x - this.pos.x) / this.layer.tilesize ),
tye = Math.floor( (y - this.pos.y) / this.layer.tilesize );
return {
x: Math.min( txb, txe ),
y: Math.min( tyb, tye ),
w: Math.abs( txb - txe) + 1,
h: Math.abs( tyb - tye) + 1
}
},
draw: function() {
ig.system.clear( "rgba(0,0,0,0.8)" );
if( !this.layer.tiles.loaded ) {
return;
}
// Tileset
ig.system.context.lineWidth = 1;
ig.system.context.strokeStyle = wm.config.colors.secondary;
ig.system.context.fillStyle = wm.config.colors.clear;
ig.system.context.fillRect(
this.pos.x * ig.system.scale,
this.pos.y * ig.system.scale,
this.layer.tiles.width * ig.system.scale,
this.layer.tiles.height * ig.system.scale
);
ig.system.context.strokeRect(
this.pos.x * ig.system.scale - 0.5,
this.pos.y * ig.system.scale - 0.5,
this.layer.tiles.width * ig.system.scale + 1,
this.layer.tiles.height * ig.system.scale + 1
);
this.layer.tiles.draw( this.pos.x, this.pos.y );
// Selected Tile
var tile = this.layer.currentTile - 1;
var tx = Math.floor( tile * this.layer.tilesize ) % this.layer.tiles.width + this.pos.x;
var ty =
Math.floor( tile * this.layer.tilesize / this.layer.tiles.width )
* this.layer.tilesize + this.pos.y
+ (tile == -1 ? this.layer.tilesize : 0);
ig.system.context.lineWidth = 1;
ig.system.context.strokeStyle = wm.config.colors.highlight;
ig.system.context.strokeRect(
tx * ig.system.scale - 0.5,
ty * ig.system.scale - 0.5,
this.layer.tilesize * ig.system.scale + 1,
this.layer.tilesize * ig.system.scale + 1
);
},
drawCursor: function( x, y ) {
var cx = Math.floor( x / this.layer.tilesize ) * this.layer.tilesize;
var cy = Math.floor( y / this.layer.tilesize ) * this.layer.tilesize;
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.layer.tilesize + this.pos.x) * ig.system.scale - 0.5,
(r.y * this.layer.tilesize + this.pos.y) * ig.system.scale - 0.5,
r.w * this.layer.tilesize * ig.system.scale + 1,
r.h * this.layer.tilesize * ig.system.scale + 1
);
}
});
});

234
dev/lib/weltmeister/undo.js Executable file
View file

@ -0,0 +1,234 @@
ig.module(
'weltmeister.undo'
)
.requires(
'weltmeister.config'
)
.defines(function(){
wm.Undo = ig.Class.extend({
levels: 10,
chain: [],
rpos: 0,
currentAction: null,
init: function( levels ) {
this.levels = levels || 10;
},
clear: function() {
this.chain = [];
this.currentAction = null;
},
commit: function( action ) {
if( this.rpos ) {
this.chain.splice( this.chain.length - this.rpos, this.rpos );
this.rpos = 0;
}
action.activeLayer = ig.game.activeLayer ? ig.game.activeLayer.name : '';
this.chain.push( action );
if( this.chain.length > this.levels ) {
this.chain.shift();
}
},
undo: function() {
var action = this.chain[ this.chain.length - this.rpos - 1 ];
if( !action ) {
return;
}
this.rpos++;
ig.game.setActiveLayer( action.activeLayer );
if( action.type == wm.Undo.MAP_DRAW ) {
for( var i = 0; i < action.changes.length; i++ ) {
var change = action.changes[i];
change.layer.setTile( change.x, change.y, change.old );
}
}
else if( action.type == wm.Undo.ENTITY_EDIT ) {
action.entity.pos.x = action.old.x;
action.entity.pos.y = action.old.y;
action.entity.size.x = action.old.w;
action.entity.size.y = action.old.h;
ig.game.entities.selectEntity( action.entity );
ig.game.entities.loadEntitySettings();
}
else if( action.type == wm.Undo.ENTITY_CREATE ) {
ig.game.entities.removeEntity( action.entity );
ig.game.entities.selectEntity( null );
}
else if( action.type == wm.Undo.ENTITY_DELETE ) {
ig.game.entities.entities.push( action.entity );
if( action.entity.name ) {
this.namedEntities[action.entity.name] = action.entity;
}
ig.game.entities.selectEntity( action.entity );
}
ig.game.setModified();
},
redo: function() {
if( !this.rpos ) {
return;
}
var action = this.chain[ this.chain.length - this.rpos ];
if( !action ) {
return;
}
this.rpos--;
ig.game.setActiveLayer( action.activeLayer );
if( action.type == wm.Undo.MAP_DRAW ) {
for( var i = 0; i < action.changes.length; i++ ) {
var change = action.changes[i];
change.layer.setTile( change.x, change.y, change.current );
}
}
else if( action.type == wm.Undo.ENTITY_EDIT ) {
action.entity.pos.x = action.current.x;
action.entity.pos.y = action.current.y;
action.entity.size.x = action.current.w;
action.entity.size.y = action.current.h;
ig.game.entities.selectEntity( action.entity );
ig.game.entities.loadEntitySettings();
}
else if( action.type == wm.Undo.ENTITY_CREATE ) {
ig.game.entities.entities.push( action.entity );
if( action.entity.name ) {
this.namedEntities[action.entity.name] = action.entity;
}
ig.game.entities.selectEntity( action.entity );
}
else if( action.type == wm.Undo.ENTITY_DELETE ) {
ig.game.entities.removeEntity( action.entity );
ig.game.entities.selectEntity( null );
}
ig.game.setModified();
},
// -------------------------------------------------------------------------
// Map changes
beginMapDraw: function( layer ) {
this.currentAction = {
type: wm.Undo.MAP_DRAW,
time: Date.now(),
changes: []
};
},
pushMapDraw: function( layer, x, y, oldTile, currentTile ) {
if( !this.currentAction ) {
return;
}
this.currentAction.changes.push({
layer: layer,
x: x,
y: y,
old: oldTile,
current: currentTile
});
},
endMapDraw: function() {
if( !this.currentAction || !this.currentAction.changes.length ) {
return;
}
this.commit( this.currentAction );
this.currentAction = null;
},
// -------------------------------------------------------------------------
// Entity changes
beginEntityEdit: function( entity ) {
this.currentAction = {
type: wm.Undo.ENTITY_EDIT,
time: Date.now(),
entity: entity,
old: {
x: entity.pos.x,
y: entity.pos.y,
w: entity.size.x,
h: entity.size.y
},
current: {
x: entity.pos.x,
y: entity.pos.y,
w: entity.size.x,
h: entity.size.y
}
};
},
pushEntityEdit: function( entity ) {
if( !this.currentAction ) {
return;
}
this.currentAction.current = {
x: entity.pos.x,
y: entity.pos.y,
w: entity.size.x,
h: entity.size.y
};
},
endEntityEdit: function() {
var a = this.currentAction;
if( !a || (
a.old.x == a.current.x && a.old.y == a.current.y &&
a.old.w == a.current.w && a.old.h == a.current.h
)) {
return;
}
this.commit( this.currentAction );
this.currentAction = null;
},
commitEntityCreate: function( entity ) {
this.commit({
type: wm.Undo.ENTITY_CREATE,
time: Date.now(),
entity: entity
});
},
commitEntityDelete: function( entity ) {
this.commit({
type: wm.Undo.ENTITY_DELETE,
time: Date.now(),
entity: entity
});
}
});
wm.Undo.MAP_DRAW = 1;
wm.Undo.ENTITY_EDIT = 2;
wm.Undo.ENTITY_CREATE = 3;
wm.Undo.ENTITY_DELETE = 4;
});

View file

@ -0,0 +1,477 @@
body {
background-color: #000;
color: #fff;
font-family: sans-serif;
font-size: 10pt;
margin: 0px;
overflow: hidden;
text-shadow: 0px 1px 1px rgba(0,0,0,0.5);
-webkit-font-smoothing: antialiased;
-webkit-user-select: none;
}
h2 {
margin: 0 0 4px 0;
padding: 4px 0 4px 6px;
background-color: #000;
font-size: 100%;
color: #555;
xtext-transform: uppercase;
xborder-bottom: 1px solid #555;
}
h3 {
margin: 0;
font-size: 100%;
display: block;
}
dt {
margin: 0;
padding: 4px 0 0 6px;
display:inline;
float:left;
margin-right:5px;
}
dd {
margin: 0;
padding: 2px 0 8px 6px;
}
dl {
margin:0;
}
div.clear {
clear: both;
}
label {
cursor: pointer;
}
/* --- Input ------------------------------------------------------------------ */
input {
background-color: rgba(0,0,0,0.5);
border: 1px solid rgb(50,50,50);
color: #fff;
margin: 0;
font-family: sans-serif;
-webkit-font-smoothing: antialiased;
font-size: 10pt;
outline: none;
text-shadow: 0px 1px 1px rgba(0,0,0,0.5);
}
input:focus{
border: 1px solid rgb(200,200,200);
}
input.text {
padding: 1px;
margin: 0;
}
input.number {
width: 30px;
text-align: right;
}
input.button {
font-size: 90%;
padding-left: 13px;
padding-right: 13px;
padding-top: 5px;
padding-bottom: 5px;
color: #fff;
font-weight: bold;
background-color: rgba(255,255,255,0.1);
border:none;
border-top: 1px solid rgba(255,255,255,0.1);
border-bottom: 1px solid rgba(0,0,0,0.1);
cursor: pointer;
-webkit-transition: 0.1s linear;
}
input.button:hover {
background-color: rgba(255,255,255,0.2);
}
input.button:active {
background-color: rgba(255,255,255,0.3);
}
input.text#layerName {
width:140px;
}
input.text#layerTileset {
width:138px;
}
input#levelSaveAs { margin-right: 10px; }
input#levelLoad { margin-right: 10px; }
input#reloadImages {margin-right: 10px;}
input:disabled {
background-color: #555;
color: #888;
}
/* --- Layout ------------------------------------------------------------------ */
#editor {
margin: 0px;
position: relative;
}
#canvas {
image-rendering: optimizeSpeed;
-webkit-interpolation-mode: nearest-neighbor;
}
#menu {
width: 200px;
float: right;
position:absolute;
top:0px;
right:0px;
}
/* --- Layers ------------------------------------------------------------------ */
#layerContainer {
background-color: rgba(0,0,0,0.95);
padding-right:2px;
}
#layers {
max-height: 200px;
overflow: auto;
}
#layerButtons div.button#buttonAddLayer {
position:absolute;
right: 0px;
top:-5px;
cursor: pointer;
padding: 10px;
color:rgba(255,255,255,0.5);
font-weight: bold;
font-size:110%;
margin-left:1px;
-webkit-transition: 0.1s linear;
-webkit-font-smoothing: none;
z-index:10;
}
#layerButtons div.button#buttonAddLayer:hover { color:rgba(255,255,255,1);}
#layerButtons div.button#buttonAddLayer:active { color:rgba(255,255,255,1); text-shadow:none;}
.layer {
padding: 6px 4px;
cursor: pointer;
-webkit-transition: background-color 0.1s linear;
border-top: 1px solid rgba(255,255,255,0);
border-bottom: 1px solid rgba(255,255,255,0);
}
.layer:hover {
background-color: rgba(255,255,255,0.1);
border-top: 1px solid rgba(255,255,255,0.1);
border-bottom: 1px solid rgba(255,255,255,0.1);
}
.layer:active {
background-color: rgba(255,255,255,0.2);
border-top: 1px solid rgba(255,255,255,0.2);
border-bottom: 1px solid rgba(255,255,255,0.2);
}
.layerActive {
background-color: rgba(255,255,255,0.1);
border-top: 1px solid rgba(255,255,255,0.2);
border-bottom: 1px solid rgba(255,255,255,0.2) !important;
}
#layerEntities { border-bottom: 1px solid #000; }
.layer .visible {
background-color: rgba(255,255,255,0.2);
text-indent: -99999px;
display: inline-block;
width: 10px;
height: 10px;
margin-right: 7px;
margin-left: 4px;
-webkit-transition: 0.1s linear;
}
.layer .visible.specialVis{
margin-right: 2px;
}
.layer .checkedVis{ background-color: rgba(255,255,255,1); }
.layer span.size { font-size: 75%; color: rgba(255,255,255,0.7); }
#layerSettings {
background-color: rgba(0,0,0,0.95);
padding-top: 5px;
margin-top: 1px;
display: none;
}
/* --- Entities ------------------------------------------------------------------ */
h3#entityClass {
border-bottom: 1px solid rgba(255,255,255,0.2);
padding: 5px;
padding-left: 10px;
}
#entitySettings {
background-color: rgba(0,0,0,0.95);
margin-top: 1px;
display: none;
}
#entityDefinitions {
max-height: 220px;
overflow: auto;
}
div.entityDefinition {
color: #aaa;
padding: 2px 0;
border-bottom: 1px solid rgba(255,255,255,0.2);
cursor: pointer;
}
div.entityDefinition:hover {
background-color: rgba(255,255,255,0.1);
}
div.entityDefinition .key {
width: 50%;
display: block;
float: left;
margin: 0 0px 0 0;
padding: 0;
text-align: right;
color: #fff;
overflow: hidden;
}
div.entityDefinition .value {
padding: 0 0 0 2px;
color: #fff;
}
dl#entityDefinitionInput {
padding: 8px 0;
}
dl#entityDefinitionInput dt {
width: 40px;
display: block;
float: left;
margin: 0 4px 0 0;
padding: 4px 0 0 0;
text-align: right;
}
dl#entityDefinitionInput dd {
display: block;
margin: 0;
padding: 2px 0;
}
#entityKey, #entityValue {
}
#entityMenu {
background-color: rgba(0,0,0,0.9);
display: none;
position: absolute;
min-width: 100px;
max-height:300px;
overflow-y: scroll;
-webkit-box-shadow:0px 0px 10px rgba(0,0,0,1);
z-index: 1000;
}
#entityMenu div {
padding: 3px;
padding-left: 8px;
color: #fff;
cursor: pointer;
border-top: 1px solid rgba(255,255,255,0);
border-bottom: 1px solid rgba(255,255,255,0);
-webkit-transition: 0.1s linear;
}
#entityMenu div:hover {
background-color: rgba(255,255,255,0.2);
border-top: 1px solid rgba(255,255,255,0.2);
border-bottom: 1px solid rgba(255,255,255,0.2);
}
/* --- Dialogs ------------------------------------------------------------------ */
.selectFileDialog {
background-color: rgba(0,0,0,0.9);
border: 1px solid white;
border-top: 1px solid rgba(255,255,255,0.4);
display: none;
position: absolute;
overflow: hidden;
-webkit-box-shadow: 0px 0px 10px rgba(0,0,0,1);
max-height: 300px;
overflow-y: scroll;
}
.selectFileDialog a {
padding: 4px;
color: #fff;
display: block;
text-decoration: none;
border-top: 1px solid rgba(255,255,255,0);
border-bottom: 1px solid rgba(255,255,255,0);
}
.selectFileDialog a:hover {
background-color: rgba(255,255,255,0.2);
border-top: 1px solid rgba(255,255,255,0.2);
border-bottom: 1px solid rgba(255,255,255,0.2);
}
div.modalDialogBackground {
background-color: rgba(0,0,0,0.7);
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
display: none;
z-index: 100;
}
div.modalDialogBox {
width: 300px;
margin-left: -170px;
background-color: rgba(0,0,0,0.9);
border: 1px solid rgb(100,100,100);
-webkit-box-shadow: 0px 0px 10px rgba(0,0,0,1);
position: absolute;
top: 20%;
left: 50%;
padding: 20px;
}
div.modalDialogText {
font-size: 180%;
font-weight: bold;
}
div.modalDialogButtons {
margin-top: 20px;
text-align: right;
}
div.modalDialogButtons input.button {
min-width: 100px;
text-align: center;
margin-left: 10px;
}
input.modalDialogPath {
margin-top: 20px;
width: 100%;
outline: none;
}
input.modalDialogPath:focus {
outline: none;
border: 1px solid rgb(100,100,100);
}
#headerMenu {
position:relative;
z-index:10;
height:47px;
width:100%;
background: #131314;
background: -webkit-gradient(linear, left bottom, left top, color-stop(0,#000000), color-stop(1,#2e3033));
background: -moz-linear-gradient(center bottom, #000000 0%, #2e3033 100%);
background: -o-linear-gradient(#2e3033, #000000);
}
#headerMenu span.headerTitle {
display:inline-block;
font-weight:bold;
font-size:200%;
padding-left:20px;
padding-top:7px;
color:rgba(0,0,0,0.1);
text-shadow:0px -1px 0px rgba(255,255,255,0.4);
}
#headerMenu span.unsavedTitle {
display:inline-block;
font-weight:bold;
font-size:240%;
padding-left:0px;
color:#cc0000;
text-shadow:0px 1px 1px rgba(0,0,0,0.1);
}
#headerMenu span.headerFloat {
float: right;
}
input#toggleSidebar {
width: 200px;
height: 47px;
text-indent: -99999px;
background: url(arrow.png) 50% -37px no-repeat;
-webkit-transition: 0s linear;
opacity: 0.25;
padding: 0px;
}
input#toggleSidebar.active{
background-position: 50% 10px;
}
input[type="checkbox"] {
position: relative;
margin: 0;
border: 0;
width: 10px;
height: 10px;
display: inline-block;
-webkit-appearance: none;
-webkit-transition: 0.1s linear;
}
input[type="checkbox"] {
background-color:rgba(255,255,255,0.2);
}
input[type="checkbox"]:checked {
background-color: rgba(255,255,255,1);
}
input[type="checkbox"]:hover {
cursor: pointer;
}
input[type="checkbox"]:disabled {
background-color: rgba(255,255,255,0.1);
}
::-webkit-scrollbar { width: 2px; }
::-webkit-scrollbar-button:start:decrement,
::-webkit-scrollbar-button:end:increment { display: block; height: 2px; }
::-webkit-scrollbar-button:vertical:increment { background-color: transparent; }
::-webkit-scrollbar-track-piece { background-color: rgba(0,0,0,0); }
::-webkit-scrollbar-thumb:vertical { background-color: rgba(255,255,255,1); }

View file

@ -0,0 +1,880 @@
var wm = {};
wm.entityFiles = [];
ig.module(
'weltmeister.weltmeister'
)
.requires(
'dom.ready',
'impact.game',
'weltmeister.evented-input',
'weltmeister.config',
'weltmeister.edit-map',
'weltmeister.edit-entities',
'weltmeister.select-file-dropdown',
'weltmeister.modal-dialogs',
'weltmeister.undo'
)
.defines(function() {
wm.Weltmeister = ig.Class.extend({
MODE: {
DRAW: 1,
TILESELECT: 2,
ENTITYSELECT: 4
},
layers: [],
entities: null,
activeLayer: null,
collisionLayer: null,
selectedEntity: null,
screen: {x: 0, y: 0},
_rscreen: {x: 0, y: 0},
mouseLast: {x: -1, y: -1},
waitForModeChange: false,
tilsetSelectDialog: null,
levelSavePathDialog: null,
rot: 0,
collisionSolid: 1,
loadDialog: null,
saveDialog: null,
loseChangesDialog: null,
fileName: 'untitled.js',
filePath: wm.config.project.levelPath + 'untitled.js',
modified: false,
undo: null,
init: function() {
ig.game = ig.editor = this;
ig.system.context.textBaseline = 'top';
ig.system.context.font = wm.config.labels.font;
// Dialogs
this.loadDialog = new wm.ModalDialogPathSelect( 'Load Level', 'Load', 'scripts' );
this.loadDialog.onOk = this.load.bind(this);
this.loadDialog.setPath( wm.config.project.levelPath );
$('#levelLoad').bind( 'click', this.showLoadDialog.bind(this) );
$('#levelNew').bind( 'click', this.showNewDialog.bind(this) );
this.saveDialog = new wm.ModalDialogPathSelect( 'Save Level', 'Save', 'scripts' );
this.saveDialog.onOk = this.save.bind(this);
this.saveDialog.setPath( wm.config.project.levelPath );
$('#levelSaveAs').bind( 'click', this.saveDialog.open.bind(this.saveDialog) );
$('#levelSave').bind( 'click', this.saveQuick.bind(this) );
this.loseChangesDialog = new wm.ModalDialog( 'Lose all changes?' );
this.deleteLayerDialog = new wm.ModalDialog( 'Delete Layer? NO UNDO!' );
this.deleteLayerDialog.onOk = this.removeLayer.bind(this);
this.mode = this.MODE.DEFAULT;
this.tilesetSelectDialog = new wm.SelectFileDropdown( '#layerTileset', wm.config.api.browse, 'images' );
this.entities = new wm.EditEntities( $('#layerEntities') );
$('#layers').sortable({
update: this.reorderLayers.bind(this)
});
$('#layers').disableSelection();
this.resetModified();
// Events/Input
for( key in wm.config.binds ) {
ig.input.bind( ig.KEY[key], wm.config.binds[key] );
}
ig.input.keydownCallback = this.keydown.bind(this);
ig.input.keyupCallback = this.keyup.bind(this);
ig.input.mousemoveCallback = this.mousemove.bind(this);
$(window).resize( this.resize.bind(this) );
$(window).bind( 'keydown', this.uikeydown.bind(this) );
$(window).bind( 'beforeunload', this.confirmClose.bind(this) );
$('#buttonAddLayer').bind( 'click', this.addLayer.bind(this) );
$('#buttonRemoveLayer').bind( 'click', this.deleteLayerDialog.open.bind(this.deleteLayerDialog) );
$('#buttonSaveLayerSettings').bind( 'click', this.saveLayerSettings.bind(this) );
$('#reloadImages').bind( 'click', ig.Image.reloadCache );
$('#layerIsCollision').bind( 'change', this.toggleCollisionLayer.bind(this) );
$('input#toggleSidebar').click(function() {
$('div#menu').slideToggle('fast');
$('input#toggleSidebar').toggleClass('active');
});
this.undo = new wm.Undo( wm.config.undoLevels );
if( wm.config.loadLastLevel ) {
var path = $.cookie('wmLastLevel');
if( path ) {
this.load( null, path )
}
}
},
uikeydown: function( event ) {
if( event.target.type == 'text' ) {
return;
}
var key = String.fromCharCode(event.which);
if( key.match(/^\d$/) ) {
var index = parseInt(key);
var name = $('#layers div.layer:nth-child('+index+') span.name').text();
var layer = name == 'entities'
? this.entities
: this.getLayerWithName(name);
if( layer ) {
if( event.shiftKey ) {
layer.toggleVisibility();
} else {
this.setActiveLayer( layer.name );
}
}
}
},
showLoadDialog: function() {
if( this.modified ) {
this.loseChangesDialog.onOk = this.loadDialog.open.bind(this.loadDialog);
this.loseChangesDialog.open();
} else {
this.loadDialog.open();
}
},
showNewDialog: function() {
if( this.modified ) {
this.loseChangesDialog.onOk = this.loadNew.bind(this);
this.loseChangesDialog.open();
} else {
this.loadNew();
}
},
setModified: function() {
if( !this.modified ) {
this.modified = true;
this.setWindowTitle();
}
},
resetModified: function() {
this.modified = false;
this.setWindowTitle();
},
setWindowTitle: function() {
document.title = this.fileName + (this.modified ? ' * ' : ' - ') + 'Weltmeister';
$('span.headerTitle').text(this.fileName);
$('span.unsavedTitle').text(this.modified ? '*' : '');
},
confirmClose: function( event ) {
var rv = undefined;
if( this.modified && wm.config.askBeforeClose ) {
rv = 'There are some unsaved changes. Leave anyway?';
}
event.returnValue = rv;
return rv;
},
resize: function() {
ig.system.resize(
Math.floor(wm.Weltmeister.getMaxWidth() / wm.config.view.zoom),
Math.floor(wm.Weltmeister.getMaxHeight() / wm.config.view.zoom),
wm.config.view.zoom
);
ig.system.context.textBaseline = 'top';
ig.system.context.font = wm.config.labels.font;
this.draw();
},
// -------------------------------------------------------------------------
// Loading
loadNew: function() {
while( this.layers.length ) {
this.layers[0].destroy();
this.layers.splice( 0, 1 );
}
this.screen = {x: 0, y: 0};
this.entities.clear();
this.fileName = 'untitled.js';
this.filePath = wm.config.project.levelPath + 'untitled.js';
this.saveDialog.setPath( this.filePath );
this.resetModified();
this.draw();
},
load: function( dialog, path ) {
$.cookie( 'wmLastLevel', path );
this.filePath = path;
this.saveDialog.setPath( path );
this.fileName = path.replace(/^.*\//,'');
var req = $.ajax({
url:( path + '?nocache=' + Math.random() ),
dataType: 'text',
async:false,
success:this.loadResponse.bind(this)
});
},
loadResponse: function( data ) {
// extract JSON from a module's JS
var jsonMatch = data.match( /\/\*JSON\[\*\/([\s\S]*?)\/\*\]JSON\*\// );
data = $.parseJSON( jsonMatch ? jsonMatch[1] : data );
while( this.layers.length ) {
this.layers[0].destroy();
this.layers.splice( 0, 1 );
}
this.screen = {x: 0, y: 0};
this.entities.clear();
for( var i=0; i < data.entities.length; i++ ) {
var ent = data.entities[i];
this.entities.spawnEntity( ent.type, ent.x, ent.y, ent.settings );
}
for( var i=0; i < data.layer.length; i++ ) {
var ld = data.layer[i];
var newLayer = new wm.EditMap( ld.name, ld.tilesize, ld.tilesetName, !!ld.foreground );
newLayer.resize( ld.width, ld.height );
newLayer.linkWithCollision = ld.linkWithCollision;
newLayer.repeat = ld.repeat;
newLayer.preRender = !!ld.preRender;
newLayer.distance = ld.distance;
newLayer.visible = !ld.visible;
newLayer.data = ld.data;
newLayer.toggleVisibility();
this.layers.push( newLayer );
if( ld.name == 'collision' ) {
this.collisionLayer = newLayer;
}
this.setActiveLayer( ld.name );
}
this.setActiveLayer( 'entities' );
this.reorderLayers();
$('#layers').sortable('refresh');
this.resetModified();
this.undo.clear();
this.draw();
},
// -------------------------------------------------------------------------
// Saving
saveQuick: function() {
if( this.fileName == 'untitled.js' ) {
this.saveDialog.open();
}
else {
this.save( null, this.filePath );
}
},
save: function( dialog, path ) {
this.filePath = path;
this.fileName = path.replace(/^.*\//,'');
var data = {
'entities': this.entities.getSaveData(),
'layer': []
};
var resources = [];
for( var i=0; i < this.layers.length; i++ ) {
var layer = this.layers[i];
data.layer.push( layer.getSaveData() );
if( layer.name != 'collision' ) {
resources.push( layer.tiles.path );
}
}
var dataString = $.toJSON(data);
if( wm.config.project.prettyPrint ) {
dataString = JSONFormat( dataString );
}
// Make it an ig.module instead of plain JSON?
if( wm.config.project.outputFormat == 'module' ) {
var levelModule = path
.replace(wm.config.project.modulePath, '')
.replace(/\.js$/, '')
.replace(/\//g, '.');
var levelName = levelModule.replace(/^.*\.(\w)(\w*)$/, function( m, a, b ) {
return a.toUpperCase() + b;
});
var resourcesString = '';
if( resources.length ) {
resourcesString = "Level" + levelName + "Resources=[new ig.Image('" +
resources.join("'), new ig.Image('") +
"')];\n";
}
// Collect all Entity Modules
var requires = ['impact.image'];
for( var i = 0; i < data.entities.length; i++ ) {
requires.push(
this.entities.entityClasses[ data.entities[i].type ]
);
}
// include /*JSON[*/ ... /*]JSON*/ markers, so we can easily load
// this level as JSON again
dataString =
"ig.module( '"+levelModule+"' )\n" +
".requires('"+requires.join("','")+"')\n" +
".defines(function(){\n"+
"Level" + levelName + "=" +
"/*JSON[*/" + dataString + "/*]JSON*/" +
";\n" +
resourcesString +
"});";
}
var postString =
'path=' + encodeURIComponent( path ) +
'&data=' + encodeURIComponent(dataString);
var req = $.ajax({
url: wm.config.api.save,
type: 'POST',
dataType: 'json',
async: false,
data: postString,
success:this.saveResponse.bind(this)
});
},
saveResponse: function( data ) {
if( data.error ) {
alert( 'Error: ' + data.msg );
} else {
this.resetModified();
}
},
// -------------------------------------------------------------------------
// Layers
addLayer: function() {
var name = 'new_layer_' + this.layers.length;
var newLayer = new wm.EditMap( name, wm.config.layerDefaults.tilesize );
newLayer.resize( wm.config.layerDefaults.width, wm.config.layerDefaults.height );
newLayer.setScreenPos( this.screen.x, this.screen.y );
this.layers.push( newLayer );
this.setActiveLayer( name );
this.updateLayerSettings();
this.reorderLayers();
$('#layers').sortable('refresh');
},
removeLayer: function() {
var name = this.activeLayer.name;
if( name == 'entities' ) {
return false;
}
this.activeLayer.destroy();
for( var i = 0; i < this.layers.length; i++ ) {
if( this.layers[i].name == name ) {
this.layers.splice( i, 1 );
this.reorderLayers();
$('#layers').sortable('refresh');
this.setActiveLayer( 'entities' );
return true;
}
}
return false;
},
getLayerWithName: function( name ) {
for( var i = 0; i < this.layers.length; i++ ) {
if( this.layers[i].name == name ) {
return this.layers[i];
}
}
return null;
},
reorderLayers: function( dir ) {
var newLayers = [];
var isForegroundLayer = true;
$('#layers div.layer span.name').each((function( newIndex, span ){
var name = $(span).text();
var layer = name == 'entities'
? this.entities
: this.getLayerWithName(name);
if( layer ) {
layer.setHotkey( newIndex+1 );
if( layer.name == 'entities' ) {
// All layers after the entity layer are not foreground
// layers
isForegroundLayer = false;
}
else {
layer.foreground = isForegroundLayer;
newLayers.unshift( layer );
}
}
}).bind(this));
this.layers = newLayers;
this.setModified();
this.draw();
},
updateLayerSettings: function( ) {
$('#layerName').val( this.activeLayer.name );
$('#layerTileset').val( this.activeLayer.tilesetName );
$('#layerTilesize').val( this.activeLayer.tilesize );
$('#layerWidth').val( this.activeLayer.width );
$('#layerHeight').val( this.activeLayer.height );
$('#layerPreRender').attr( 'checked', this.activeLayer.preRender ? 'checked' : '' );
$('#layerRepeat').attr( 'checked', this.activeLayer.repeat ? 'checked' : '' );
$('#layerLinkWithCollision').attr( 'checked', this.activeLayer.linkWithCollision ? 'checked' : '' );
$('#layerDistance').val( this.activeLayer.distance );
},
saveLayerSettings: function() {
var isCollision = $('#layerIsCollision').attr('checked') ? true : false;
var newName = $('#layerName').val();
var newWidth = Math.floor($('#layerWidth').val());
var newHeight = Math.floor($('#layerHeight').val());
if( newWidth != this.activeLayer.width || newHeight != this.activeLayer.height ) {
this.activeLayer.resize( newWidth, newHeight );
}
this.activeLayer.tilesize = Math.floor($('#layerTilesize').val());
if( isCollision ) {
newName = 'collision';
this.activeLayer.linkWithCollision = false;
this.activeLayer.distance = 1;
this.activeLayer.repeat = false;
this.activeLayer.setCollisionTileset();
}
else {
var newTilesetName = $('#layerTileset').val();
if( newTilesetName != this.activeLayer.tilesetName ) {
this.activeLayer.setTileset( newTilesetName );
}
this.activeLayer.linkWithCollision = $('#layerLinkWithCollision').attr('checked') ? true : false;
this.activeLayer.distance = $('#layerDistance').val();
this.activeLayer.repeat = $('#layerRepeat').attr('checked') ? true : false;
this.activeLayer.preRender = $('#layerPreRender').attr('checked') ? true : false;
}
if( newName == 'collision' ) {
// is collision layer
this.collisionLayer = this.activeLayer;
}
else if( this.activeLayer.name == 'collision' ) {
// was collision layer, but is no more
this.collisionLayer = null;
}
this.activeLayer.setName( newName );
this.setModified();
this.draw();
},
setActiveLayer: function( name ) {
var previousLayer = this.activeLayer;
this.activeLayer = ( name == 'entities' ? this.entities : this.getLayerWithName(name) );
if( previousLayer == this.activeLayer ) {
return; // nothing to do here
}
if( previousLayer ) {
previousLayer.setActive( false );
}
this.activeLayer.setActive( true );
this.mode = this.MODE.DEFAULT;
$('#layerIsCollision').attr('checked', (name == 'collision') );
if( name == 'entities' ) {
$('#layerSettings').fadeOut(100);
}
else {
this.entities.selectEntity( null );
this.toggleCollisionLayer();
$('#layerSettings')
.fadeOut(100,this.updateLayerSettings.bind(this))
.fadeIn(100);
}
this.draw();
},
toggleCollisionLayer: function( ev ) {
var isCollision = $('#layerIsCollision').attr('checked') ? true : false;
$('#layerLinkWithCollision,#layerDistance,#layerPreRender,#layerRepeat,#layerName,#layerTileset')
.attr('disabled', isCollision );
},
// -------------------------------------------------------------------------
// Update
mousemove: function() {
if( !this.activeLayer ) {
return;
}
if( this.mode == this.MODE.DEFAULT ) {
// scroll map
if( ig.input.state('drag') ) {
this.screen.x -= ig.input.mouse.x - this.mouseLast.x;
this.screen.y -= ig.input.mouse.y - this.mouseLast.y;
this._rscreen.x = Math.round(this.screen.x * ig.system.scale)/ig.system.scale;
this._rscreen.y = Math.round(this.screen.y * ig.system.scale)/ig.system.scale;
for( var i = 0; i < this.layers.length; i++ ) {
this.layers[i].setScreenPos( this.screen.x, this.screen.y );
}
}
else if( ig.input.state('draw') ) {
// move/scale entity
if( this.activeLayer == this.entities ) {
var x = ig.input.mouse.x + this.screen.x;
var y = ig.input.mouse.y + this.screen.y;
this.entities.dragOnSelectedEntity( x, y );
this.setModified();
}
// draw on map
else if( !this.activeLayer.isSelecting ) {
this.setTileOnCurrentLayer();
}
}
else if( this.activeLayer == this.entities ) {
var x = ig.input.mouse.x + this.screen.x;
var y = ig.input.mouse.y + this.screen.y;
this.entities.mousemove( x, y );
}
}
this.mouseLast = {x: ig.input.mouse.x, y: ig.input.mouse.y};
this.draw();
},
keydown: function( action ) {
if( !this.activeLayer ) {
return;
}
if( action == 'draw' ) {
if( this.mode == this.MODE.DEFAULT ) {
// select entity
if( this.activeLayer == this.entities ) {
var x = ig.input.mouse.x + this.screen.x;
var y = ig.input.mouse.y + this.screen.y;
var entity = this.entities.selectEntityAt( x, y );
if( entity ) {
this.undo.beginEntityEdit( entity );
}
}
else {
if( ig.input.state('select') ) {
this.activeLayer.beginSelecting( ig.input.mouse.x, ig.input.mouse.y );
}
else {
this.undo.beginMapDraw();
this.activeLayer.beginEditing();
if(
this.activeLayer.linkWithCollision &&
this.collisionLayer &&
this.collisionLayer != this.activeLayer
) {
this.collisionLayer.beginEditing();
}
this.setTileOnCurrentLayer();
}
}
}
else if( this.mode == this.MODE.TILESELECT && ig.input.state('select') ) {
this.activeLayer.tileSelect.beginSelecting( ig.input.mouse.x, ig.input.mouse.y );
}
}
this.draw();
},
keyup: function( action ) {
if( !this.activeLayer ) {
return;
}
if( action == 'delete' ) {
this.entities.deleteSelectedEntity();
this.setModified();
}
else if( action == 'clone' ) {
this.entities.cloneSelectedEntity();
this.setModified();
}
else if( action == 'grid' ) {
wm.config.view.grid = !wm.config.view.grid;
}
else if( action == 'menu' ) {
if( this.mode != this.MODE.TILESELECT && this.mode != this.MODE.ENTITYSELECT ) {
if( this.activeLayer == this.entities ) {
this.mode = this.MODE.ENTITYSELECT;
this.entities.showMenu( ig.input.mouse.x, ig.input.mouse.y );
}
else {
this.mode = this.MODE.TILESELECT;
this.activeLayer.tileSelect.setPosition( ig.input.mouse.x, ig.input.mouse.y );
}
} else {
this.mode = this.MODE.DEFAULT;
this.entities.hideMenu();
}
}
if( action == 'draw' ) {
// select tile
if( this.mode == this.MODE.TILESELECT ) {
this.activeLayer.brush = this.activeLayer.tileSelect.endSelecting( ig.input.mouse.x, ig.input.mouse.y );
this.mode = this.MODE.DEFAULT;
}
else if( this.activeLayer == this.entities ) {
this.undo.endEntityEdit();
}
else {
if( this.activeLayer.isSelecting ) {
this.activeLayer.brush = this.activeLayer.endSelecting( ig.input.mouse.x, ig.input.mouse.y );
}
else {
this.undo.endMapDraw();
}
}
}
if( action == 'undo' ) {
this.undo.undo();
}
if( action == 'redo' ) {
this.undo.redo();
}
this.draw();
this.mouseLast = {x: ig.input.mouse.x, y: ig.input.mouse.y};
},
setTileOnCurrentLayer: function() {
if( !this.activeLayer || !this.activeLayer.scroll ) {
return;
}
var co = this.activeLayer.getCursorOffset();
var x = ig.input.mouse.x + this.activeLayer.scroll.x - co.x;
var y = ig.input.mouse.y + this.activeLayer.scroll.y - co.y;
var brush = this.activeLayer.brush;
for( var by = 0; by < brush.length; by++ ) {
var brushRow = brush[by];
for( var bx = 0; bx < brushRow.length; bx++ ) {
var mapx = x + bx * this.activeLayer.tilesize;
var mapy = y + by * this.activeLayer.tilesize;
var newTile = brushRow[bx];
var oldTile = this.activeLayer.getOldTile( mapx, mapy );
this.activeLayer.setTile( mapx, mapy, newTile );
this.undo.pushMapDraw( this.activeLayer, mapx, mapy, oldTile, newTile );
if(
this.activeLayer.linkWithCollision &&
this.collisionLayer &&
this.collisionLayer != this.activeLayer
) {
var collisionLayerTile = newTile > 0 ? this.collisionSolid : 0;
var oldCollisionTile = this.collisionLayer.getOldTile(mapx, mapy);
this.collisionLayer.setTile( mapx, mapy, collisionLayerTile );
this.undo.pushMapDraw( this.collisionLayer, mapx, mapy, oldCollisionTile, collisionLayerTile );
}
}
}
this.setModified();
},
// -------------------------------------------------------------------------
// Drawing
draw: function() {
ig.system.clear( wm.config.colors.clear );
var entitiesDrawn = false;
for( var i = 0; i < this.layers.length; i++ ) {
layer = this.layers[i];
// This layer is a foreground layer? -> Draw entities first!
if( !entitiesDrawn && layer.foreground ) {
entitiesDrawn = true;
this.entities.draw();
}
layer.draw();
}
if( !entitiesDrawn ) {
this.entities.draw();
}
if( this.activeLayer ) {
if( this.mode == this.MODE.TILESELECT ) {
this.activeLayer.tileSelect.draw();
this.activeLayer.tileSelect.drawCursor( ig.input.mouse.x, ig.input.mouse.y );
}
if( this.mode == this.MODE.DEFAULT ) {
this.activeLayer.drawCursor( ig.input.mouse.x, ig.input.mouse.y );
}
}
if( wm.config.labels.draw ) {
this.drawLabels( wm.config.labels.step );
}
},
drawLabels: function( step ) {
ig.system.context.fillStyle = wm.config.colors.primary;
var xlabel = this.screen.x - this.screen.x % step - step;
for( var tx = Math.floor(-this.screen.x % step); tx < ig.system.width; tx += step ) {
xlabel += step;
ig.system.context.fillText( xlabel, tx * ig.system.scale, 0 );
}
var ylabel = this.screen.y - this.screen.y % step - step;
for( var ty = Math.floor(-this.screen.y % step); ty < ig.system.height; ty += step ) {
ylabel += step;
ig.system.context.fillText( ylabel, 0, ty * ig.system.scale );
}
},
getEntityByName: function( name ) {
return this.entities.getEntityByName( name );
}
});
wm.Weltmeister.getMaxWidth = function() {
return $(window).width();
};
wm.Weltmeister.getMaxHeight = function() {
return $(window).height() - $('#headerMenu').height();
};
// Create a custom loader, to skip sound files and the run loop creation
wm.Loader = ig.Loader.extend({
end: function() {
if( this.done ) { return; }
clearInterval( this._intervalId );
this.done = true;
ig.system.clear( wm.config.colors.clear );
ig.game = new (this.gameClass)();
},
loadResource: function( res ) {
if( res instanceof ig.Sound ) {
this._unloaded.erase( res.path );
}
else {
this.parent( res );
}
}
});
// Init!
ig.system = new ig.System(
'#canvas', 1,
Math.floor(wm.Weltmeister.getMaxWidth() / wm.config.view.zoom),
Math.floor(wm.Weltmeister.getMaxHeight() / wm.config.view.zoom),
wm.config.view.zoom
);
ig.input = new wm.EventedInput();
ig.soundManager = new ig.SoundManager();
ig.ready = true;
var loader = new wm.Loader( wm.Weltmeister, ig.resources );
loader.load();
});

BIN
dev/media/04b03.font.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

21
dev/tools/bake.bat Executable file
View file

@ -0,0 +1,21 @@
@echo off
:: Path to impact.js and your game's main .js
SET IMPACT_LIBRARY=lib/impact/impact.js
SET GAME=lib/game/main.js
:: Output file
SET OUTPUT_FILE=game.min.js
:: Change CWD to Impact's base dir and bake!
cd ../
php tools/bake.php %IMPACT_LIBRARY% %GAME% %OUTPUT_FILE%
:: If you dont have the php.exe in your PATH uncomment the
:: following line and point it to your php.exe
::c:/php/php.exe bake.php %IMPACT_LIBRARY% %GAME% %OUTPUT_FILE%
pause

157
dev/tools/bake.php Executable file
View file

@ -0,0 +1,157 @@
<?php
if( count($argv) < 3 ) {
echo "Usage: bake.php <in...> <out>\n";
echo "e.g. bake.php lib/impact/impact.js lib/game/game.js mygame-baked.js\n";
die;
}
$inFiles = array_slice( $argv, 1, -1 );
$outFile = $argv[ count($argv)-1 ];
$baker = new Baker( Baker::MINIFIED );
$baker->bake( $inFiles, $outFile );
class Baker {
const PLAIN = 0;
const MINIFIED = 1;
const GZIPPED = 2;
protected $base = 'lib/';
protected $format = 0;
protected $loaded = array();
protected $currentInput = 'Command Line';
protected $fileCount = 0, $bytesIn = 0, $bytesOut = 0;
public function __construct( $format = 0 ) {
$this->format = $format;
if( $this->format & self::MINIFIED ) {
require_once( 'jsmin.php' );
}
}
public function bake( $inFiles, $outFile ) {
$this->fileCount = 0;
$this->bytesIn = 0;
$out = "/*! Built with IMPACT - impactjs.com */\n\n";
foreach( $inFiles as $f ) {
$out .= $this->load( $f );
}
$bytesOut = strlen($out);
$bytesOutZipped = 0;
echo "writing $outFile\n";
@file_put_contents( $outFile, $out ) or
die("ERROR: Couldn't write to $outFile\n");
if( $this->format & self::GZIPPED ) {
$gzFile = "$outFile.gz";
echo "writing $gzFile\n";
$fh = gzopen( $gzFile, 'w9' ) or
die("ERROR: Couldn't write to $gzFile\n");
gzwrite( $fh, $out );
gzclose( $fh );
$bytesOutZipped = filesize( $gzFile );
}
echo
"\nbaked {$this->fileCount} files: ".
round($this->bytesIn/1024,1)."kb -> ".round($bytesOut/1024,1)."kb" .
( $this->format & self::GZIPPED
? " (".round($bytesOutZipped/1024,1)."kb gzipped)\n"
: "\n"
);
}
protected function load( $path ) {
if( isset($this->loaded[$path]) ) {
return '';
}
if( !file_exists($path) ) {
die("ERROR: Couldn't load $path required from {$this->currentInput}\n");
}
echo "loading $path \n";
$this->loaded[$path] = true;
$this->currentInput = $path;
$code = file_get_contents( $path );
$this->bytesIn += strlen($code);
$this->fileCount++;
if( $this->format & self::MINIFIED ) {
$code = trim(JSMin::minify($code));
}
// Naively probe the file for 'ig.module().requires().defines()' code;
// the 'requries()' part will be handled by the regexp callback
$this->definesModule = false;
$code = preg_replace_callback(
'/ig\s*
\.\s*module\s*\((.*?)\)\s*
(\.\s*requires\s*\((.*?)\)\s*)?
\.\s*defines\s*\(
/smx',
array($this,'loadCallback'),
$code
);
// All files should define a module; maybe we just missed it? Print a
// friendly reminder :)
if( !$this->definesModule ) {
echo "WARNING: file $path seems to define no module!\n";
}
return $code;
}
protected function loadCallback( $matches ) {
$currentInput = $this->currentInput;
$this->definesModule = true;
$moduleName = $matches[1];
$requiredFiles = isset($matches[3]) ? $matches[3] : '';
$requiredCode = '';
if( $requiredFiles ) {
// Explode the module names and map them to file names. Ignore the
// dom.ready module if present
$moduleFiles = array_diff(
explode(
',',
preg_replace(
'/[\s\'"]|\/\/.*|\/\*.*\*\//', // strip quotes and spaces
'',
str_replace('.', '/', $requiredFiles ) // . to /
)
),
array('dom/ready')
);
foreach( $moduleFiles as $f ) {
$requiredCode .= $this->load( $this->base . $f.'.js' );
}
}
return
$requiredCode .
"\n\n// $currentInput\n" .
'ig.baked=true;' .
'ig.module('.$moduleName.')' .
( $requiredFiles
? '.requires('.$requiredFiles.')'
: ''
) .
'.defines(';
}
}
?>

13
dev/tools/bake.sh Executable file
View file

@ -0,0 +1,13 @@
#!/bin/bash
# Path to impact.js and your game's main .js
IMPACT_LIBRARY=lib/impact/impact.js
GAME=lib/game/main.js
# Output file
OUTPUT_FILE=game.min.js
# Change CWD to Impact's base dir and bake!
cd ..
php tools/bake.php $IMPACT_LIBRARY $GAME $OUTPUT_FILE

291
dev/tools/jsmin.php Executable file
View file

@ -0,0 +1,291 @@
<?php
/**
* jsmin.php - PHP implementation of Douglas Crockford's JSMin.
*
* This is pretty much a direct port of jsmin.c to PHP with just a few
* PHP-specific performance tweaks. Also, whereas jsmin.c reads from stdin and
* outputs to stdout, this library accepts a string as input and returns another
* string as output.
*
* PHP 5 or higher is required.
*
* Permission is hereby granted to use this version of the library under the
* same terms as jsmin.c, which has the following license:
*
* --
* Copyright (c) 2002 Douglas Crockford (www.crockford.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is furnished to do
* so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* The Software shall be used for Good, not Evil.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* --
*
* @package JSMin
* @author Ryan Grove <ryan@wonko.com>
* @copyright 2002 Douglas Crockford <douglas@crockford.com> (jsmin.c)
* @copyright 2008 Ryan Grove <ryan@wonko.com> (PHP port)
* @license http://opensource.org/licenses/mit-license.php MIT License
* @version 1.1.1 (2008-03-02)
* @link http://code.google.com/p/jsmin-php/
*/
class JSMin {
const ORD_LF = 10;
const ORD_SPACE = 32;
protected $a = '';
protected $b = '';
protected $input = '';
protected $inputIndex = 0;
protected $inputLength = 0;
protected $lookAhead = null;
protected $output = '';
// -- Public Static Methods --------------------------------------------------
public static function minify($js) {
$jsmin = new JSMin($js);
return $jsmin->min();
}
// -- Public Instance Methods ------------------------------------------------
public function __construct($input) {
$this->input = str_replace("\r\n", "\n", $input);
$this->inputLength = strlen($this->input);
}
// -- Protected Instance Methods ---------------------------------------------
protected function action($d) {
switch($d) {
case 1:
$this->output .= $this->a;
case 2:
$this->a = $this->b;
if ($this->a === "'" || $this->a === '"') {
for (;;) {
$this->output .= $this->a;
$this->a = $this->get();
if ($this->a === $this->b) {
break;
}
if (ord($this->a) <= self::ORD_LF) {
throw new JSMinException('Unterminated string literal.');
}
if ($this->a === '\\') {
$this->output .= $this->a;
$this->a = $this->get();
}
}
}
case 3:
$this->b = $this->next();
if ($this->b === '/' && (
$this->a === '(' || $this->a === ',' || $this->a === '=' ||
$this->a === ':' || $this->a === '[' || $this->a === '!' ||
$this->a === '&' || $this->a === '|' || $this->a === '?')) {
$this->output .= $this->a . $this->b;
for (;;) {
$this->a = $this->get();
if ($this->a === '/') {
break;
} elseif ($this->a === '\\') {
$this->output .= $this->a;
$this->a = $this->get();
} elseif (ord($this->a) <= self::ORD_LF) {
throw new JSMinException('Unterminated regular expression '.
'literal.');
}
$this->output .= $this->a;
}
$this->b = $this->next();
}
}
}
protected function get() {
$c = $this->lookAhead;
$this->lookAhead = null;
if ($c === null) {
if ($this->inputIndex < $this->inputLength) {
$c = $this->input[$this->inputIndex];
$this->inputIndex += 1;
} else {
$c = null;
}
}
if ($c === "\r") {
return "\n";
}
if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) {
return $c;
}
return ' ';
}
protected function isAlphaNum($c) {
return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1;
}
protected function min() {
$this->a = "\n";
$this->action(3);
while ($this->a !== null) {
switch ($this->a) {
case ' ':
if ($this->isAlphaNum($this->b)) {
$this->action(1);
} else {
$this->action(2);
}
break;
case "\n":
switch ($this->b) {
case '{':
case '[':
case '(':
case '+':
case '-':
$this->action(1);
break;
case ' ':
$this->action(3);
break;
default:
if ($this->isAlphaNum($this->b)) {
$this->action(1);
}
else {
$this->action(2);
}
}
break;
default:
switch ($this->b) {
case ' ':
if ($this->isAlphaNum($this->a)) {
$this->action(1);
break;
}
$this->action(3);
break;
case "\n":
switch ($this->a) {
case '}':
case ']':
case ')':
case '+':
case '-':
case '"':
case "'":
$this->action(1);
break;
default:
if ($this->isAlphaNum($this->a)) {
$this->action(1);
}
else {
$this->action(3);
}
}
break;
default:
$this->action(1);
break;
}
}
}
return $this->output;
}
protected function next() {
$c = $this->get();
if ($c === '/') {
switch($this->peek()) {
case '/':
for (;;) {
$c = $this->get();
if (ord($c) <= self::ORD_LF) {
return $c;
}
}
case '*':
$this->get();
for (;;) {
switch($this->get()) {
case '*':
if ($this->peek() === '/') {
$this->get();
return ' ';
}
break;
case null:
throw new JSMinException('Unterminated comment.');
}
}
default:
return $c;
}
}
return $c;
}
protected function peek() {
$this->lookAhead = $this->get();
return $this->lookAhead;
}
}
// -- Exceptions ---------------------------------------------------------------
class JSMinException extends Exception {}
?>

96
dev/weltmeister.html Executable file
View file

@ -0,0 +1,96 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Weltmeister</title>
<link rel="stylesheet" type="text/css" href="lib/weltmeister/weltmeister.css"/>
<script src="lib/weltmeister/jquery-1.4.2.min.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/weltmeister/jquery-ui-1.8.1.custom.min.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/impact/impact.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/weltmeister/weltmeister.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="headerMenu">
<span class="headerTitle"></span>
<span class="unsavedTitle"></span>
<span class="headerFloat">
<input type="button" id="levelSave" value="Save" class="button"/>
<input type="button" id="levelSaveAs" value="Save As" class="button"/>
<input type="button" id="levelNew" value="New" class="button"/>
<input type="button" id="levelLoad" value="Load" class="button"/>
<input type="button" id="reloadImages" value="Reload Images" title="Reload Images" class="button"/>
<input type="button" id="toggleSidebar" value="Toggle Sidebar" title="Toggle Sidebar" class="button"/>
</span>
</div>
<div id="editor">
<div id="entityMenu"></div>
<canvas id="canvas"></canvas>
<div id="menu">
<div id="layerContainer">
<h2>Layers</h2>
<div id="layerButtons">
<div class="button" id="buttonAddLayer" title="Add Layer">+</div>
</div>
<div id="layers">
<div id="layerEntities" class="layer">
<span class="visible specialVis checkedVis" title="Toggle Visibility (Shift+0)"></span>
<span class="name">entities</span>
</div>
</div>
</div>
<div id="layerSettings">
<h2>Layer Settings</h2>
<dl>
<dt>Name:</dt><dd><input type="text" class="text" id="layerName"/></dd>
<dt>Tileset:</dt><dd><input type="text" class="text" id="layerTileset"/></dd>
<dt>Tilesize:</dt><dd><input type="text" class="number" id="layerTilesize"/></dd>
<dt>Dimensions:</dt>
<dd>
<input type="text" class="number" id="layerWidth"/> &times; <input type="text" class="number" id="layerHeight"/>
</dd>
<dt>Distance:</dt><dd><input type="text" class="number" id="layerDistance"/></dd>
<dd>
<input type="checkbox" id="layerIsCollision"/>
<label for="layerIsCollision">Is Collision Layer</label>
</dd>
<dd>
<input type="checkbox" id="layerPreRender"/>
<label for="layerPreRender">Pre-Render in Game</label>
</dd>
<dd>
<input type="checkbox" id="layerRepeat"/>
<label for="layerRepeat">Repeat</label>
</dd>
<dd>
<input type="checkbox" id="layerLinkWithCollision"/>
<label for="layerLinkWithCollision">Link with Collision</label>
</dd>
<dd>
<input type="button" id="buttonSaveLayerSettings" value="Apply Changes" class="button"/>
<input type="button" id="buttonRemoveLayer" value="Delete" class="button"/>
</dd>
</dl>
</div>
<div id="entitySettings">
<h2>Entity Settings</h2>
<h3 id="entityClass">EntityClassName</h3>
<div id="entityDefinitions">
<div class="entityDefinition"><span class="key">x</span>:<span class="value">188</span></div>
<div class="entityDefinition"><span class="key">y</span>:<span class="value">269</span></div>
</div>
<dl id="entityDefinitionInput">
<dt>Key:</dt><dd><input type="text" class="text" id="entityKey"/></dd>
<dt>Value:</dt><dd><input type="text" class="text" id="entityValue"/></dd>
</dl>
</div>
</div>
</div>
</body>
</html>