2022-09-17 16:50:08 +00:00
|
|
|
var QBCompiler = null;
|
|
|
|
// if code has been passed on the query string load it into the editor
|
|
|
|
var qbcode = "";
|
|
|
|
var url = location.href;
|
|
|
|
var sizeMode = "normal";
|
|
|
|
var appMode = "ide";
|
|
|
|
var consoleVisible = false;
|
|
|
|
var currTab = "js";
|
|
|
|
var editor;
|
|
|
|
var selectedError = null;
|
|
|
|
var currPath = "/";
|
2022-10-27 14:04:15 +00:00
|
|
|
var mainProg = null;
|
2022-09-17 16:50:08 +00:00
|
|
|
|
|
|
|
async function init() {
|
|
|
|
if (window.innerWidth < 1200) {
|
|
|
|
sizeMode = "max";
|
|
|
|
}
|
|
|
|
|
2022-10-27 14:04:15 +00:00
|
|
|
var srcUrl = null;
|
2022-09-17 16:50:08 +00:00
|
|
|
if (url && url.indexOf("?")) {
|
|
|
|
var queryString = url.substring(url.indexOf("?")+1);
|
|
|
|
var nvpairs = queryString.split("&");
|
|
|
|
for (var i = 0; i < nvpairs.length; i++) {
|
|
|
|
var nv = nvpairs[i].split("=");
|
|
|
|
if (nv[0] == "qbcode") {
|
|
|
|
var zin = new Shorty();
|
|
|
|
qbcode = zin.inflate(atob(nv[1]));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (nv[0] == "code") {
|
|
|
|
qbcode = LZUTF8.decompress(nv[1], { inputEncoding: "Base64" });
|
|
|
|
}
|
|
|
|
else if (nv[0] == "mode") {
|
|
|
|
appMode = nv[1];
|
|
|
|
}
|
|
|
|
else if (nv[0] == "src") {
|
2022-10-27 14:04:15 +00:00
|
|
|
srcUrl = nv[1];
|
|
|
|
}
|
|
|
|
else if (nv[0] == "main") {
|
|
|
|
mainProg = nv[1];
|
2022-09-17 16:50:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (appMode == "play") {
|
|
|
|
document.getElementById("gx-load-screen").style.display = "block";
|
|
|
|
}
|
|
|
|
|
|
|
|
// initialize the code editor
|
|
|
|
editor = CodeMirror(document.querySelector("#code"), {
|
|
|
|
lineNumbers: true,
|
|
|
|
tabSize: 4,
|
|
|
|
indentUnit: 4,
|
|
|
|
value: qbcode,
|
|
|
|
module: "qbjs",
|
|
|
|
theme: "qbjs",
|
|
|
|
height: "auto",
|
|
|
|
styleActiveLine: true,
|
|
|
|
smartIndent: false,
|
|
|
|
extraKeys: {
|
|
|
|
"Tab": function(cm) {
|
|
|
|
cm.replaceSelection(" ", "end");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
editor.setSize(600, 600);
|
|
|
|
editor.on("beforeChange", (cm, change) => {
|
|
|
|
if (change.origin === "paste") {
|
|
|
|
const newText = change.text.map(line => line.replace(/\t/g, " "));
|
|
|
|
change.update(null, null, newText);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
document.getElementsByClassName("CodeMirror-cursor")[0].innerHTML = " ";
|
|
|
|
|
2022-10-27 14:04:15 +00:00
|
|
|
|
|
|
|
if (srcUrl) {
|
|
|
|
var res = await fetch(nv[1]);
|
|
|
|
var contentType = res.headers.get("Content-Type");
|
|
|
|
if (contentType == "application/zip") {
|
|
|
|
// load a project
|
|
|
|
await loadProject(await res.arrayBuffer(), mainProg);
|
|
|
|
// TODO: shouldn't have to do this
|
|
|
|
//qbcode = editor.getValue();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// otherwise, assume a single source file
|
|
|
|
var decoder = new TextDecoder("iso-8859-1");
|
|
|
|
qbcode = decoder.decode(await res.arrayBuffer());
|
|
|
|
editor.setValue(qbcode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-17 16:50:08 +00:00
|
|
|
var warnCount = 0;
|
|
|
|
changeTab("console");
|
|
|
|
window.onresize();
|
|
|
|
|
|
|
|
if (appMode == "auto") {
|
|
|
|
runProgram();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function runProgram() {
|
|
|
|
document.getElementById("gx-load-screen").style.display = "none";
|
|
|
|
|
|
|
|
if (sizeMode == "max") {
|
|
|
|
slideLeft();
|
|
|
|
}
|
|
|
|
GX.reset();
|
|
|
|
QB.start();
|
|
|
|
var qbCode = editor.getValue();
|
|
|
|
if (!QBCompiler) { QBCompiler = await _QBCompiler(); }
|
|
|
|
var jsCode = await QBCompiler.compile(qbCode);
|
|
|
|
|
|
|
|
await displayWarnings();
|
|
|
|
|
|
|
|
var jsDiv = document.getElementById("js-code");
|
|
|
|
jsDiv.innerHTML = jsCode;
|
|
|
|
window.onresize();
|
|
|
|
|
|
|
|
try {
|
|
|
|
const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
|
|
|
|
var codeFn = new AsyncFunction(jsCode);
|
|
|
|
await codeFn();
|
|
|
|
}
|
|
|
|
catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
|
|
|
|
// find the source line, if possible
|
|
|
|
var srcLine = "";
|
|
|
|
if (error.line) {
|
|
|
|
srcLine = error.line - 1;
|
|
|
|
}
|
|
|
|
var stack = error.stack.split("\n");
|
|
|
|
for (var i=0; i < stack.length; i++) {
|
|
|
|
// chrome
|
|
|
|
if (stack[i].trim().startsWith("at eval (eval at runProgram")) {
|
|
|
|
var idx = stack[i].indexOf("<anonymous>:");
|
|
|
|
var pos = stack[i].substring(idx + 12);
|
|
|
|
pos = pos.substring(0, pos.length - 1);
|
|
|
|
pos = pos.split(":");
|
|
|
|
srcLine = pos[0] - 2;
|
|
|
|
}
|
|
|
|
// firefox
|
|
|
|
else if (stack[i].trim().indexOf("> AsyncFunction:") > -1) {
|
|
|
|
var idx = stack[i].indexOf("> AsyncFunction:");
|
|
|
|
var pos = stack[i].substring(idx + 16);
|
|
|
|
pos = pos.split(":");
|
|
|
|
srcLine = pos[0] - 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isNaN(srcLine)) {
|
|
|
|
srcLine = QBCompiler.getSourceLine(srcLine);
|
|
|
|
}
|
|
|
|
|
|
|
|
var table = document.getElementById("warning-table");
|
|
|
|
if (table) {
|
|
|
|
tr = document.createElement("tr");
|
|
|
|
addWarningCell(tr, "ERROR");
|
|
|
|
addWarningCell(tr, ":");
|
|
|
|
addWarningCell(tr, srcLine);
|
|
|
|
addWarningCell(tr, ":");
|
|
|
|
addWarningCell(tr, "<div style='white-space:pre'>" + error.message + "\n<div style='color:#666'>" + error.stack + "</div></div>", "99%");
|
|
|
|
tr.codeLine = srcLine - 1;
|
|
|
|
tr.onclick = gotoWarning;
|
|
|
|
table.append(tr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*var wdiv = document.getElementById("warning-container");
|
|
|
|
var div = document.createElement("div");
|
|
|
|
div.innerHTML = error.name + ": " + error.message + "\n" + error.stack;
|
|
|
|
wdiv.appendChild(div); */
|
|
|
|
consoleVisible = true;
|
|
|
|
window.onresize();
|
|
|
|
QB.halt();
|
|
|
|
GX.sceneStop();
|
|
|
|
}
|
|
|
|
document.getElementById("gx-container").focus();
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
function stopProgram() {
|
|
|
|
QB.halt();
|
|
|
|
GX.sceneStop();
|
|
|
|
}
|
|
|
|
|
|
|
|
function shareProgram() {
|
|
|
|
var zout = new Shorty();
|
|
|
|
var b64 = LZUTF8.compress(editor.getValue(), { outputEncoding: "Base64" });
|
|
|
|
var baseUrl = location.href.split('?')[0];
|
|
|
|
|
|
|
|
var mode = document.getElementById("share-mode").value;
|
|
|
|
var codeShare = document.getElementById("share-code");
|
|
|
|
var url = baseUrl + "?";
|
|
|
|
if (mode) {
|
|
|
|
url += "mode=" + mode + "&";
|
|
|
|
}
|
|
|
|
url += "code=" + b64;
|
|
|
|
codeShare.value = url;
|
|
|
|
var shareDialog = document.getElementById("share-dialog");
|
|
|
|
if (!shareDialog.open) {
|
|
|
|
shareDialog.showModal();
|
|
|
|
}
|
|
|
|
codeShare.focus();
|
|
|
|
codeShare.select();
|
|
|
|
|
|
|
|
var exportVisible = (mode == "play" || mode == "auto");
|
|
|
|
document.getElementById("export-button").style.display = (exportVisible) ? "block" : "none";
|
|
|
|
}
|
|
|
|
|
|
|
|
async function exportProgram() {
|
|
|
|
var zip = new JSZip();
|
|
|
|
|
|
|
|
var qbCode = editor.getValue();
|
|
|
|
if (!QBCompiler) { QBCompiler = await _QBCompiler(); }
|
|
|
|
var jsCode = "async function __qbjs_run() {\n" + await QBCompiler.compile(qbCode) + "\n}";
|
|
|
|
|
|
|
|
var mode = document.getElementById("share-mode").value;
|
|
|
|
zip.file("index.html", await getFile("export/" + mode + ".html", "text"));
|
|
|
|
zip.file("program.js", jsCode);
|
|
|
|
zip.file("fullscreen.png", await getFile("export/fullscreen.png", "blob"));
|
|
|
|
zip.file("logo.png", await getFile("logo.png", "blob"));
|
|
|
|
zip.file("dosvga.ttf", await getFile("dosvga.ttf", "blob"));
|
|
|
|
zip.file("play.png", await getFile("play.png", "blob"));
|
|
|
|
zip.file("qbjs.css", await getFile("export/qbjs.css", "text"));
|
|
|
|
zip.file("qb.js", await getFile("qb.js", "text"));
|
|
|
|
zip.file("vfs.js", await getFile("vfs.js", "text"));
|
|
|
|
|
|
|
|
zip.file("gx/gx.js", await getFile("gx/gx.js", "text"));
|
|
|
|
zip.file("gx/__gx_font_default.png", await getFile("gx/__gx_font_default.png", "blob"));
|
|
|
|
zip.file("gx/__gx_font_default_black.png", await getFile("gx/__gx_font_default_black.png", "blob"));
|
|
|
|
|
|
|
|
// include vfs content
|
|
|
|
var vfs = QB.vfs();
|
|
|
|
var node = vfs.getNode("/");
|
|
|
|
addVFSFiles(vfs, zip, node);
|
|
|
|
|
|
|
|
zip.generateAsync({type:"blob"}).then(function(content) {
|
|
|
|
const link = document.createElement("a");
|
|
|
|
link.href = URL.createObjectURL(content);
|
|
|
|
link.download = "program.zip";
|
|
|
|
link.click();
|
|
|
|
link.remove();
|
|
|
|
});
|
2022-10-27 14:04:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function addVFSFiles(vfs, zip, parent) {
|
|
|
|
//alert("addVFSFiles: " + parent);
|
|
|
|
var files = vfs.getChildren(parent, vfs.FILE);
|
|
|
|
for (var i=0; i < files.length; i++) {
|
|
|
|
var f = files[i];
|
|
|
|
var path = vfs.fullPath(f).substring(1);
|
|
|
|
zip.file(path, f.data);
|
|
|
|
}
|
|
|
|
|
|
|
|
var dirs = vfs.getChildren(parent, vfs.DIRECTORY);
|
|
|
|
for (var i=0; i < dirs.length; i++) {
|
|
|
|
addVFSFiles(vfs, zip, dirs[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function saveProject() {
|
|
|
|
var vfs = QB.vfs();
|
|
|
|
var node = vfs.getNode("/");
|
|
|
|
var count = vfs.getChildren(node, vfs.FILE).length;
|
2022-11-01 03:55:08 +00:00
|
|
|
if (count < 1) {
|
|
|
|
count = vfs.getChildren(node, vfs.DIRECTORY).length;
|
|
|
|
}
|
2022-10-27 14:04:15 +00:00
|
|
|
|
|
|
|
// save a single .bas file
|
|
|
|
if (count == 0) {
|
|
|
|
var progFile = new Blob([ editor.getValue() ]);
|
|
|
|
const link = document.createElement("a");
|
|
|
|
link.href = URL.createObjectURL(progFile);
|
|
|
|
link.download = "program.bas";
|
|
|
|
link.click();
|
|
|
|
link.remove();
|
|
|
|
}
|
|
|
|
|
|
|
|
// save a project .zip file
|
|
|
|
else {
|
|
|
|
var zip = new JSZip();
|
|
|
|
zip.file("main.bas", editor.getValue());
|
|
|
|
|
|
|
|
var vfs = QB.vfs();
|
|
|
|
var node = vfs.getNode("/");
|
|
|
|
addVFSFiles(vfs, zip, node);
|
|
|
|
|
|
|
|
zip.generateAsync({type:"blob"}).then(function(content) {
|
|
|
|
const link = document.createElement("a");
|
|
|
|
link.href = URL.createObjectURL(content);
|
|
|
|
link.download = "project.zip";
|
|
|
|
link.click();
|
|
|
|
link.remove();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function openProject() {
|
|
|
|
var f = document.getElementById("file-input");
|
|
|
|
f.click();
|
|
|
|
}
|
|
|
|
|
|
|
|
async function onOpenProject(event) {
|
|
|
|
var f = event.target.files[0];
|
2022-09-17 16:50:08 +00:00
|
|
|
|
2022-10-27 14:04:15 +00:00
|
|
|
// load a single BASIC source file
|
|
|
|
if (f.name.toLowerCase().endsWith(".bas") || f.type.startsWith("text/")) {
|
|
|
|
var fr = new FileReader();
|
|
|
|
fr.onload = function() {
|
|
|
|
editor.setValue(fr.result);
|
|
|
|
}
|
|
|
|
fr.readAsText(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
// load a project from a zip file
|
|
|
|
else if (f.name.endsWith(".zip") || f.type == "application/x-zip-compressed") {
|
|
|
|
await loadProject(f);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
document.getElementById("file-input").onchange = onOpenProject;
|
|
|
|
|
|
|
|
async function loadProject(zipData, mainFilename) {
|
|
|
|
if (!mainFilename) {
|
|
|
|
mainFilename = "main.bas";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mainFilename = mainFilename.toLowerCase();
|
|
|
|
}
|
|
|
|
var vfs = GX.vfs();
|
|
|
|
vfs.reset();
|
|
|
|
JSZip.loadAsync(zipData).then(async function(zip) {
|
|
|
|
var basFiles = [];
|
|
|
|
var fnames = "";
|
|
|
|
var mainFound = false;
|
|
|
|
for (let [filename, file] of Object.entries(zip.files)) {
|
|
|
|
fnames += filename + " - " + zip.files[filename].name + "\n";
|
|
|
|
var parentDir = dirFromPath(vfs.getParentPath(filename));
|
|
|
|
if (filename.toLowerCase() == mainFilename) {
|
|
|
|
var text = await zip.file(filename).async("text");
|
|
|
|
editor.setValue(text);
|
|
|
|
mainFound = true;
|
|
|
|
}
|
|
|
|
else {
|
2022-11-01 03:55:08 +00:00
|
|
|
console.log(filename);
|
|
|
|
if (zip.file(filename)) {
|
|
|
|
var fdata = await zip.file(filename).async("arraybuffer");
|
|
|
|
var f = vfs.createFile(vfs.getFileName(filename), parentDir);
|
|
|
|
vfs.writeData(f, fdata);
|
|
|
|
if (filename.toLowerCase().endsWith(".bas")) {
|
|
|
|
basFiles.push(filename);
|
|
|
|
}
|
2022-10-27 14:04:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!mainFound) {
|
|
|
|
var fileList = document.getElementById("prog-sel-sources");
|
|
|
|
fileList.innerHTML = "";
|
|
|
|
for (var i=0; i < basFiles.length; i++) {
|
|
|
|
var opt = new Option(basFiles[i], basFiles[i]);
|
|
|
|
fileList.append(opt);
|
|
|
|
}
|
|
|
|
var progSelDlg = document.getElementById("prog-sel-dialog");
|
|
|
|
progSelDlg.showModal();
|
2022-09-17 16:50:08 +00:00
|
|
|
}
|
|
|
|
|
2022-10-27 14:04:15 +00:00
|
|
|
refreshFS();
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
function dirFromPath(path) {
|
|
|
|
var vfs = GX.vfs();
|
|
|
|
if (path == "") { return vfs.rootDirectory(); }
|
|
|
|
|
|
|
|
var dirnames = path.split("/");
|
|
|
|
var dirpath = ""
|
|
|
|
var parent = vfs.rootDirectory();
|
|
|
|
for (var i=0; i < dirnames.length; i++) {
|
|
|
|
dirpath += "/" + dirnames[i];
|
|
|
|
var dir = vfs.getNode(dirpath);
|
|
|
|
if (!dir) {
|
|
|
|
dir = vfs.createDirectory(dirnames[i], parent);
|
|
|
|
}
|
|
|
|
parent = dir;
|
2022-09-17 16:50:08 +00:00
|
|
|
}
|
2022-10-27 14:04:15 +00:00
|
|
|
return parent;
|
2022-09-17 16:50:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-27 14:04:15 +00:00
|
|
|
|
|
|
|
function onSelMainProg() {
|
|
|
|
var fileList = document.getElementById("prog-sel-sources");
|
|
|
|
if (fileList.value == "") {
|
|
|
|
alert("No file selected.");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
var vfs = GX.vfs();
|
|
|
|
var file = vfs.getNode("/" + fileList.value);
|
|
|
|
editor.setValue(vfs.readText(file));
|
|
|
|
vfs.removeFile(file);
|
|
|
|
closeProgSelDlg();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function closeProgSelDlg() {
|
|
|
|
var progSelDlg = document.getElementById("prog-sel-dialog");
|
|
|
|
progSelDlg.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-09-17 16:50:08 +00:00
|
|
|
async function getFile(path, type) {
|
|
|
|
var file = await fetch(path);
|
|
|
|
if (type == "text") {
|
|
|
|
return await file.text();
|
|
|
|
}
|
|
|
|
else if (type == "blob") {
|
|
|
|
return await file.blob();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function testShare() {
|
|
|
|
var url = document.getElementById("share-code").value;
|
|
|
|
open(url, "_blank");
|
|
|
|
}
|
|
|
|
|
|
|
|
function closeDialog() {
|
|
|
|
document.getElementById("share-dialog").close();
|
|
|
|
}
|
|
|
|
|
|
|
|
async function displayWarnings() {
|
|
|
|
var wstr = "";
|
|
|
|
var w = await QBCompiler.getWarnings();
|
|
|
|
warnCount = w.length;
|
|
|
|
|
|
|
|
var wdiv = document.getElementById("warning-container");
|
|
|
|
wdiv.innerHTML = "";
|
|
|
|
var table = document.createElement("table");
|
|
|
|
table.width = "100%";
|
|
|
|
table.id = "warning-table";
|
|
|
|
table.cellPadding = 2;
|
|
|
|
table.cellSpacing = 0;
|
|
|
|
table.style.cursor = "default";
|
|
|
|
wdiv.appendChild(table);
|
|
|
|
|
|
|
|
selectedError = null;
|
|
|
|
if (warnCount > 0) {
|
|
|
|
for (var i=0; i < w.length; i++) {
|
|
|
|
var tr = document.createElement("tr");
|
|
|
|
var td1 = document.createElement("td");
|
|
|
|
var td2 = document.createElement("td");
|
|
|
|
var td3 = document.createElement("td");
|
|
|
|
addWarningCell(tr, "WARN");
|
|
|
|
addWarningCell(tr, ":");
|
|
|
|
addWarningCell(tr, w[i].line);
|
|
|
|
addWarningCell(tr, ":");
|
|
|
|
addWarningCell(tr, w[i].text, "99%");
|
|
|
|
table.append(tr);
|
|
|
|
tr.codeLine = w[i].line - 1;
|
|
|
|
tr.onclick = gotoWarning; /*function() {
|
|
|
|
if (selectedError ) { selectedError.style.backgroundColor = "transparent"; }
|
|
|
|
editor.setCursor({ line: this.codeLine});
|
|
|
|
this.style.backgroundColor = "#333";
|
|
|
|
selectedError = this;
|
|
|
|
};*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!consoleVisible && w.length > 0) {
|
|
|
|
consoleVisible = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function gotoWarning() {
|
|
|
|
if (selectedError ) { selectedError.style.backgroundColor = "transparent"; }
|
|
|
|
editor.setCursor({ line: this.codeLine});
|
|
|
|
this.style.backgroundColor = "#333";
|
|
|
|
selectedError = this;
|
|
|
|
};
|
|
|
|
|
|
|
|
function addWarningCell(tr, text, width) {
|
|
|
|
var td = document.createElement("td");
|
|
|
|
td.innerHTML = text;
|
|
|
|
td.vAlign = "top";
|
|
|
|
if (width != undefined) {
|
|
|
|
td.width = width;
|
|
|
|
}
|
|
|
|
tr.append(td);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function showConsole() {
|
|
|
|
consoleVisible = !consoleVisible;
|
|
|
|
window.dispatchEvent(new Event('resize'));
|
|
|
|
//window.onresize();
|
|
|
|
}
|
|
|
|
|
|
|
|
function changeTab(tabName) {
|
|
|
|
if (tabName == currTab) { return; }
|
|
|
|
document.getElementById("tab-" + currTab).classList.remove("active");
|
|
|
|
document.getElementById("tab-" + tabName).classList.add("active");
|
|
|
|
currTab = tabName;
|
|
|
|
|
|
|
|
if (currTab == "console") {
|
|
|
|
document.getElementById("warning-container").style.display = "block";
|
|
|
|
document.getElementById("js-code").style.display = "none";
|
|
|
|
document.getElementById("fs-browser").style.display = "none";
|
|
|
|
}
|
|
|
|
else if (currTab == "js") {
|
|
|
|
document.getElementById("warning-container").style.display = "none";
|
|
|
|
document.getElementById("fs-browser").style.display = "none";
|
|
|
|
document.getElementById("js-code").style.display = "block";
|
|
|
|
}
|
|
|
|
else if (currTab == "fs") {
|
|
|
|
document.getElementById("fs-browser").style.display = "block";
|
|
|
|
document.getElementById("warning-container").style.display = "none";
|
|
|
|
document.getElementById("js-code").style.display = "none";
|
|
|
|
refreshFS();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function displayTypes() {
|
|
|
|
var tstr = "";
|
|
|
|
var t = QBCompiler.getTypes();
|
|
|
|
for (var i=0; i < t.length; i++) {
|
|
|
|
tstr += t[i].name
|
|
|
|
}
|
|
|
|
var wdiv = document.getElementById("warning-container");
|
|
|
|
wdiv.innerHTML = tstr;
|
|
|
|
}
|
|
|
|
|
|
|
|
function slideLeft() {
|
|
|
|
document.getElementById("slider-right").style.display = "block";
|
|
|
|
if (sizeMode == "max" && window.innerWidth >= 1200) {
|
|
|
|
sizeMode = "normal"
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sizeMode = "min"
|
|
|
|
document.getElementById("slider-left").style.display = "none";
|
|
|
|
}
|
|
|
|
//window.onresize();
|
|
|
|
window.dispatchEvent(new Event('resize'));
|
|
|
|
}
|
|
|
|
|
|
|
|
function slideRight() {
|
|
|
|
document.getElementById("slider-left").style.display = "block";
|
|
|
|
if (sizeMode == "min" && window.innerWidth >= 1200) {
|
|
|
|
sizeMode = "normal"
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sizeMode = "max"
|
|
|
|
document.getElementById("slider-right").style.display = "none";
|
|
|
|
}
|
|
|
|
//window.onresize();
|
|
|
|
window.dispatchEvent(new Event('resize'));
|
|
|
|
}
|
|
|
|
|
|
|
|
window.onresize = function() {
|
|
|
|
if (!editor) { return; }
|
|
|
|
|
|
|
|
var f = document.getElementById("gx-container");
|
|
|
|
var jsDiv = document.getElementById("output-container");
|
|
|
|
|
|
|
|
if (appMode == "play" || appMode == "auto") {
|
|
|
|
f.style.left = "0px";
|
|
|
|
f.style.top = "0px";
|
|
|
|
f.style.width = window.innerWidth;
|
|
|
|
f.style.height = window.innerHeight;
|
|
|
|
f.style.border = "0px";
|
|
|
|
document.getElementById("code-container").style.display = "none";
|
|
|
|
document.getElementById("slider").style.display = "none";
|
|
|
|
document.getElementById("show-js-container").style.display = "none";
|
|
|
|
document.getElementById("game-container").style.left = "0px";
|
|
|
|
document.getElementById("game-container").style.top = "0px";
|
|
|
|
jsDiv.style.display = "none";
|
|
|
|
document.getElementById("logo").style.display = "none";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
var cmwidth = 600;
|
|
|
|
if (sizeMode == "min") {
|
|
|
|
cmwidth = 0;
|
|
|
|
editor.getWrapperElement().style.display = "none";
|
|
|
|
document.getElementById("code").style.borderRight = "0";
|
|
|
|
document.getElementById("game-container").style.display = "block";
|
|
|
|
document.getElementById("edit-button").style.display = "block";
|
|
|
|
}
|
|
|
|
else if (sizeMode == "max") {
|
|
|
|
cmwidth = window.innerWidth - 25;
|
|
|
|
document.getElementById("game-container").style.display = "none";
|
|
|
|
document.getElementById("code").style.borderRight = "1px solid #666";
|
|
|
|
document.getElementById("slider").style.border = "1px solid #666";
|
|
|
|
document.getElementById("slider").style.borderLeft = "0";
|
|
|
|
editor.getWrapperElement().style.display = "block";
|
|
|
|
document.getElementById("edit-button").style.display = "none";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
editor.getWrapperElement().style.display = "block";
|
|
|
|
document.getElementById("game-container").style.display = "block";
|
|
|
|
document.getElementById("code").style.borderRight = "1px solid #666";
|
|
|
|
document.getElementById("slider").style.border = "0";
|
|
|
|
document.getElementById("edit-button").style.display = "none";
|
|
|
|
}
|
|
|
|
|
|
|
|
document.getElementById("game-container").style.left = (cmwidth + 20) + "px";
|
|
|
|
f.style.width = (window.innerWidth - (cmwidth + 35)) + "px";
|
|
|
|
jsDiv.style.width = f.style.width;
|
|
|
|
|
|
|
|
document.getElementById("slider").style.left = (cmwidth + 12) + "px";
|
|
|
|
|
|
|
|
if (consoleVisible) {
|
|
|
|
f.style.height = (window.innerHeight - 337) + "px";
|
|
|
|
jsDiv.style.display = "block";
|
|
|
|
jsDiv.style.top = (window.innerHeight - 327) + "px";
|
|
|
|
document.getElementById("toggle-console").innerHTML = "Hide Console";
|
|
|
|
/*if (currTab == "console") {
|
|
|
|
document.getElementById("warning-container").style.display = "block";
|
|
|
|
document.getElementById("js-code").style.display = "none";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
document.getElementById("warning-container").style.display = "none";
|
|
|
|
document.getElementById("js-code").style.display = "block";
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
f.style.height = (window.innerHeight - 50) + "px";
|
|
|
|
jsDiv.style.display = "none";
|
|
|
|
document.getElementById("toggle-console").innerHTML = "Show Console";
|
|
|
|
}
|
|
|
|
document.getElementById("show-js-container").style.top = (window.innerHeight - 45) + "px";
|
|
|
|
document.getElementById("show-js-container").style.right = "5px";
|
|
|
|
|
2022-10-27 14:04:15 +00:00
|
|
|
editor.setSize(cmwidth, window.innerHeight - 79);
|
|
|
|
//document.getElementById("code").style.height = (window.innerHeight - 50) + "px";
|
|
|
|
document.getElementById("code").style.height = (window.innerHeight - 79) + "px";
|
2022-09-17 16:50:08 +00:00
|
|
|
document.getElementById("slider").style.height = (window.innerHeight - 50) + "px";
|
|
|
|
}
|
|
|
|
//QB.resize(f.style.width.replace("px", ""), f.style.height.replace("px", ""));
|
|
|
|
QB.resize(f.clientWidth, f.clientHeight);
|
|
|
|
}
|
|
|
|
window.onresize();
|
|
|
|
|
|
|
|
function checkButtonState() {
|
|
|
|
var stopButton = document.getElementById("stop-button");
|
|
|
|
if (GX.sceneActive() || QB.running()) {
|
|
|
|
stopButton.style.display = "inline";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
stopButton.style.display = "none";
|
|
|
|
}
|
|
|
|
|
|
|
|
setTimeout(checkButtonState, 100);
|
|
|
|
}
|
|
|
|
checkButtonState();
|
|
|
|
init();
|
|
|
|
|
|
|
|
|
|
|
|
// Virtual File System Viewer
|
|
|
|
function refreshFS() {
|
|
|
|
var vfs = QB.vfs();
|
|
|
|
var node = vfs.getNode(currPath);
|
|
|
|
if (!node) {
|
|
|
|
currPath = "/";
|
|
|
|
node = vfs.getNode(currPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
var contents = document.getElementById("fs-contents");
|
|
|
|
while (contents.firstChild) {
|
|
|
|
contents.removeChild(contents.firstChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!node) {
|
|
|
|
// TODO: better error reporting
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
currPath = vfs.fullPath(node)
|
|
|
|
document.getElementById("fs-url").innerHTML = currPath;
|
|
|
|
|
|
|
|
if (currPath != "/") {
|
|
|
|
var a = document.createElement("a");
|
|
|
|
a.className = "fs-dir";
|
|
|
|
a.innerHTML = "..";
|
|
|
|
a.fullpath = currPath + "/..";
|
|
|
|
a.onclick = function() { chdir(this.fullpath); };
|
|
|
|
contents.appendChild(a);
|
2022-10-28 19:58:21 +00:00
|
|
|
contents.appendChild(document.createElement("span"));
|
2022-09-17 16:50:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var folders = vfs.getChildren(node, vfs.DIRECTORY);
|
|
|
|
for (var i=0; i < folders.length; i++) {
|
|
|
|
var a = document.createElement("a");
|
|
|
|
a.className = "fs-dir";
|
|
|
|
a.innerHTML = folders[i].name;
|
|
|
|
a.fullpath = vfs.fullPath(folders[i]);
|
|
|
|
a.onclick = function() { chdir(this.fullpath); };
|
|
|
|
contents.appendChild(a);
|
2022-10-28 19:58:21 +00:00
|
|
|
a = document.createElement("a");
|
|
|
|
a.className = "fs-delete";
|
|
|
|
a.vfsnode = folders[i];
|
|
|
|
a.onclick = function() { deleteDir(this.vfsnode); };
|
|
|
|
contents.appendChild(a);
|
2022-09-17 16:50:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var files = vfs.getChildren(node, vfs.FILE);
|
|
|
|
for (var i=0; i < files.length; i++) {
|
|
|
|
var a = document.createElement("a");
|
|
|
|
a.className = "fs-file";
|
|
|
|
a.innerHTML = files[i].name;
|
|
|
|
a.fullpath = vfs.fullPath(files[i]);
|
|
|
|
a.onclick = function() { saveFile(this.fullpath); };
|
|
|
|
contents.appendChild(a);
|
2022-10-28 19:58:21 +00:00
|
|
|
a = document.createElement("a");
|
|
|
|
a.className = "fs-delete";
|
|
|
|
a.vfsnode = files[i];
|
|
|
|
a.onclick = function() { deleteFile(this.vfsnode); };
|
|
|
|
contents.appendChild(a);
|
|
|
|
}
|
|
|
|
|
|
|
|
function deleteFile(node) {
|
|
|
|
if (confirm("This will permanently delete file '" + node.name + "'.\nAre you sure you wish to continue?")) {
|
|
|
|
vfs.removeFile(node);
|
|
|
|
refreshFS();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function deleteDir(node) {
|
|
|
|
if (vfs.getChildren(node).length > 0) {
|
|
|
|
alert("Directory is not empty.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (confirm("This will permanently delete directory '" + node.name + "'.\nAre you sure you wish to continue?")) {
|
|
|
|
vfs.removeDirectory(node);
|
|
|
|
refreshFS();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function onNewDirectory() {
|
|
|
|
var vfs = QB.vfs();
|
|
|
|
var parent = vfs.getNode(currPath);
|
|
|
|
var dirname = prompt("Enter new directory name");
|
|
|
|
if (dirname && dirname != "") {
|
|
|
|
vfs.createDirectory(dirname, parent);
|
|
|
|
refreshFS();
|
2022-09-17 16:50:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function chdir(path) {
|
|
|
|
currPath = path;
|
|
|
|
refreshFS();
|
|
|
|
}
|
|
|
|
|
|
|
|
function saveFile(path) {
|
|
|
|
var vfs = QB.vfs();
|
|
|
|
var fileNode = vfs.getNode(path);
|
|
|
|
var fileBlob = new Blob([fileNode.data]);
|
|
|
|
var url = URL.createObjectURL(fileBlob);
|
|
|
|
|
|
|
|
var link = document.createElement("a");
|
|
|
|
link.href = url;
|
|
|
|
link.download = fileNode.name;
|
|
|
|
link.click();
|
|
|
|
}
|
|
|
|
|
|
|
|
async function fileDrop(e) {
|
|
|
|
if (currTab != "fs") { return; }
|
|
|
|
e.stopPropagation();
|
|
|
|
e.preventDefault();
|
|
|
|
dropArea.style.backgroundColor = "transparent";
|
|
|
|
|
|
|
|
var dt = e.dataTransfer;
|
|
|
|
var files = dt.files;
|
|
|
|
console.log(files);
|
|
|
|
|
|
|
|
var vfs = QB.vfs();
|
|
|
|
var parentDir = vfs.getNode(currPath);
|
|
|
|
var fr = new FileReader();
|
|
|
|
|
|
|
|
console.log(files.length);
|
|
|
|
for (var i=0; i < files.length; i++) {
|
|
|
|
console.log("processing[" + i + "]...");
|
2022-11-01 03:55:08 +00:00
|
|
|
|
2022-09-17 16:50:08 +00:00
|
|
|
var f = files[i];
|
2022-11-01 03:55:08 +00:00
|
|
|
if (!f.type && f.size%4096 == 0) {
|
|
|
|
// this is a folder, skip
|
|
|
|
console.log(" -> skipping folder [" + i + "]");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-09-17 16:50:08 +00:00
|
|
|
var file = vfs.createFile(f.name, parentDir);
|
|
|
|
var data = await f.arrayBuffer();
|
|
|
|
console.log(data);
|
|
|
|
vfs.writeData(file, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
refreshFS();
|
|
|
|
}
|
|
|
|
|
|
|
|
function fileDragEnter(e) {
|
|
|
|
if (currTab != "fs") { return; }
|
|
|
|
e.stopPropagation();
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
dropArea.style.backgroundColor = "rgb(255,255,255,.1)";
|
|
|
|
}
|
|
|
|
|
|
|
|
function fileDragLeave(e) {
|
|
|
|
if (currTab != "fs") { return; }
|
|
|
|
e.stopPropagation();
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
dropArea.style.backgroundColor = "transparent";
|
|
|
|
}
|
|
|
|
|
|
|
|
function fileDragOver(e) {
|
|
|
|
if (currTab != "fs") { return; }
|
|
|
|
e.stopPropagation();
|
|
|
|
e.preventDefault();
|
|
|
|
}
|
|
|
|
|
|
|
|
var dropArea = document.getElementById("output-content");
|
|
|
|
dropArea.addEventListener("drop", fileDrop, false);
|
|
|
|
dropArea.addEventListener("dragover", fileDragOver, false);
|
|
|
|
dropArea.addEventListener("dragenter", fileDragEnter, false);
|
|
|
|
dropArea.addEventListener("dragleave", fileDragLeave, false);
|