added the raw impact licence into the "/dev" folder
This commit is contained in:
parent
0f4a2d7271
commit
6d6c98ddf2
47 changed files with 8488 additions and 0 deletions
32
dev/index.html
Executable file
32
dev/index.html
Executable 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
45
dev/lib/game/main.js
Executable 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
127
dev/lib/impact/animation.js
Executable 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
242
dev/lib/impact/background-map.js
Executable 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
258
dev/lib/impact/collision-map.js
Executable 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
148
dev/lib/impact/debug/debug.css
Executable 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
13
dev/lib/impact/debug/debug.js
Executable 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 */
|
||||
|
||||
});
|
129
dev/lib/impact/debug/entities-panel.js
Executable file
129
dev/lib/impact/debug/entities-panel.js
Executable 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'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
});
|
198
dev/lib/impact/debug/graph-panel.js
Executable file
198
dev/lib/impact/debug/graph-panel.js
Executable 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'
|
||||
});
|
||||
|
||||
|
||||
});
|
154
dev/lib/impact/debug/maps-panel.js
Executable file
154
dev/lib/impact/debug/maps-panel.js
Executable 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
292
dev/lib/impact/debug/menu.js
Executable 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
415
dev/lib/impact/entity.js
Executable 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
129
dev/lib/impact/font.js
Executable 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
304
dev/lib/impact/game.js
Executable 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
183
dev/lib/impact/image.js
Executable 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
476
dev/lib/impact/impact.js
Executable 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
308
dev/lib/impact/input.js
Executable 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
101
dev/lib/impact/loader.js
Executable 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
48
dev/lib/impact/map.js
Executable 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
333
dev/lib/impact/sound.js
Executable 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
116
dev/lib/impact/system.js
Executable 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
54
dev/lib/impact/timer.js
Executable 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;
|
||||
};
|
||||
|
||||
});
|
37
dev/lib/weltmeister/api/browse.php
Executable file
37
dev/lib/weltmeister/api/browse.php
Executable 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
|
||||
));
|
||||
|
||||
?>
|
22
dev/lib/weltmeister/api/config.php
Executable file
22
dev/lib/weltmeister/api/config.php
Executable 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 );
|
||||
}
|
||||
|
||||
?>
|
18
dev/lib/weltmeister/api/glob.php
Executable file
18
dev/lib/weltmeister/api/glob.php
Executable 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 );
|
||||
|
||||
?>
|
34
dev/lib/weltmeister/api/save.php
Executable file
34
dev/lib/weltmeister/api/save.php
Executable 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
BIN
dev/lib/weltmeister/arrow.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 717 B |
BIN
dev/lib/weltmeister/collisiontiles-64.png
Executable file
BIN
dev/lib/weltmeister/collisiontiles-64.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
72
dev/lib/weltmeister/config.js
Executable file
72
dev/lib/weltmeister/config.js
Executable 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'
|
||||
}
|
||||
};
|
||||
|
||||
});
|
667
dev/lib/weltmeister/edit-entities.js
Executable file
667
dev/lib/weltmeister/edit-entities.js
Executable 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
383
dev/lib/weltmeister/edit-map.js
Executable 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
56
dev/lib/weltmeister/entities.js
Executable 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
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
62
dev/lib/weltmeister/evented-input.js
Executable file
62
dev/lib/weltmeister/evented-input.js
Executable 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
405
dev/lib/weltmeister/jquery-1.4.2.min.js
vendored
Executable 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;
|
||||
}
|
||||
};
|
107
dev/lib/weltmeister/jquery-ui-1.8.1.custom.min.js
vendored
Executable file
107
dev/lib/weltmeister/jquery-ui-1.8.1.custom.min.js
vendored
Executable 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);
|
||||
;
|
108
dev/lib/weltmeister/modal-dialogs.js
Executable file
108
dev/lib/weltmeister/modal-dialogs.js
Executable 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();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
99
dev/lib/weltmeister/select-file-dropdown.js
Executable file
99
dev/lib/weltmeister/select-file-dropdown.js
Executable 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: '…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);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
144
dev/lib/weltmeister/tile-select.js
Executable file
144
dev/lib/weltmeister/tile-select.js
Executable 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
234
dev/lib/weltmeister/undo.js
Executable 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;
|
||||
|
||||
});
|
477
dev/lib/weltmeister/weltmeister.css
Executable file
477
dev/lib/weltmeister/weltmeister.css
Executable 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); }
|
880
dev/lib/weltmeister/weltmeister.js
Executable file
880
dev/lib/weltmeister/weltmeister.js
Executable 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
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
21
dev/tools/bake.bat
Executable 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
157
dev/tools/bake.php
Executable 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
13
dev/tools/bake.sh
Executable 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
291
dev/tools/jsmin.php
Executable 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
96
dev/weltmeister.html
Executable 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"/> × <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>
|
Loading…
Reference in a new issue