569 lines
17 KiB
JavaScript
569 lines
17 KiB
JavaScript
RllmrdLevelEditr = function(_editor) {
|
|
|
|
var that = this;
|
|
|
|
that.data = '../../data/';
|
|
that.currentTile = 0;
|
|
that.tilePainting = false;
|
|
that.erasing = false;
|
|
that.tiles = {};
|
|
that.layers = {};
|
|
that.currentLayer = 0;
|
|
that.nextLayer = 1;
|
|
that.level = {}
|
|
|
|
that.tileSize = 64;
|
|
that.tileSetSize = 1024;
|
|
that.zoom = 0.5;
|
|
|
|
that.width = 0;
|
|
that.height = 0;
|
|
|
|
that.defaultImageLayer = {
|
|
id: 0,
|
|
type: 'imagelayer',
|
|
z: 0.0,
|
|
imageFilename: '',
|
|
imageOffset: '',
|
|
tiling: '',
|
|
movement: '',
|
|
color: '',
|
|
};
|
|
|
|
that.defaultTilemapLayer = {
|
|
id: 0,
|
|
tileSetFilename: '',
|
|
visible: 1,
|
|
enablePhysics: 1,
|
|
type: 'tilemaplayer',
|
|
z: 0
|
|
};
|
|
|
|
that.defaultLevel = {
|
|
name: '',
|
|
size: '(40, 15)',
|
|
backgroundColor: '(1.0, 1.0, 1.0, 1.0)',
|
|
gravity: '(0.0, 9.81)',
|
|
musicFilename: '',
|
|
supportedGameModes: 'GM_STORY',
|
|
};
|
|
|
|
that.editor = _editor;
|
|
|
|
that.addImageLayer = function() {
|
|
var layerID = that.nextLayer++;
|
|
that.layers[layerID] = {};
|
|
for (var z in that.defaultImageLayer) {
|
|
that.layers[layerID][z] = that.defaultImageLayer[z];
|
|
}
|
|
that.layers[layerID].id = layerID;
|
|
that.updateLayerList();
|
|
return false;
|
|
}
|
|
|
|
that.addTilemapLayer = function(layerID) {
|
|
if (typeof layerID == 'undefined') {
|
|
layerID = that.nextLayer++;
|
|
var grid = [];
|
|
for (var y = 0; y < that.height; ++y) {
|
|
grid[y] = [];
|
|
for (var x = 0; x < that.width; ++x) {
|
|
grid[y][x] = 0;
|
|
}
|
|
}
|
|
that.layers[layerID] = {};
|
|
for (var z in that.defaultTilemapLayer) {
|
|
that.layers[layerID][z] = that.defaultTilemapLayer[z];
|
|
}
|
|
that.layers[layerID].id = layerID;
|
|
that.layers[layerID].grid = grid;
|
|
}
|
|
that.updateLayerList();
|
|
that.selectLayer(layerID);
|
|
var div = document.getElementById('layer_' + layerID);
|
|
if (div) {
|
|
div.parentNode.removeChild(div);
|
|
}
|
|
var html = '<div class="layer" id="layer_' + layerID + '"><table border="0" cellspacing="0" cellpadding="0">';
|
|
for (var y = 0; y < that.height; ++y) {
|
|
html += '<tr>';
|
|
for (var x = 0; x < that.width; ++x) {
|
|
html += '<td><div id="box_' + layerID + '_' + y + '_' + x + '" onclick="return RLE.applyTile(event)" onmouseover="return RLE.hoverBox(event)" onmousemove="return RLE.hoverBox(event)" onmousedown="return RLE.applyTile(event)" style="width: ' + parseInt(that.tileSize * that.zoom) + 'px; height: ' + parseInt(that.tileSize * that.zoom) + 'px;">'
|
|
var tile = that.tiles[parseInt(that.layers[layerID].grid[y][x])];
|
|
if (tile) {
|
|
html += '<img src="' + that.data + "tilesets/" + tile.filename + '" style="' + 'top: -' + parseInt(tile.posY * that.zoom) + 'px; left: -' + parseInt(tile.posX * that.zoom) + 'px; width: ' + parseInt(that.tileSetSize * that.zoom) + 'px; height: ' + parseInt(that.tileSetSize * that.zoom) + 'px;" onmousedown="return false;" />';
|
|
}
|
|
html += '</div></td>';
|
|
}
|
|
html += '</tr>';
|
|
}
|
|
html += '</table></div>';
|
|
that.editor.innerHTML += html;
|
|
return false;
|
|
}
|
|
|
|
that.deleteLayer = function(id) {
|
|
if (!confirm("Wirklich?")) return;
|
|
delete that.layers[id];
|
|
var elem = document.getElementById('layer_' + id);
|
|
if (elem) {
|
|
elem.parentNode.removeChild(elem);
|
|
}
|
|
that.updateLayerList();
|
|
return false;
|
|
}
|
|
|
|
that.layerComparator = function(a, b) {
|
|
return that.layers[a].z - that.layers[b].z;
|
|
}
|
|
|
|
that.getLayerOrder = function() {
|
|
var ids = [];
|
|
for (var i in that.layers) {
|
|
ids.push(i);
|
|
}
|
|
ids.sort(that.layerComparator);
|
|
return ids;
|
|
}
|
|
|
|
that.updateLayerList = function() {
|
|
var layerlist = document.getElementById('layers').getElementsByTagName('div')[0];
|
|
var html = '';
|
|
var layerOrder = that.getLayerOrder();
|
|
for (var j = 0; j < layerOrder.length; ++j) {
|
|
var i = layerOrder[j];
|
|
html += '<div id="layerselector_' + i + '"';
|
|
if (i == that.currentLayer) {
|
|
html += ' style="background-color: #ffc;"';
|
|
}
|
|
html += '>';
|
|
var refLayer;
|
|
switch (that.layers[i].type) {
|
|
case 'imagelayer':
|
|
html += i + ': image';
|
|
refLayer = that.defaultImageLayer;
|
|
break;
|
|
case 'tilemaplayer':
|
|
html += '<a href="#" onclick="return RLE.selectLayer(' + i + ')">' + i + ': tilemap</a>';
|
|
refLayer = that.defaultTilemapLayer;
|
|
break;
|
|
}
|
|
html += ' [<a href="#" onclick="return RLE.toggle(\'editlayer_' + i + '\');">edit</a>] ';
|
|
html += ' [<a href="#" onclick="return RLE.deleteLayer(' + i + ');">entf.</a>]';
|
|
html += '<div id="editlayer_' + i + '" style="display: none;">';
|
|
html += '<form action="#" onsubmit="return RLE.updateLayer(this);">';
|
|
html += '<input type="hidden" name="__layerid" value="' + i + '" >';
|
|
for (var z in refLayer) {
|
|
if (z == 'grid' || z == 'objects' || z == 'type') {
|
|
continue;
|
|
}
|
|
html += '<label for="editlayer_' + i + '_' + z + '">' + z + ': </label>';
|
|
html += '<input type="text" id="editlayer_' + i + '_' + z + '" name="' + z + '" value="' + (that.layers[i][z] || refLayer[z]) + '"/><br />';
|
|
}
|
|
html += '<input type="submit" value="Speichern" />';
|
|
html += '</form>';
|
|
html += '</div>';
|
|
html += '</div>';
|
|
}
|
|
layerlist.innerHTML = html;
|
|
}
|
|
|
|
that.updateLayer = function(form) {
|
|
var layerInfo = {};
|
|
for (var i = 0; i < form.elements.length; ++i) {
|
|
var e = form.elements[i];
|
|
if (e.id) {
|
|
layerInfo[e.name] = e.value;
|
|
}
|
|
}
|
|
if (!layerInfo.id || !that.layers[layerInfo.id]) {
|
|
return false;
|
|
}
|
|
for (var i in layerInfo) {
|
|
that.layers[layerInfo.id][i] = layerInfo[i];
|
|
}
|
|
that.updateLayerList();
|
|
that.selectLayer(layerInfo.id);
|
|
return false;
|
|
}
|
|
|
|
that.selectLayer = function(id) {
|
|
if (that.layers[id].type != 'tilemaplayer') {
|
|
return false;
|
|
}
|
|
var elem = document.getElementById('layerselector_' + that.currentLayer);
|
|
if (elem) {
|
|
that.toggle2('layer_' + that.currentLayer);
|
|
elem.style.backgroundColor = '';
|
|
}
|
|
that.currentLayer = id;
|
|
that.toggle2('layer_' + that.currentLayer);
|
|
that.loadTileset(that.data + "tilesets/" + that.layers[that.currentLayer].tileSetFilename, true);
|
|
document.getElementById('layerselector_' + that.currentLayer).style.backgroundColor = '#ffc';
|
|
return false;
|
|
}
|
|
|
|
that.hoverBox = function(event) {
|
|
var ret = that.applyTile(event);
|
|
var box = event.currentTarget;
|
|
var info = /box_(\d+)_(\d+)_(\d+)/.exec(box.getAttribute('id'));
|
|
if (!info) {
|
|
return ret;
|
|
}
|
|
|
|
var layerID = info[1];
|
|
var y = parseInt(info[2]);
|
|
var x = parseInt(info[3]);
|
|
|
|
var html = '<strong>Tile</strong> ' + that.layers[layerID].grid[y][x] + ' @ X: ' + x + ' Y: ' + y + ' ';
|
|
|
|
var levelX = x + parseFloat(event.layerX / that.zoom / that.tileSize);
|
|
var levelY = y + parseFloat(event.layerY / that.zoom / that.tileSize);
|
|
html += '<strong>Level</strong> X: ' + levelX + ' Y: ' + levelY + ' ';
|
|
|
|
document.getElementById('statusbar').innerHTML = html;
|
|
|
|
return ret;
|
|
}
|
|
|
|
that.setSize = function(width, height) {
|
|
if (width == that.width && height == that.height) {
|
|
// nothing changed
|
|
return;
|
|
}
|
|
|
|
that.width = width;
|
|
that.height = height;
|
|
|
|
for (var layerID in that.layers) {
|
|
var layer = that.layers[layerID];
|
|
if (layer.type != 'tilemaplayer') {
|
|
continue;
|
|
}
|
|
var grid = []
|
|
for (var y = 0; y < height; ++y) {
|
|
grid[y] = [];
|
|
for (var x = 0; x < width; ++x) {
|
|
if (layer.grid[y] && layer.grid[y][x]) {
|
|
grid[y][x] = layer.grid[y][x];
|
|
} else {
|
|
grid[y][x] = 0;
|
|
}
|
|
}
|
|
}
|
|
that.layers[layerID].grid = grid;
|
|
that.addTilemapLayer(layerID);
|
|
}
|
|
|
|
if (that.currentLayer) {
|
|
that.selectLayer(that.currentLayer);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
that.createLevelForm = function() {
|
|
var html = '<form action="#" id="level_info" onsubmit="return RLE.processLevelForm(this);">';
|
|
for (var z in that.defaultLevel) {
|
|
html += ' <label for="level_' + z + '">' + z + '</label>';
|
|
html += ' <input type="text" name="level_' + z + '" id="level_' + z + '" value="' + that.defaultLevel[z] + '" />';
|
|
html += ' <br />\n';
|
|
}
|
|
html += ' <input type="submit" value="Speichern" />';
|
|
html += '</form>';
|
|
document.getElementById('levelform').innerHTML = html;
|
|
}
|
|
|
|
that.processLevelForm = function(form) {
|
|
var info = {};
|
|
for (var z in that.defaultLevel) {
|
|
if (!form['level_' + z]) continue;
|
|
info[z] = form['level_' + z].value;
|
|
}
|
|
that.setLevelInfo(info);
|
|
return false;
|
|
}
|
|
|
|
that.setLevelInfo = function(info) {
|
|
that.level = info;
|
|
var size = /\((\d+), (\d+)\)/.exec(that.level.size);
|
|
if (size) {
|
|
that.setSize(size[1], size[2]);
|
|
}
|
|
var form = document.getElementById('level_info');
|
|
for (var z in info) {
|
|
form['level_' + z].value = that.level[z] || that.defaultLevel[z];
|
|
}
|
|
}
|
|
|
|
that.applyTile = function(event) {
|
|
if ((event.type == 'mouseover' || event.type == 'mousemove') && !that.tilePainting && !that.erasing) {
|
|
return false;
|
|
}
|
|
var element = event.currentTarget;
|
|
var box = /box_(\d+)_(\d+)_(\d+)/.exec(element.id);
|
|
if (!box || !box[1] || !box[2] || !box[3]) {
|
|
return false;
|
|
}
|
|
var layer = box[1];
|
|
var y = box[2];
|
|
var x = box[3];
|
|
|
|
if (event.button == 2 || that.erasing || that.currentTile == 'eraser') {
|
|
that.layers[layer].grid[y][x] = 0;
|
|
element.innerHTML = '';
|
|
return false;
|
|
}
|
|
that.layers[layer].grid[y][x] = that.currentTile;
|
|
var tile = that.tiles[that.currentTile];
|
|
element.innerHTML = '<img src="' + that.data + "tilesets/" + tile.filename + '" style="' + 'top: -' + parseInt(tile.posY * that.zoom) + 'px; left: -' + parseInt(tile.posX * that.zoom) + 'px; width: ' + parseInt(that.tileSetSize * that.zoom) + 'px; height: ' + parseInt(that.tileSetSize * that.zoom) + 'px;" onmousedown="return false;" />';
|
|
return false;
|
|
}
|
|
|
|
that.loadTileset = function(filename, silent) {
|
|
var ajax = new af_AJAX();
|
|
try {
|
|
var resp = ajax.getSync(filename);
|
|
} catch(e) {
|
|
alert(
|
|
'Tileset konnte nicht geladen werden!\n'
|
|
+ 'Um den Editor lokal zu benutzen, muss in die Adresszeile "about:config" eingegeben werden und dann\n'
|
|
+ '"security.fileuri.strict_origin_policy" auf false gesetzt werden.\n\n'
|
|
+ e
|
|
);
|
|
return;
|
|
}
|
|
if (!resp.responseXML) {
|
|
if (!silent) {
|
|
alert('Tileset konnte nicht geladen werden!');
|
|
}
|
|
return;
|
|
}
|
|
var tileset = resp.responseXML;
|
|
var root = tileset.getElementsByTagName('TileSet')[0];
|
|
if (!root) return
|
|
var img = root.getAttribute('imageFilename');
|
|
var tileDefs = tileset.getElementsByTagName('Tile');
|
|
|
|
var tileSelector = document.getElementById('tiles');
|
|
var html = '<div id="tile_eraser" onclick="return RLE.selectTile(\'eraser\');"></div>';
|
|
for (var i = 0; i < tileDefs.length; ++i) {
|
|
var pos = /(\d+), ?(\d+)/.exec(tileDefs[i].getAttribute('position'));
|
|
var id = parseInt(tileDefs[i].getAttribute('id'));
|
|
that.tiles[id] = { filename: img, posX: pos[1], posY: pos[2] };
|
|
html += '<div style="background: url(\'' + that.data + "tilesets/" + img + '\'); float: left; ';
|
|
html += 'background-position: -' + pos[1] + 'px -' + pos[2] + 'px;" ';
|
|
html += 'onclick="return RLE.selectTile(' + id + ');" id="tile_' + id + '"></div>';
|
|
}
|
|
tileSelector.innerHTML = html;
|
|
that.selectTile('eraser');
|
|
}
|
|
|
|
that.selectTile = function(id) {
|
|
var elem = document.getElementById('tile_' + that.currentTile)
|
|
if (elem) {
|
|
elem.style.borderColor = '';
|
|
}
|
|
that.currentTile = id;
|
|
document.getElementById('tile_' + that.currentTile).style.borderColor = '#f00';
|
|
return false;
|
|
}
|
|
|
|
that.loadLevel = function(filename) {
|
|
that.unloadLevel();
|
|
var file = that.data + "levels/" + filename;
|
|
var ajax = new af_AJAX;
|
|
try {
|
|
var resp = ajax.getSync(file);
|
|
} catch (e) {
|
|
alert(
|
|
'Level konnte nicht geladen werden!\n'
|
|
+ 'Um den Editor lokal zu benutzen, muss in die Adresszeile "about:config" eingegeben werden und dann\n'
|
|
+ '"security.fileuri.strict_origin_policy" auf false gesetzt werden.\n\n'
|
|
+ e
|
|
);
|
|
return;
|
|
}
|
|
var xml = resp.responseXML;
|
|
if (!xml) {
|
|
alert('Level konnte nicht geladen werden!');
|
|
return false;
|
|
}
|
|
document.getElementById('level_filename').value = filename;
|
|
var root = xml.getElementsByTagName('Level')[0];
|
|
|
|
that.setLevelInfo(that.getObjectFromAttributes(root.attributes));
|
|
|
|
var layers = xml.getElementsByTagName('Layers')[0].childNodes;
|
|
for (var n = 0; n < layers.length; ++n) {
|
|
var layer = layers[n];
|
|
switch (layer.tagName) {
|
|
case 'ImageLayer':
|
|
var layerAttributes = that.getObjectFromAttributes(layer.attributes);
|
|
layerAttributes.type = 'imagelayer';
|
|
that.layers[layerAttributes.id] = layerAttributes;
|
|
that.nextLayer = Math.max(that.nextLayer, parseInt(layerAttributes.id) + 1);
|
|
break;
|
|
case 'TileMapLayer':
|
|
var objects = layer.getElementsByTagName('Objects')[0];
|
|
var layerObjects = [];
|
|
if (objects) {
|
|
for (var i = 0; i < objects.childNodes.length; ++i) {
|
|
var object = objects.childNodes[i];
|
|
if (object.nodeType != 1) {
|
|
continue;
|
|
}
|
|
var obj = that.getObjectFromAttributes(objects.childNodes[i].attributes);
|
|
obj.__type = object.nodeName;
|
|
layerObjects.push(obj);
|
|
}
|
|
}
|
|
var rows = layer.getElementsByTagName('Row');
|
|
var i = 0;
|
|
var grid = [];
|
|
for (var y = 0; y < that.height; ++y) {
|
|
grid[y] = [];
|
|
var row = rows[i++].textContent.split(', ');
|
|
var j = 0;
|
|
for (var x = 0; x < that.width; ++x) {
|
|
grid[y][x] = (row[j++] - 0) || 0;
|
|
}
|
|
}
|
|
var layerAttributes = that.getObjectFromAttributes(layer.attributes);
|
|
layerAttributes.type = 'tilemaplayer';
|
|
layerAttributes.objects = layerObjects;
|
|
layerAttributes.grid = grid;
|
|
that.layers[layerAttributes.id] = layerAttributes;
|
|
that.nextLayer = Math.max(that.nextLayer, parseInt(layerAttributes.id) + 1);
|
|
that.addTilemapLayer(layerAttributes.id);
|
|
break;
|
|
}
|
|
}
|
|
that.updateLayerList();
|
|
return false;
|
|
}
|
|
|
|
that.unloadLevel = function() {
|
|
that.currentTile = 0;
|
|
that.tilePainting = false;
|
|
that.erasing = false;
|
|
that.tiles = {};
|
|
that.layers = {};
|
|
that.currentLayer = 0;
|
|
that.nextLayer = 1;
|
|
|
|
that.setLevelInfo(that.defaultLevel);
|
|
|
|
document.getElementById('tiles').innerHTML = '';
|
|
that.editor.innerHTML = '';
|
|
that.updateLayerList();
|
|
|
|
document.getElementById('level_filename').value = '';
|
|
|
|
return false;
|
|
}
|
|
|
|
that.saveLevel = function() {
|
|
var xml = '';
|
|
xml += '<?xml version="1.0" ?>\n';
|
|
xml += '<Level' + that.getAttributesFromObject(that.level) + '> \n';
|
|
xml += ' <Layers>\n';
|
|
for (var i in that.layers) {
|
|
var layer = that.layers[i];
|
|
switch (layer.type) {
|
|
case 'imagelayer':
|
|
xml += ' <ImageLayer' + that.getAttributesFromObject(layer, ['type']) + ' />\n';
|
|
break;
|
|
case 'tilemaplayer':
|
|
xml += ' <TileMapLayer' + that.getAttributesFromObject(layer, ['grid', 'objects', 'type']) + '>\n';
|
|
xml += ' <Objects>\n';
|
|
for (var i in layer.objects) {
|
|
var obj = layer.objects[i];
|
|
xml += ' <' + obj.__type + that.getAttributesFromObject(obj, ['__type']) + ' />\n';
|
|
}
|
|
xml += ' </Objects>\n';
|
|
for (var y = 0; y < that.height; y++) {
|
|
xml += ' <Row>' + layer.grid[y].join(', ') + '</Row>\n';
|
|
}
|
|
xml += ' </TileMapLayer>\n';
|
|
break;
|
|
}
|
|
}
|
|
xml += ' </Layers>\n';
|
|
xml += '</Level>\n';
|
|
|
|
var win = window.open('about:blank', 'rollmorad level editor output', '');
|
|
win.document.open('text/xml');
|
|
win.document.write(xml);
|
|
win.document.close();
|
|
}
|
|
|
|
that.getObjectFromAttributes = function(attributes) {
|
|
var obj = {};
|
|
for (var i = 0; i < attributes.length; ++i) {
|
|
obj[attributes[i].nodeName] = attributes[i].value;
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
that.getAttributesFromObject = function(object, exclude) {
|
|
var exc = {}
|
|
exclude = exclude || [];
|
|
for (var i = 0; i < exclude.length; ++i) {
|
|
exc[exclude[i]] = true;
|
|
}
|
|
var attributes = '';
|
|
for (var z in object) {
|
|
if (exc[z] || object[z] === '' || typeof object[z] == undefined) {
|
|
continue;
|
|
}
|
|
attributes += ' ' + z + '="' + object[z] + '"';
|
|
}
|
|
return attributes;
|
|
}
|
|
|
|
that.toggle2 = function(id) {
|
|
// return that.toggle(id)
|
|
var elem = document.getElementById(id)
|
|
if (!elem) return
|
|
if (elem.style.MozOpacity != 0.5) elem.style.MozOpacity = 0.5
|
|
else elem.style.MozOpacity = 1.0
|
|
if (elem.style.zIndex != 10) elem.style.zIndex = 10
|
|
else elem.style.zIndex = 100
|
|
return false
|
|
}
|
|
|
|
that.toggle = function(id) {
|
|
var elem = document.getElementById(id);
|
|
if (!elem) {
|
|
return;
|
|
}
|
|
if (elem.style.display != 'none') {
|
|
elem.style.display = 'none';
|
|
} else {
|
|
elem.style.display = '';
|
|
}
|
|
return false;
|
|
}
|
|
|
|
that.startTilePainting = function(event) {
|
|
if (event.button == 2) {
|
|
that.erasing = true;
|
|
} else {
|
|
that.tilePainting = true;
|
|
}
|
|
}
|
|
|
|
that.stopTilePainting = function(event) {
|
|
that.tilePainting = false;
|
|
that.erasing = false;
|
|
af_Events.stopEvent(event);
|
|
return false;
|
|
}
|
|
|
|
af_Events.addEventListener(window, 'mousedown', that.startTilePainting);
|
|
af_Events.addEventListener(window, 'mouseup', that.stopTilePainting);
|
|
that.createLevelForm();
|
|
that.setLevelInfo(that.defaultLevel);
|
|
}
|