Rollmorad/tools/editor/js/RllmrdLevelEditr.js
2015-11-15 23:18:06 +00:00

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 + ' &nbsp; &nbsp; &nbsp;';
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 + ' &nbsp; &nbsp; &nbsp;';
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);
}