-<!DOCTYPE html>
-<html>
- <head>
- <meta charset="utf-8">
- <title>PCDSL Editor</title>
- <script type="text/javascript" src="include/jquery.js"></script>
- <script type="text/javascript" src="include/jquery.textarea-util.js"></script>
- <script type="text/javascript" src="include/jquery.selection.js"></script>
- <script type="text/javascript" src="include/texteditor-script.js"></script>
- <style type="text/css">
-html,body{
- margin:0;padding:0;
-}
-#menubar{
- background-color: #DED7B4;
- overflow: hidden;
- font-size: 18px;
-}
-#menubar>a{
- display: block;
- float: left;
- padding: 0.5em 1em;
- cursor: pointer;
- margin-left: 5px;
-}
-#menubar>a:hover{
- background-color: #BAAB63;
-
-}
-
-.window{
- display: none;
- height: 100%;
- padding-bottom: 36px;
- margin-bottom: -36px;
- overflow: hidden;
-}
-textarea {
- font-family: Consolas, 'Courier New', Courier, Monaco, monospace;
- font-size: 12px;
- line-height: 1.2;
-}
-
-#palletBox>div{
- padding: 10px;
- cursor: pointer;
- border-bottom: 1px #666 solid;
- overflow: hidden;
-}
-#palletBox>div:hover{
- background-color: green;
-}
-#palletBox>div>img{
- float: left;
- width: 64px;
- height: 64px;
-}
-
-#editorBox>div{
- position: absolute;
- width: 32px;
- height: 32px;
- color: black;
- border: 1px black solid;
-}
-#editorBox>div>img{
- position: absolute;
- top: 0; left: 0; width: 32px; height: 32px;
-}
-#editorBox>div>div{
- position: absolute;
- top: 0; left: 0; right: 0; bottom: 0;
- background-color: transparent;
-}
-
- </style>
-<script type="text/javascript">
-
-function resize()
-{
- $('#textarea>textarea').css("width", $(window).width() - 30);
- $('#textarea>textarea').css("height", $(window).height() - 120);
-
-}
-
-var isModified = false;
-
- // イベントをキャンセルするハンドラです.
-var cancelEvent = function(event) {
- event.preventDefault();
- event.stopPropagation();
- return false;
-};
-
-function initDrop()
-{
- var droppable = $("#openWindow");
-
- if(!window.FileReader) {
- alert("File API がサポートされていません。");
- window.close();
- }
-
-
- // dragenter, dragover イベントのデフォルト処理をキャンセルします.
- droppable.bind("dragenter", cancelEvent);
- droppable.bind("dragover", cancelEvent);
-
- // ドロップ時のイベントハンドラを設定します.
- var handleDroppedFile = function(event) {
- // ファイルは複数ドロップされる可能性がありますが, ここでは 1 つ目のファイルを扱います.
- var file = event.originalEvent.dataTransfer.files[0];
-
- // ファイルの内容は FileReader で読み込みます.
- var fileReader = new FileReader();
- fileReader.onload = function(event) {
- // event.target.result に読み込んだファイルの内容が入っています.
- $("#textarea textarea").val(event.target.result);
-
- isModified = false;
- browserFileName = null;
- if(_guiMode)
- {
- if(!textToGui())
- {
- $('#guiWindow').fadeOut();
- $('#textWindow').fadeIn();
- _guiMode = false;
- }
- }
- }
- fileReader.readAsText(file);
-
- // デフォルトの処理をキャンセルします.
- cancelEvent(event);
- $('#openWindow').hide();
- return false;
- }
-
- // ドロップ時のイベントハンドラを設定します.
- droppable.bind("drop", handleDroppedFile);
-
-}
-
-window.onload = function(){
-
- $(window).bind("dragenter", cancelEvent);
- $(window).bind("dragover", cancelEvent);
- $(window).bind("drop", cancelEvent);
- initDrop();
- resize();
-
- var oldData = localStorage.getItem("savedat");
- if(oldData)
- {
- $('#textarea textarea').val(oldData);
- }
-
- $('#textarea textarea').change(function(){
- isModified = true;
- });
-
-};
-
-window.onbeforeunload = function(e) {
- if(isModified)
- {
- e = e || window.event;
- return e.returnValue = '変更が保存されていません。破棄されますが続行しますか?';
- }
-};
-
-function openFile()
-{
- if(isModified)
- {
- if(!window.confirm("内容が変更されています。破棄されますがよろしいですか?")) return;
- }
- $('#openWindow').show();
-}
-
-function saveFile()
-{
- var value = $('#textarea textarea').val();
- var href = "data:application/octet-stream," + encodeURIComponent(value);
- isModified = false;
- location.href = href;
-
-}
-
-var browserFileName = null;
-function saveToBrowser()
-{
- if(browserFileName == null || !window.confirm("名前 " + browserFileName + " でよろしいですか?"))
- {
- var input = window.prompt("名前を入力してください");
- if(!input)
- {
- return;
- }
- browserFileName = input;
- }
-
- localStorage.setItem(browserFileName, $('#textarea textarea').val());
- isModified = false;
- window.alert("名前 " + browserFileName + " で保存しました");
-}
-
-function openFromBrowser()
-{
- $('#selectWindow #select > option').remove();
- for(var item in localStorage)
- {
- $('#selectWindow #select').append($('<option>').html(item).val(item));
- }
- $("#selectWindow").show();
-}
-
-function removeSelectedItem()
-{
- var item = $("#selectWindow #select").val();
- if(!item) return;
- if(window.confirm(item + " の保存項目を削除しますか?"))
- {
- $('#selectWindow #select > option:selected').remove();
- localStorage.removeItem(item);
- }
-}
-
-function openSelectedItem()
-{
- var item = $("#selectWindow #select").val();
- if(!item) return;
- if(isModified)
- {
- if(!window.confirm("変更されています。破棄されますがよろしいですか?")) return;
- }
-
- $("#textarea textarea").val(localStorage.getItem(item));
-
- $("#selectWindow").hide();
- isModified = false;
- browserFileName = item;
- if(_guiMode)
- {
- if(!textToGui())
- {
- $('#guiWindow').fadeOut();
- $('#textWindow').fadeIn();
- _guiMode = false;
- }
- }
-}
-
-function run()
-{
- localStorage.setItem("previewStage", $("#textarea textarea").val());
- window.open("../index_local_debug.html");
-}
-
-function editInTextEditor()
-{
- if(!_guiMode) return;
- $('#guiWindow').fadeOut();
- $('#textWindow').fadeIn();
- _guiMode = false;
-}
-
-function editInGui()
-{
- if(_guiMode) return;
- if(textToGui()) //gui移行に成功したら
- {
- $('#guiWindow').fadeIn();
- $('#textWindow').fadeOut();
- _guiMode = true;
- }
-}
-
-var _guiStageInfo = null;
-var _guiTbl = null;
-var _guiElements = null;
-var _guiMode = false;
-var stgObjects = {};
-var stgSymbolVals = {};
-var stgSymbolImages = {};
-function textToGui()
-{
- try{
- var code = $("#textarea textarea").val();
-
- //コメントのマスク
- var isInLineComment = false;
- var isInComment = false;
- for(var i = 0; i < code.length; i++)
- {
- if(isInComment)
- {
- if(code[i] == "*" && code[i + 1] == "/")
- {
- code++;
- isInComment = false;
- }else
- {
- code = code.slice(0, i) + "*" + code.slice(i + 1);
- }
- }
- if(isInLineComment)
- {
- if(code[i] == "\n")
- {
- isInLineComment = false;
- //}else if(code[i] == "/" && code[i + 1] == "*")
- //{
- // i++;
- // isInLineComment = false;
- // isInComment = true;
- }else
- {
- code = code.slice(0, i) + "*" + code.slice(i + 1);
- }
- }else
- {
- if(code[i] == "/")
- {
- if(code[i + 1] == "*")
- {
- i++;
- isInComment = true;
- }else if(code[i + 1] == "/")
- {
- i++;
- isInLineComment = true;
- }
- }
- }
- }
-
-
- //stgObjectsの取得
- stgObjects = {};
- var objStart = code.indexOf("var stgObjects");
- if(objStart == -1) throw new Error("stgObjectsの定義が見つかりません。");
- var objLength = exploreEndParen(code.slice(objStart));
- if(objLength == -1) throw new Error("stgObjectsの終端が見つかりません。カッコが不足している可能性があります。");
-
- var nextColon = objStart;
- for(;;)
- {
- nextColon = code.indexOf(":", nextColon);
- if(nextColon == -1 || nextColon >= objStart + objLength) break;
-
- var symbol = ""; // tbl[]で使う文字
- var index = nextColon;
- for(;;)
- {
- index--;
- if(" \t */ \n".indexOf(code[index]) != -1)
- {
- if(symbol != "") break;
- }else
- {
- symbol = code[index] + symbol;
- }
- }
-
- index = nextColon;
- for(;;)
- {
- index++;
- if(" \t ".indexOf(code[index]) == -1) break;
- }
- if(index >= objStart + objLength) throw new Error("stgObjectsの文法エラーです");
-
- var argLen;
- if(code[index] == "{"){
- argLen = exploreEndParen(code.slice(index));
- }else
- {
- var argt = "";
- var ind = index;
- for(;;)
- {
- if(" \t/ \n".indexOf(code[ind]) != -1) break;
- argt += code[ind];
- ind++;
- }
- argLen = argt.length;
- }
- if(index + argLen >= objStart + objLength) throw new Error("stgObjectsの文法エラーです");
-
- var argText = code.slice(index, index + argLen); //文字に対応するコード
-
- // stgObjectsに登録
- if(!stgObjects[symbol])
- {
- stgObjects[symbol] = symbol;
- }else
- {
- throw new Error("シンボル" + symbol + "は二重定義されています");
- }
-
- // stgSymbolValsに登録
- stgSymbolVals[symbol] = argText;
-
- // 画像を探す
- if(argText.indexOf(".png") != -1)
- {
- var ind = argText.indexOf(".png");
- var imgName = ".png";
- for(;;)
- {
- ind--;
- if("\"'".indexOf(argText[ind]) != -1) break;
- imgName = argText[ind] + imgName;
- }
- stgSymbolImages[symbol] = imgName;
-
- }else
- {
- stgSymbolImages[symbol] = null;
- }
-
- nextColon = index + argLen;
-
-
- }
-
- // tblの取得
- var tblStart = code.indexOf("with(stgObjects)") + 16;
- if(tblStart == -1) throw new Error("tbl[]が見つかりません。");
- var tblLength = exploreEndParen(code.slice(tblStart));
- if(tblLength == -1) throw new Error("tbl[]の終端が見つかりません。カッコが不足している可能性があります。");
- var tblCode = "with(stgObjects)" + code.slice(tblStart, tblStart + tblLength);
- try{
- eval(tblCode); //これでtblにテーブルデータが入る
- }catch(e)
- {
- if(e instanceof ReferenceError)
- {
- window.alert("tbl[] の中に StgObjects で定義されていない文字が含まれています。\nエラーの詳細:\n" + e.message);
- return false;
- }else
- {
- window.alert("stgObjects の中身の書式が間違っています\nエラーの詳細:\n" + e.message);
- return false;
- }
- }
- if(!tbl) return false;
- _guiTbl = tbl; //_guiTbl に代入
-
- // stgInfoの取得
- var infoStart = code.indexOf("var stgInfo");
- if(infoStart == -1) throw new Error("stgInfoが見つかりません。");
- var infoLength = exploreEndParen(code.slice(infoStart));
- if(infoLength == -1) throw new Error("stgInfoの終端が見つかりません。カッコが不足している可能性があります。");
- var infoCode = code.slice(infoStart, infoStart + infoLength);
- try{
- eval(infoCode);
- }catch(e)
- {
- window.alert("var StgInfo の中身の書式が間違っています\nエラーの詳細:\n" + e.message);
- return false;
- }
- if(!stgInfo) return false;
- _guiStageInfo = stgInfo;
- if(!stgInfo.width) return false;
- if(!stgInfo.height) return false;
-
-
- //パレットの初期化
-
- document.getElementById('palletBox').innerHTML = "";
-
- for(var symbol in stgObjects)
- {
- var div = document.createElement('div');
- var p = document.createElement('p');
- p.innerText = symbol + " : " + stgSymbolVals[symbol];
-
- if(stgSymbolImages[symbol] != null)
- {
- var img = document.createElement('img');
- img.src = "../images/" + stgSymbolImages[symbol];
- div.appendChild(img);
- }
- div.appendChild(p);
- document.getElementById('palletBox').appendChild(div);
- eval("func = function(){PalletItemClickEvent(\"" + symbol + "\");};");
- div.addEventListener("click", func);
- }
-
-
- //作業領域の描画
- var area = document.getElementById("editorBox");
- $('#editorBox > div').remove();
- _guiElements = [];
- for(var y = 0; y < stgInfo.height / 32; y++)
- {
- _guiElements[y] = [];
- for(var x = 0; x < stgInfo.width / 32; x++)
- {
- var element = document.createElement('div');
- element.style.top = (y * 32) + "px";
- element.style.left = (x * 32) + "px";
- var img = document.createElement('img');
- element.appendChild(img);
- var div = document.createElement('div');
- element.appendChild(div);
- _guiElements[y][x] = element;
- area.appendChild(element);
- eval("onMouseDownFunc = function(){guiElementMouseDownEvent(" + x + ", " + y + ");};");
- eval("onMouseUpFunc = function(){guiElementMouseUpEvent(" + x + ", " + y + ");};");
- eval("onMouseOverFunc = function(){guiElementMouseOverEvent(" + x + ", " + y + ");};");
- element.addEventListener("mousedown", onMouseDownFunc);
- element.addEventListener("mouseover", onMouseOverFunc);
- element.addEventListener("mouseup", onMouseUpFunc);
- }
- }
-
- var ignoreOverflow = false;
- for(var y = 0; y < _guiTbl.length; y++)
- {
- for(var x = 0; x < _guiTbl[y].length; x++)
- {
- if(_guiElements[y] && _guiElements[y][x])
- {
- var symbol = _guiTbl[y][x];
- var img = stgSymbolImages[symbol];
- if(img != null)
- {
- $(_guiElements[y][x]).find("img").attr('src', "../images/" +img);
- }else
- {
- $(_guiElements[y][x]).find("div").text(symbol);
- }
- }else if(!ignoreOverflow)
- {
- if(window.confirm("tbl[]のサイズがステージのサイズをオーバーしています。はみ出た分を破棄して続行しますか? (破棄したくない場合は、「いいえ」で戻ってステージのサイズを大きくするかtbl[]の要素数を確認してください)"))
- {
- ignoreOverflow = true;
- }else
- {
- return false;
- }
- }
- }
- }
-
- return true;
- }catch(e)
- {
- if(e instanceof Error)
- {
-
- //アプリ内で起こされたエラー
- window.alert(e.message);
- }else
- {
- window.alert("不明なエラーです\nエラーの詳細:\n" + (e.message));
- }
- return false;
- }
-}
-
-var mouseState = false;
-function guiElementMouseDownEvent(x, y)
-{
- mouseState = true;
- if($('#toolBox input:radio:checked').val() == 'pen')
- {
- var img = stgSymbolImages[selectedPalletItem];
- if(img != null)
- {
- $(_guiElements[y][x]).find("img").attr('src', "../images/" + img);
- $(_guiElements[y][x]).find("div").text("");
- }else
- {
- $(_guiElements[y][x]).find("img").attr('src', "../images/null.png");
- $(_guiElements[y][x]).find("div").text(selectedPalletItem);
- }
-
- _guiTbl[y][x] = selectedPalletItem;
- GuiToText();
- }
-}
-
-function guiElementMouseUpEvent(x, y)
-{
- mouseState = false;
- if($('#toolBox input:radio:checked').val() == "addr")
- {
- window.alert("位置(" + x + ", " + y + ")\n座標(" + (x * 32) + ", " + (y * 32) + ")");
- }
-}
-
-function guiElementMouseOverEvent(x, y)
-{
- if(mouseState && $('#toolBox input:radio:checked').val() == 'pen')
- {
- var img = stgSymbolImages[selectedPalletItem];
- if(img != null)
- {
- $(_guiElements[y][x]).find("img").attr('src', "../images/" + img);
- $(_guiElements[y][x]).find("div").text("");
- }else
- {
- $(_guiElements[y][x]).find("img").attr('src', "../images/null.png");
- $(_guiElements[y][x]).find("div").text(selectedPalletItem);
- }
-
- _guiTbl[y][x] = selectedPalletItem;
- GuiToText();
- }
-}
-
-function guiElementClickEvent(x,y)
-{
- var val = $('#stageBox input:radio:checked').val();
- if(val == "addr")
- {
- window.alert("位置(" + x + ", " + y + ")\n座標(" + (x * 32) + ", " + (y * 32) + ")");
- }else if(val == "other")
- {
- val = window.prompt("ブロックとして使用する文字を入力してください(通常は一文字か二文字の英文字です)");
- if(val)
- {
- $(_guiElements[y][x]).text(val);
- _guiTbl[y][x] = val;
- GuiToText();
- }
- }else
- {
- $(_guiElements[y][x]).text(val);
- _guiTbl[y][x] = val;
- GuiToText();
- }
-}
-
-var selectedPalletItem = "";
-function PalletItemClickEvent(symbol)
-{
- $('#selectedSymbol').text(symbol);
- selectedPalletItem = symbol;
-}
-
-function GuiToText()
-{
- var code = $("#textarea textarea").val();
- var tblCode = "with(stgObjects){\n\tvar tbl = [\n";
- for(var y = 0; y < _guiStageInfo.height / 32; y++)
- {
- tblCode += "\t\t[";
- if(_guiTbl[y])
- {
- for(var x = 0; x < _guiStageInfo.width / 32; x++)
- {
- if(_guiTbl[y][x])
- {
- tblCode += _guiTbl[y][x];
- }else
- {
- tblCode += " ";
- }
- tblCode += ",";
- }
- if(tblCode.slice(tblCode.length - 1) == ",") tblCode = tblCode.slice(0, tblCode.length - 1);
- }
- tblCode += "],\n";
- }
- if(tblCode.slice(tblCode.length - 3) == "],\n") tblCode = tblCode.slice(0, tblCode.length - 2) + "\n";
- tblCode += "\t];\n";
- tblCode += "}";
- var tblStart = code.indexOf("with(stgObjects)");
- if(tblStart == -1) return false;
- var tblLength = exploreEndParen(code.slice(tblStart + 16)) + 16;
- if(tblLength == 15) return false;
-
- code = code.slice(0, tblStart) + tblCode + code.slice(tblStart + tblLength);
- $("#textarea textarea").val(code);
-
- isModified = true;
- return true;
-}
-
-// 最後にカッコが閉じて最初と同じレベルに到達するまでのインデックスを返す。カッコが閉じられずに終わったら(もしくは急に閉じかっこが出てきたら)-1
-function exploreEndParen(text)
-{
- var nest = 0;
-
- for(var i = 0; i < text.length; i++)
- {
- if(text[i] == '{' || text[i] == '(' || text[i] == '[') nest++;
- else if(text[i] == '}' || text[i] == ')' || text[i] == ']')
- {
- nest--;
- if(nest < 0) //開始カッコがないのに急に終了カッコが出てきた
- {
- return -1;
- }else if(nest == 0)
- {
- return i + 1; //カッコの後ろまで含める
- }
- }
- }
-
- return nest != 0 ? -1 : i;
-}
-
-$(window).bind("resize", resize);
-
-</script>
- </head>
- <body>
- <div id="menubar">
- <a onclick="openFile();">開く</a>
- <a onclick="saveFile()">名前を付けて保存</a>
- <a onclick="openFromBrowser()">ブラウザから開く</a>
- <a onclick="saveToBrowser();">ブラウザに保存</a>
- <a onclick="editInGui();">GUI編集</a>
- <a onclick="editInTextEditor()">テキスト編集</a>
- <a onclick="run()">実行</a>
- <a target="_blank" href="readme.txt">ヘルプ</a>
- <a target="_blank" href="./expression.html">文法ヘルプ</a>
- </div>
- <div id="guiWindow" class="window">
- <div style="float: left; width: 30%; background-color: #eee; padding: 30px; margin-bottom: -32737px; margin-right: 30px; padding-bottom: 32767px;">
- <strong>パレット</strong><br>
- <div id="palletBox" style="height: 500px; overflow: scroll; background-color: white; border: 1px black solid; margin: 10px;">
-
- </div>
- <strong>選択された項目</strong><br>
- <div id="selectedSymbol"></div><br>
- <strong>ツール</strong><br>
- <div id="toolBox">
- <input id="penTool" type="radio" name="tool" value="pen" checked>ペン<br>
- <input type="radio" name="tool" value="addr">座標の取得<br>
- </div>
- </div>
- <div style="padding: 30px;">
- <strong>エディット</strong>
- <div id="editorBox" style="user-select: none; -webkit-user-select: none; -khtml-user-select: none; height: 500px; overflow: scroll; background-color: white; border: 1px black solid; margin: 10px; position: relative; font-size: 32px;"></div>
- <div id="editorMessageBox"></div>
- </div>
- </div>
- <div id="textWindow" class="window" style="display: block;">
- <div id="wrapper" style="height: 100%;">
- <div id="textarea" style="width: 100%;">
- <textarea wrap="off">
-// StageObjectsはステージに文字シンボルとして配置したいオブジェクト定義の連想配列である。
-// StageObjectの各項目の指定方法は以下の二通りある。
-// ・クラス名指定 ... コンストラクタがに引数が不要な時
-// a : BlockClass
-// ・拡張指定
-// a : {base : FreeItemClass, //鋳型となるクラス名
-// args : '1190.png', //コンストラクタに指定する引数(一つだけの場合) stageは自動で指定されるので不要
-// args : ['1190.png', callback], //二つ以上の場合。やはり第一引数のstageは不要
-// prop : {times : 1}, //各インスタンスに指定したいプロパティの連想配列。(省略可)
- //この例ではaFreeItemClass.timesプロパティを1に指定している
-// adjust : [-50, 50], //位置の微調整。必ずX座標、Y座標の相対位置を示す配列にする。(省略可)
-// extid : 19 //ネットワークを超えて一つのオブジェクトである必要がある場合にはゼロではない値を取る(ステージ内で固有の値, 省略可; 既定0)
-// sync : true //ネットワーク同期を有効に(addStageObjectの第二引数)(省略可; 既定false)
-
-var stgObjects = {
-
- // BlockClass : 普通のブロック。 引数に画像名を指定
- a : {base:BlockClass,args:'1190.png'},
-
- // SlopeBlockClass : 当たり判定が斜めのブロック。
- // 引数 : 画像名, 当たり判定領域左側の開始位置のブロック上辺からの高さ, 当たり判定領域右側の...
- // たとえば、この例のように 0, 32 と指定すれば右下がりの坂になり、32, 0と指定すれば左下がり、 16, 16と指定すれば半分の高さの長方形になる
- // enableBlockMode : 当たり判定領域をデバッグ表示する。
- b : {base:SlopeBlockClass,args:['1191.png',0,32],prop:{enableDebugMode:true}},
-
- // FreeItemClass : キャラが取得するとコールバックが実行されるアイテム
- // callback : 誰かに取得されたときに発生するコールバック。アタックした人、そのアタック直後のx, y座標が引数にセットされる。
- // times : 取得できる回数で、-1で無限。
- c : {base:FreeItemClass,args:["1234.png",callBack],prop:{times:1}},
-
- // 何もブロックを置かない位置のためにかならずこのようなエントリーを記述
- _ : null
-};
-
-// FreeItemClassのコールバック
-function callBack(obj, obj_x, obj_y)
-{
- if(obj instanceof MainCharacterClass){
-
- }
-}
-
-var stgInfo = {
- width: 6400, //横サイズ
- height: 480, //縦サイズ
- background: "back2.png" //背景画像。横幅は640pxである必要はない。
-};
-
-with(stgObjects) {
- var tbl = [
- [],
- [],
- [],
- [],
- [],
- [],
- [],
- [],
- [],
- [],
- [b],
- [_,b],
- [_,_,b],
- [_,_,_,b,_,_,_,_,_,c],
- [a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a],
- ];
-}
-
-//約束事
-var stage = new PCDSLStageClass(stgInfo, tbl);
-
-stage.runStage = function(){
- PCDSLStageClass.prototype.runStage.apply(this, []);
- var main = new MainCharacterClass(stage, [["kuma1.png","kuma2.png","kuma3.png", "kuma4.png", "kuma3.png", "kuma2.png"], ["kumaready.png"]]);
- main.size.x = 64;
- main.size.y=64;
- main.origin.x = 50;
- main.origin.y =0;
- main.ownerUID = stage.manager.userID;
- stage.userControlledCharacter = main;
- stage.addStageObject(main, true);
-},
-
-
-stage;
- </textarea>
- </div>
-
- <div id="info">
- <span class="countChar">0</span>
- <span class="currentLine">1</span>
- <span class="countLine">1</span>
- </div>
- </div>
- </div>
- <div id="openWindow" style="z-index : 100; position: absolute; top: 10%; left: 25%; right: 25%; height: 40%; border: 5px #666 solid; background-color: white; display: none">
- <div onclick="$('#openWindow').hide()" style="float: right; width: 4em; text-align: center; background-color: red; color: white; cursor: pointer">X</div>
- <h1>ファイルを開く</h1>
- このウィンドウにファイルをドロップしてください!<br>
- </div>
- <div id="selectWindow" style="z-index : 100; position: absolute; top: 10%; left: 25%; right: 25%; height: 40%; border: 5px #666 solid; background-color: white; display: none">
- <div onclick="$('#selectWindow').hide()" style="float: right; width: 4em; text-align: center; background-color: red; color: white; cursor: pointer">X</div>
- <h1>開く項目の選択</h1>
- 操作する項目: <br>
- <select id="select"></select><br>
- <input type="button" onclick="removeSelectedItem()" value="選択項目の削除"><input onclick="openSelectedItem()" type="button" value="開く"><br>
- ※savedat という名前の項目は次回起動時に自動的に開かれます
- </div>
- </body>
+<!DOCTYPE html>\r
+<html>\r
+ <head>\r
+ <meta charset="utf-8">\r
+ <title>PCDSL Editor</title>\r
+ <script type="text/javascript" src="include/jquery.js"></script>\r
+ <script type="text/javascript" src="include/jquery.textarea-util.js"></script>\r
+ <script type="text/javascript" src="include/jquery.selection.js"></script>\r
+ <script type="text/javascript" src="include/texteditor-script.js"></script>\r
+ <style type="text/css">\r
+html,body{\r
+ margin:0;padding:0;\r
+}\r
+#menubar{\r
+ background-color: #DED7B4;\r
+ overflow: hidden;\r
+ font-size: 18px;\r
+}\r
+#menubar>a{\r
+ display: block;\r
+ float: left;\r
+ padding: 0.5em 1em;\r
+ cursor: pointer;\r
+ margin-left: 5px;\r
+}\r
+#menubar>a:hover{\r
+ background-color: #BAAB63;\r
+\r
+}\r
+\r
+.window{\r
+ display: none;\r
+ height: 100%;\r
+ padding-bottom: 36px;\r
+ margin-bottom: -36px;\r
+ overflow: hidden;\r
+}\r
+textarea {\r
+ font-family: Consolas, 'Courier New', Courier, Monaco, monospace;\r
+ font-size: 12px;\r
+ line-height: 1.2;\r
+}\r
+\r
+#palletBox>div{\r
+ padding: 10px;\r
+ cursor: pointer;\r
+ border-bottom: 1px #666 solid;\r
+ overflow: hidden;\r
+}\r
+#palletBox>div:hover{\r
+ background-color: green;\r
+}\r
+#palletBox>div>img{\r
+ float: left;\r
+ width: 64px;\r
+ height: 64px;\r
+}\r
+\r
+#editorBox>div{\r
+ position: absolute;\r
+ width: 32px;\r
+ height: 32px;\r
+ color: black;\r
+ border: 1px black solid;\r
+}\r
+#editorBox>div>img{\r
+ position: absolute;\r
+ top: 0; left: 0; width: 32px; height: 32px;\r
+}\r
+#editorBox>div>div{\r
+ position: absolute;\r
+ top: 0; left: 0; right: 0; bottom: 0;\r
+ background-color: transparent;\r
+}\r
+ \r
+ </style>\r
+<script type="text/javascript">\r
+\r
+function resize()\r
+{\r
+ $('#textarea>textarea').css("width", $(window).width() - 30);\r
+ $('#textarea>textarea').css("height", $(window).height() - 120);\r
+ \r
+}\r
+\r
+var isModified = false;\r
+\r
+ // イベントをキャンセルするハンドラです.\r
+var cancelEvent = function(event) {\r
+ event.preventDefault();\r
+ event.stopPropagation();\r
+ return false;\r
+};\r
+\r
+function initDrop()\r
+{\r
+ var droppable = $("#openWindow");\r
+ \r
+ if(!window.FileReader) {\r
+ alert("File API がサポートされていません。");\r
+ window.close();\r
+ }\r
+ \r
+ \r
+ // dragenter, dragover イベントのデフォルト処理をキャンセルします.\r
+ droppable.bind("dragenter", cancelEvent);\r
+ droppable.bind("dragover", cancelEvent);\r
+ \r
+ // ドロップ時のイベントハンドラを設定します.\r
+ var handleDroppedFile = function(event) {\r
+ // ファイルは複数ドロップされる可能性がありますが, ここでは 1 つ目のファイルを扱います.\r
+ var file = event.originalEvent.dataTransfer.files[0];\r
+ \r
+ // ファイルの内容は FileReader で読み込みます.\r
+ var fileReader = new FileReader();\r
+ fileReader.onload = function(event) {\r
+ // event.target.result に読み込んだファイルの内容が入っています.\r
+ $("#textarea textarea").val(event.target.result);\r
+ \r
+ isModified = false;\r
+ browserFileName = null;\r
+ if(_guiMode)\r
+ {\r
+ if(!textToGui())\r
+ {\r
+ $('#guiWindow').fadeOut();\r
+ $('#textWindow').fadeIn();\r
+ _guiMode = false;\r
+ }\r
+ }\r
+ }\r
+ fileReader.readAsText(file);\r
+ \r
+ // デフォルトの処理をキャンセルします.\r
+ cancelEvent(event);\r
+ $('#openWindow').hide();\r
+ return false;\r
+ }\r
+ \r
+ // ドロップ時のイベントハンドラを設定します.\r
+ droppable.bind("drop", handleDroppedFile);\r
+ \r
+}\r
+\r
+window.onload = function(){\r
+\r
+ $(window).bind("dragenter", cancelEvent);\r
+ $(window).bind("dragover", cancelEvent);\r
+ $(window).bind("drop", cancelEvent);\r
+ initDrop();\r
+ resize();\r
+ \r
+ var oldData = localStorage.getItem("savedat");\r
+ if(oldData)\r
+ {\r
+ $('#textarea textarea').val(oldData);\r
+ }\r
+ \r
+ $('#textarea textarea').change(function(){\r
+ isModified = true;\r
+ });\r
+\r
+};\r
+\r
+window.onbeforeunload = function(e) {\r
+ if(isModified)\r
+ {\r
+ e = e || window.event;\r
+ return e.returnValue = '変更が保存されていません。破棄されますが続行しますか?';\r
+ }\r
+};\r
+\r
+function openFile()\r
+{\r
+ if(isModified)\r
+ {\r
+ if(!window.confirm("内容が変更されています。破棄されますがよろしいですか?")) return;\r
+ }\r
+ $('#openWindow').show();\r
+}\r
+\r
+function saveFile()\r
+{\r
+ var value = $('#textarea textarea').val();\r
+ var href = "data:application/octet-stream," + encodeURIComponent(value);\r
+ isModified = false;\r
+ location.href = href;\r
+ \r
+}\r
+\r
+var browserFileName = null;\r
+function saveToBrowser()\r
+{\r
+ if(browserFileName == null || !window.confirm("名前 " + browserFileName + " でよろしいですか?"))\r
+ {\r
+ var input = window.prompt("名前を入力してください");\r
+ if(!input)\r
+ {\r
+ return;\r
+ }\r
+ browserFileName = input;\r
+ }\r
+ \r
+ localStorage.setItem(browserFileName, $('#textarea textarea').val());\r
+ isModified = false;\r
+ window.alert("名前 " + browserFileName + " で保存しました");\r
+}\r
+\r
+function openFromBrowser()\r
+{\r
+ $('#selectWindow #select > option').remove();\r
+ for(var item in localStorage)\r
+ {\r
+ $('#selectWindow #select').append($('<option>').html(item).val(item));\r
+ }\r
+ $("#selectWindow").show();\r
+}\r
+\r
+function removeSelectedItem()\r
+{\r
+ var item = $("#selectWindow #select").val();\r
+ if(!item) return;\r
+ if(window.confirm(item + " の保存項目を削除しますか?"))\r
+ {\r
+ $('#selectWindow #select > option:selected').remove();\r
+ localStorage.removeItem(item);\r
+ }\r
+}\r
+\r
+function openSelectedItem()\r
+{\r
+ var item = $("#selectWindow #select").val();\r
+ if(!item) return;\r
+ if(isModified)\r
+ {\r
+ if(!window.confirm("変更されています。破棄されますがよろしいですか?")) return;\r
+ }\r
+ \r
+ $("#textarea textarea").val(localStorage.getItem(item));\r
+ \r
+ $("#selectWindow").hide();\r
+ isModified = false;\r
+ browserFileName = item;\r
+ if(_guiMode)\r
+ {\r
+ if(!textToGui())\r
+ {\r
+ $('#guiWindow').fadeOut();\r
+ $('#textWindow').fadeIn();\r
+ _guiMode = false;\r
+ }\r
+ }\r
+}\r
+\r
+function run()\r
+{\r
+ localStorage.setItem("previewStage", $("#textarea textarea").val());\r
+ window.open("../index_local_debug.html");\r
+}\r
+\r
+function editInTextEditor()\r
+{\r
+ if(!_guiMode) return;\r
+ $('#guiWindow').fadeOut();\r
+ $('#textWindow').fadeIn();\r
+ _guiMode = false;\r
+}\r
+\r
+function editInGui()\r
+{\r
+ if(_guiMode) return;\r
+ if(textToGui()) //gui移行に成功したら\r
+ {\r
+ $('#guiWindow').fadeIn();\r
+ $('#textWindow').fadeOut();\r
+ _guiMode = true;\r
+ }\r
+}\r
+\r
+var _guiStageInfo = null;\r
+var _guiTbl = null;\r
+var _guiElements = null;\r
+var _guiMode = false;\r
+var stgObjects = {};\r
+var stgSymbolVals = {};\r
+var stgSymbolImages = {};\r
+function textToGui()\r
+{\r
+ try{\r
+ var code = $("#textarea textarea").val();\r
+ \r
+ //コメントのマスク\r
+ var isInLineComment = false;\r
+ var isInComment = false;\r
+ for(var i = 0; i < code.length; i++)\r
+ {\r
+ if(isInComment)\r
+ {\r
+ if(code[i] == "*" && code[i + 1] == "/")\r
+ {\r
+ code++;\r
+ isInComment = false;\r
+ }else\r
+ {\r
+ code = code.slice(0, i) + "*" + code.slice(i + 1);\r
+ }\r
+ }\r
+ if(isInLineComment)\r
+ {\r
+ if(code[i] == "\n")\r
+ {\r
+ isInLineComment = false;\r
+ //}else if(code[i] == "/" && code[i + 1] == "*")\r
+ //{\r
+ // i++;\r
+ // isInLineComment = false;\r
+ // isInComment = true;\r
+ }else\r
+ {\r
+ code = code.slice(0, i) + "*" + code.slice(i + 1);\r
+ }\r
+ }else\r
+ {\r
+ if(code[i] == "/")\r
+ {\r
+ if(code[i + 1] == "*")\r
+ {\r
+ i++;\r
+ isInComment = true;\r
+ }else if(code[i + 1] == "/")\r
+ {\r
+ i++;\r
+ isInLineComment = true;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ \r
+ //stgObjectsの取得\r
+ stgObjects = {};\r
+ var objStart = code.indexOf("var stgObjects");\r
+ if(objStart == -1) throw new Error("stgObjectsの定義が見つかりません。");\r
+ var objLength = exploreEndParen(code.slice(objStart));\r
+ if(objLength == -1) throw new Error("stgObjectsの終端が見つかりません。カッコが不足している可能性があります。");\r
+ \r
+ var nextColon = objStart;\r
+ for(;;)\r
+ {\r
+ nextColon = code.indexOf(":", nextColon);\r
+ if(nextColon == -1 || nextColon >= objStart + objLength) break;\r
+ \r
+ var symbol = ""; // tbl[]で使う文字\r
+ var index = nextColon;\r
+ for(;;)\r
+ {\r
+ index--;\r
+ if(" \t */ \n".indexOf(code[index]) != -1)\r
+ {\r
+ if(symbol != "") break;\r
+ }else\r
+ {\r
+ symbol = code[index] + symbol;\r
+ }\r
+ }\r
+ \r
+ index = nextColon;\r
+ for(;;)\r
+ {\r
+ index++;\r
+ if(" \t ".indexOf(code[index]) == -1) break;\r
+ }\r
+ if(index >= objStart + objLength) throw new Error("stgObjectsの文法エラーです");\r
+ \r
+ var argLen;\r
+ if(code[index] == "{"){\r
+ argLen = exploreEndParen(code.slice(index));\r
+ }else\r
+ {\r
+ var argt = "";\r
+ var ind = index;\r
+ for(;;)\r
+ {\r
+ if(" \t/ \n".indexOf(code[ind]) != -1) break;\r
+ argt += code[ind];\r
+ ind++;\r
+ }\r
+ argLen = argt.length;\r
+ }\r
+ if(index + argLen >= objStart + objLength) throw new Error("stgObjectsの文法エラーです");\r
+ \r
+ var argText = code.slice(index, index + argLen); //文字に対応するコード\r
+ \r
+ // stgObjectsに登録\r
+ if(!stgObjects[symbol])\r
+ {\r
+ stgObjects[symbol] = symbol;\r
+ }else\r
+ {\r
+ throw new Error("シンボル" + symbol + "は二重定義されています");\r
+ }\r
+ \r
+ // stgSymbolValsに登録\r
+ stgSymbolVals[symbol] = argText;\r
+ \r
+ // 画像を探す\r
+ if(argText.indexOf(".png") != -1)\r
+ {\r
+ var ind = argText.indexOf(".png");\r
+ var imgName = ".png";\r
+ for(;;)\r
+ {\r
+ ind--;\r
+ if("\"'".indexOf(argText[ind]) != -1) break;\r
+ imgName = argText[ind] + imgName;\r
+ }\r
+ stgSymbolImages[symbol] = imgName;\r
+ \r
+ }else\r
+ {\r
+ stgSymbolImages[symbol] = null;\r
+ }\r
+ \r
+ nextColon = index + argLen;\r
+ \r
+ \r
+ }\r
+ \r
+ // tblの取得\r
+ var tblStart = code.indexOf("with(stgObjects)") + 16;\r
+ if(tblStart == -1) throw new Error("tbl[]が見つかりません。");\r
+ var tblLength = exploreEndParen(code.slice(tblStart));\r
+ if(tblLength == -1) throw new Error("tbl[]の終端が見つかりません。カッコが不足している可能性があります。");\r
+ var tblCode = "with(stgObjects)" + code.slice(tblStart, tblStart + tblLength);\r
+ try{\r
+ eval(tblCode); //これでtblにテーブルデータが入る\r
+ }catch(e)\r
+ {\r
+ if(e instanceof ReferenceError)\r
+ {\r
+ window.alert("tbl[] の中に StgObjects で定義されていない文字が含まれています。\nエラーの詳細:\n" + e.message);\r
+ return false;\r
+ }else\r
+ {\r
+ window.alert("stgObjects の中身の書式が間違っています\nエラーの詳細:\n" + e.message);\r
+ return false;\r
+ }\r
+ }\r
+ if(!tbl) return false;\r
+ _guiTbl = tbl; //_guiTbl に代入\r
+ \r
+ // stgInfoの取得\r
+ var infoStart = code.indexOf("var stgInfo");\r
+ if(infoStart == -1) throw new Error("stgInfoが見つかりません。");\r
+ var infoLength = exploreEndParen(code.slice(infoStart));\r
+ if(infoLength == -1) throw new Error("stgInfoの終端が見つかりません。カッコが不足している可能性があります。");\r
+ var infoCode = code.slice(infoStart, infoStart + infoLength);\r
+ try{\r
+ eval(infoCode);\r
+ }catch(e)\r
+ {\r
+ window.alert("var StgInfo の中身の書式が間違っています\nエラーの詳細:\n" + e.message);\r
+ return false;\r
+ }\r
+ if(!stgInfo) return false;\r
+ _guiStageInfo = stgInfo;\r
+ if(!stgInfo.width) return false;\r
+ if(!stgInfo.height) return false;\r
+ \r
+ \r
+ //パレットの初期化\r
+ \r
+ document.getElementById('palletBox').innerHTML = "";\r
+ \r
+ for(var symbol in stgObjects)\r
+ {\r
+ var div = document.createElement('div');\r
+ var p = document.createElement('p');\r
+ p.innerText = symbol + " : " + stgSymbolVals[symbol];\r
+ \r
+ if(stgSymbolImages[symbol] != null)\r
+ {\r
+ var img = document.createElement('img');\r
+ img.src = "../images/" + stgSymbolImages[symbol];\r
+ div.appendChild(img);\r
+ }\r
+ div.appendChild(p);\r
+ document.getElementById('palletBox').appendChild(div);\r
+ eval("func = function(){PalletItemClickEvent(\"" + symbol + "\");};");\r
+ div.addEventListener("click", func);\r
+ }\r
+ \r
+ \r
+ //作業領域の描画\r
+ var area = document.getElementById("editorBox");\r
+ $('#editorBox > div').remove();\r
+ _guiElements = [];\r
+ for(var y = 0; y < stgInfo.height / 32; y++)\r
+ {\r
+ _guiElements[y] = [];\r
+ for(var x = 0; x < stgInfo.width / 32; x++)\r
+ {\r
+ var element = document.createElement('div');\r
+ element.style.top = (y * 32) + "px";\r
+ element.style.left = (x * 32) + "px";\r
+ var img = document.createElement('img');\r
+ element.appendChild(img);\r
+ var div = document.createElement('div');\r
+ element.appendChild(div);\r
+ _guiElements[y][x] = element;\r
+ area.appendChild(element);\r
+ eval("onMouseDownFunc = function(){guiElementMouseDownEvent(" + x + ", " + y + ");};");\r
+ eval("onMouseUpFunc = function(){guiElementMouseUpEvent(" + x + ", " + y + ");};");\r
+ eval("onMouseOverFunc = function(){guiElementMouseOverEvent(" + x + ", " + y + ");};");\r
+ element.addEventListener("mousedown", onMouseDownFunc);\r
+ element.addEventListener("mouseover", onMouseOverFunc);\r
+ element.addEventListener("mouseup", onMouseUpFunc);\r
+ }\r
+ }\r
+ \r
+ var ignoreOverflow = false;\r
+ for(var y = 0; y < _guiTbl.length; y++)\r
+ {\r
+ for(var x = 0; x < _guiTbl[y].length; x++)\r
+ {\r
+ if(_guiElements[y] && _guiElements[y][x])\r
+ {\r
+ var symbol = _guiTbl[y][x];\r
+ var img = stgSymbolImages[symbol];\r
+ if(img != null)\r
+ {\r
+ $(_guiElements[y][x]).find("img").attr('src', "../images/" +img);\r
+ }else\r
+ {\r
+ $(_guiElements[y][x]).find("div").text(symbol);\r
+ }\r
+ }else if(!ignoreOverflow)\r
+ {\r
+ if(window.confirm("tbl[]のサイズがステージのサイズをオーバーしています。はみ出た分を破棄して続行しますか? (破棄したくない場合は、「いいえ」で戻ってステージのサイズを大きくするかtbl[]の要素数を確認してください)"))\r
+ {\r
+ ignoreOverflow = true;\r
+ }else\r
+ {\r
+ return false;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ return true;\r
+ }catch(e)\r
+ {\r
+ if(e instanceof Error)\r
+ {\r
+ \r
+ //アプリ内で起こされたエラー\r
+ window.alert(e.message);\r
+ }else\r
+ {\r
+ window.alert("不明なエラーです\nエラーの詳細:\n" + (e.message));\r
+ }\r
+ return false;\r
+ }\r
+}\r
+\r
+var mouseState = false;\r
+function guiElementMouseDownEvent(x, y)\r
+{\r
+ mouseState = true;\r
+ if($('#toolBox input:radio:checked').val() == 'pen')\r
+ {\r
+ var img = stgSymbolImages[selectedPalletItem];\r
+ if(img != null)\r
+ {\r
+ $(_guiElements[y][x]).find("img").attr('src', "../images/" + img);\r
+ $(_guiElements[y][x]).find("div").text("");\r
+ }else\r
+ {\r
+ $(_guiElements[y][x]).find("img").attr('src', "../images/null.png");\r
+ $(_guiElements[y][x]).find("div").text(selectedPalletItem);\r
+ }\r
+ \r
+ _guiTbl[y][x] = selectedPalletItem;\r
+ GuiToText();\r
+ }\r
+}\r
+\r
+function guiElementMouseUpEvent(x, y)\r
+{\r
+ mouseState = false;\r
+ if($('#toolBox input:radio:checked').val() == "addr")\r
+ {\r
+ window.alert("位置(" + x + ", " + y + ")\n座標(" + (x * 32) + ", " + (y * 32) + ")");\r
+ }\r
+}\r
+\r
+function guiElementMouseOverEvent(x, y)\r
+{\r
+ if(mouseState && $('#toolBox input:radio:checked').val() == 'pen')\r
+ {\r
+ var img = stgSymbolImages[selectedPalletItem];\r
+ if(img != null)\r
+ {\r
+ $(_guiElements[y][x]).find("img").attr('src', "../images/" + img);\r
+ $(_guiElements[y][x]).find("div").text("");\r
+ }else\r
+ {\r
+ $(_guiElements[y][x]).find("img").attr('src', "../images/null.png");\r
+ $(_guiElements[y][x]).find("div").text(selectedPalletItem);\r
+ }\r
+ \r
+ _guiTbl[y][x] = selectedPalletItem;\r
+ GuiToText();\r
+ }\r
+}\r
+\r
+function guiElementClickEvent(x,y)\r
+{\r
+ var val = $('#stageBox input:radio:checked').val();\r
+ if(val == "addr")\r
+ {\r
+ window.alert("位置(" + x + ", " + y + ")\n座標(" + (x * 32) + ", " + (y * 32) + ")");\r
+ }else if(val == "other")\r
+ {\r
+ val = window.prompt("ブロックとして使用する文字を入力してください(通常は一文字か二文字の英文字です)");\r
+ if(val)\r
+ {\r
+ $(_guiElements[y][x]).text(val);\r
+ _guiTbl[y][x] = val;\r
+ GuiToText();\r
+ }\r
+ }else\r
+ {\r
+ $(_guiElements[y][x]).text(val);\r
+ _guiTbl[y][x] = val;\r
+ GuiToText();\r
+ }\r
+}\r
+\r
+var selectedPalletItem = "";\r
+function PalletItemClickEvent(symbol)\r
+{\r
+ $('#selectedSymbol').text(symbol);\r
+ selectedPalletItem = symbol;\r
+}\r
+\r
+function GuiToText()\r
+{\r
+ var code = $("#textarea textarea").val();\r
+ var tblCode = "with(stgObjects){\n\tvar tbl = [\n";\r
+ for(var y = 0; y < _guiStageInfo.height / 32; y++)\r
+ {\r
+ tblCode += "\t\t[";\r
+ if(_guiTbl[y])\r
+ {\r
+ for(var x = 0; x < _guiStageInfo.width / 32; x++)\r
+ {\r
+ if(_guiTbl[y][x])\r
+ {\r
+ tblCode += _guiTbl[y][x];\r
+ }else\r
+ {\r
+ tblCode += " ";\r
+ }\r
+ tblCode += ",";\r
+ }\r
+ if(tblCode.slice(tblCode.length - 1) == ",") tblCode = tblCode.slice(0, tblCode.length - 1);\r
+ }\r
+ tblCode += "],\n";\r
+ }\r
+ if(tblCode.slice(tblCode.length - 3) == "],\n") tblCode = tblCode.slice(0, tblCode.length - 2) + "\n";\r
+ tblCode += "\t];\n";\r
+ tblCode += "}";\r
+ var tblStart = code.indexOf("with(stgObjects)");\r
+ if(tblStart == -1) return false;\r
+ var tblLength = exploreEndParen(code.slice(tblStart + 16)) + 16;\r
+ if(tblLength == 15) return false;\r
+ \r
+ code = code.slice(0, tblStart) + tblCode + code.slice(tblStart + tblLength);\r
+ $("#textarea textarea").val(code);\r
+ \r
+ isModified = true;\r
+ return true;\r
+}\r
+\r
+// 最後にカッコが閉じて最初と同じレベルに到達するまでのインデックスを返す。カッコが閉じられずに終わったら(もしくは急に閉じかっこが出てきたら)-1 \r
+function exploreEndParen(text)\r
+{\r
+ var nest = 0;\r
+ \r
+ for(var i = 0; i < text.length; i++)\r
+ {\r
+ if(text[i] == '{' || text[i] == '(' || text[i] == '[') nest++;\r
+ else if(text[i] == '}' || text[i] == ')' || text[i] == ']')\r
+ {\r
+ nest--;\r
+ if(nest < 0) //開始カッコがないのに急に終了カッコが出てきた\r
+ {\r
+ return -1;\r
+ }else if(nest == 0)\r
+ {\r
+ return i + 1; //カッコの後ろまで含める\r
+ }\r
+ }\r
+ }\r
+ \r
+ return nest != 0 ? -1 : i;\r
+}\r
+\r
+$(window).bind("resize", resize);\r
+\r
+</script>\r
+ </head>\r
+ <body>\r
+ <div id="menubar">\r
+ <a onclick="openFile();">開く</a>\r
+ <a onclick="saveFile()">名前を付けて保存</a>\r
+ <a onclick="openFromBrowser()">ブラウザから開く</a>\r
+ <a onclick="saveToBrowser();">ブラウザに保存</a>\r
+ <a onclick="editInGui();">GUI編集</a>\r
+ <a onclick="editInTextEditor()">テキスト編集</a>\r
+ <a onclick="run()">実行</a>\r
+ <a target="_blank" href="readme.txt">ヘルプ</a>\r
+ <a target="_blank" href="./expression.html">文法ヘルプ</a>\r
+ </div>\r
+ <div id="guiWindow" class="window">\r
+ <div style="float: left; width: 30%; background-color: #eee; padding: 30px; margin-bottom: -32737px; margin-right: 30px; padding-bottom: 32767px;">\r
+ <strong>パレット</strong><br>\r
+ <div id="palletBox" style="height: 500px; overflow: scroll; background-color: white; border: 1px black solid; margin: 10px;">\r
+ \r
+ </div>\r
+ <strong>選択された項目</strong><br>\r
+ <div id="selectedSymbol"></div><br>\r
+ <strong>ツール</strong><br>\r
+ <div id="toolBox">\r
+ <input id="penTool" type="radio" name="tool" value="pen" checked>ペン<br>\r
+ <input type="radio" name="tool" value="addr">座標の取得<br>\r
+ </div>\r
+ </div>\r
+ <div style="padding: 30px;">\r
+ <strong>エディット</strong>\r
+ <div id="editorBox" style="user-select: none; -webkit-user-select: none; -khtml-user-select: none; height: 500px; overflow: scroll; background-color: white; border: 1px black solid; margin: 10px; position: relative; font-size: 32px;"></div>\r
+ <div id="editorMessageBox"></div>\r
+ </div>\r
+ </div>\r
+ <div id="textWindow" class="window" style="display: block;">\r
+ <div id="wrapper" style="height: 100%;">\r
+ <div id="textarea" style="width: 100%;">\r
+ <textarea wrap="off">\r
+// StageObjectsはステージに文字シンボルとして配置したいオブジェクト定義の連想配列である。\r
+// StageObjectの各項目の指定方法は以下の二通りある。\r
+// ・クラス名指定 ... コンストラクタがに引数が不要な時\r
+// a : BlockClass\r
+// ・拡張指定\r
+// a : {base : FreeItemClass, //鋳型となるクラス名\r
+// args : '1190.png', //コンストラクタに指定する引数(一つだけの場合) stageは自動で指定されるので不要\r
+// args : ['1190.png', callback], //二つ以上の場合。やはり第一引数のstageは不要\r
+// prop : {times : 1}, //各インスタンスに指定したいプロパティの連想配列。(省略可)\r
+ //この例ではaFreeItemClass.timesプロパティを1に指定している\r
+// adjust : [-50, 50], //位置の微調整。必ずX座標、Y座標の相対位置を示す配列にする。(省略可)\r
+// extid : 19 //ネットワークを超えて一つのオブジェクトである必要がある場合にはゼロではない値を取る(ステージ内で固有の値, 省略可; 既定0)\r
+// sync : true //ネットワーク同期を有効に(addStageObjectの第二引数)(省略可; 既定false)\r
+\r
+var stgObjects = {\r
+ \r
+ // BlockClass : 普通のブロック。 引数に画像名を指定\r
+ a : {base:BlockClass,args:'1190.png'},\r
+ \r
+ // SlopeBlockClass : 当たり判定が斜めのブロック。\r
+ // 引数 : 画像名, 当たり判定領域左側の開始位置のブロック上辺からの高さ, 当たり判定領域右側の...\r
+ // たとえば、この例のように 0, 32 と指定すれば右下がりの坂になり、32, 0と指定すれば左下がり、 16, 16と指定すれば半分の高さの長方形になる\r
+ // enableBlockMode : 当たり判定領域をデバッグ表示する。\r
+ b : {base:SlopeBlockClass,args:['1191.png',0,32],prop:{enableDebugMode:true}},\r
+ \r
+ // FreeItemClass : キャラが取得するとコールバックが実行されるアイテム\r
+ // callback : 誰かに取得されたときに発生するコールバック。アタックした人、そのアタック直後のx, y座標が引数にセットされる。\r
+ // times : 取得できる回数で、-1で無限。\r
+ c : {base:FreeItemClass,args:["1234.png",callBack],prop:{times:1}},\r
+ \r
+ // 何もブロックを置かない位置のためにかならずこのようなエントリーを記述\r
+ _ : null\r
+};\r
+\r
+// FreeItemClassのコールバック\r
+function callBack(obj, obj_x, obj_y)\r
+{\r
+ if(obj instanceof MainCharacterClass){\r
+\r
+ }\r
+}\r
+\r
+var stgInfo = {\r
+ width: 6400, //横サイズ\r
+ height: 480, //縦サイズ\r
+ background: "back2.png" //背景画像。横幅は640pxである必要はない。\r
+};\r
+\r
+with(stgObjects) {\r
+ var tbl = [\r
+ [],\r
+ [],\r
+ [],\r
+ [],\r
+ [],\r
+ [],\r
+ [],\r
+ [],\r
+ [],\r
+ [],\r
+ [b],\r
+ [_,b],\r
+ [_,_,b],\r
+ [_,_,_,b,_,_,_,_,_,c],\r
+ [a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a],\r
+ ];\r
+}\r
+\r
+//約束事\r
+var stage = new PCDSLStageClass(stgInfo, tbl);\r
+\r
+stage.runStage = function(){\r
+ PCDSLStageClass.prototype.runStage.apply(this, []);\r
+ var main = new MainCharacterClass(stage, [["kuma1.png","kuma2.png","kuma3.png", "kuma4.png", "kuma3.png", "kuma2.png"], ["kumaready.png"]]);\r
+ main.size.x = 64;\r
+ main.size.y=64;\r
+ main.origin.x = 50;\r
+ main.origin.y =0;\r
+ main.ownerUID = stage.manager.userID;\r
+ stage.userControlledCharacter = main;\r
+ stage.addStageObject(main, true);\r
+},\r
+\r
+\r
+stage;\r
+ </textarea>\r
+ </div>\r
+ \r
+ <div id="info">\r
+ <span class="countChar">0</span>\r
+ <span class="currentLine">1</span>\r
+ <span class="countLine">1</span>\r
+ </div>\r
+ </div>\r
+ </div>\r
+ <div id="openWindow" style="z-index : 100; position: absolute; top: 10%; left: 25%; right: 25%; height: 40%; border: 5px #666 solid; background-color: white; display: none">\r
+ <div onclick="$('#openWindow').hide()" style="float: right; width: 4em; text-align: center; background-color: red; color: white; cursor: pointer">X</div>\r
+ <h1>ファイルを開く</h1>\r
+ このウィンドウにファイルをドロップしてください!<br>\r
+ </div>\r
+ <div id="selectWindow" style="z-index : 100; position: absolute; top: 10%; left: 25%; right: 25%; height: 40%; border: 5px #666 solid; background-color: white; display: none">\r
+ <div onclick="$('#selectWindow').hide()" style="float: right; width: 4em; text-align: center; background-color: red; color: white; cursor: pointer">X</div>\r
+ <h1>開く項目の選択</h1>\r
+ 操作する項目: <br>\r
+ <select id="select"></select><br>\r
+ <input type="button" onclick="removeSelectedItem()" value="選択項目の削除"><input onclick="openSelectedItem()" type="button" value="開く"><br>\r
+ ※savedat という名前の項目は次回起動時に自動的に開かれます\r
+ </div>\r
+ </body>\r
</html>
\ No newline at end of file