diff --git a/API列表.txt b/API列表.txt index b2013082..4ed96670 100644 --- a/API列表.txt +++ b/API列表.txt @@ -661,8 +661,9 @@ core.clearStatusBar() 清空状态栏的数据。 -core.updateStatusBar() +core.updateStatusBar(doNotCheckAutoEvents) 更新状态栏,被转发到了脚本编辑中。此函数还会根据是否在回放来设置工具栏的图标。 +如果doNotCheckAutoEvents为true则此时不检查自动事件。 core.showStatusBar() / core.hideStatusBar(showToolbox) diff --git a/README.md b/README.md index 7ccf34ca..2345887d 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏! ``` bash ├── /_server/ # 为可视化地图编辑器提供一些支持的目录 ├── /docs/ # 文档目录 +├── /extensions/ # 拓展工具目录,发布到网站后不会加载 ├── /libs/ # 系统库目录 │ ├─ /thirdparty/ # 游戏所用到的第三方库文件 │ ├─ actions.js # 处理用户交互的文件 @@ -25,6 +26,7 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏! │ ├─ data.js # 记录了一些初始化信息 │ ├─ enemys.js # 记录了怪物的信息,包括特殊属性、伤害计算公式、临界值计算等。 │ ├─ events.js # 处理事件的文件,所有自定义事件都会在此文件中进行处理 +│ ├─ extensions.js # 加载拓展工具的文件 │ ├─ icons.js # 图标信息,会被转发到project下 │ ├─ items.js # 道具信息,会被转发到project下 │ ├─ loader.js # 动态加载JS代码、图片、音效等 @@ -55,6 +57,23 @@ HTML5 canvas制作的魔塔样板,支持全平台游戏! ## 更新说明 +### 2019.10.29 HTML5魔塔样板V2.6.4 + +* [x] 自动事件,多事件页 +* [x] 增加开场logo动画 +* [x] 拓展:游戏时动态修改地图和怪物数据 +* [x] 插件:道具商店,支持买入和卖出道具 +* [x] 编辑器可以搜索变量出现位置 +* [x] 变量的中文替换 +* [x] 可以给图块绑定自定义脚本,碰触时触发 +* [x] 编辑器右键可以绑定机关门和出生点 +* [x] 支持多个drawTip同时出现 +* [x] 闪烁光标同时支持多个同时存在 +* [x] 插件:镜头平滑移动,默认禁用 +* [x] 素材的快速追加 +* [x] 批量导出动画 +* [x] 部分Bug修复,大量细节优化 + ### 2019.7.24 V2.6.3 * [x] 标题界面大幅美化,增加闪烁光标,支持键盘开始游戏 diff --git a/_docs/api.md b/_docs/api.md index 6424dcf3..38916a10 100644 --- a/_docs/api.md +++ b/_docs/api.md @@ -654,9 +654,9 @@ core.clearStatusBar() 清空状态栏的数据。 -core.updateStatusBar() +core.updateStatusBar(doNotCheckAutoEvents) 更新状态栏,被转发到了脚本编辑中。此函数还会根据是否在回放来设置工具栏的图标。 - +如果doNotCheckAutoEvents为true则此时不检查自动事件。 core.showStatusBar() / core.hideStatusBar(showToolbox) 显示和隐藏状态栏。 @@ -973,6 +973,10 @@ core.getCommonEvent(name) core.recoverEvents(data) 恢复事件现场。一般用于呼出怪物手册、呼出存读档页面等时,恢复事件执行流。 +core.checkAutoEvents() +检测自动事件并执行。 + + // ------ 点击状态栏图标时执行的一些操作 ------ // core.openBook(fromUserAction) @@ -1220,6 +1224,10 @@ core.quickSaveEquip(index) core.quickLoadEquip() 读取当前套装。index为读取的套装编号。 + + +core.getEquippedStatus(name) +获得装备直接增加的属性数据。 ``` ## loader.js @@ -1711,11 +1719,16 @@ core.clearUI() 重置UI窗口。此函数将清掉所有的UI帧动画和光标,清空UI画布,并将alpha设为1。 -core.drawTip(text, id) +core.drawTip(text, id, clear) 在左上角以气泡的形式绘制一段提示。 text为文字内容,仅支持${}的表达式计算,不支持换行和变色。 id可选,为同时绘制的图标ID,如果不为null则会同时绘制该图标(仅对32x32的素材有效)。 也可以使用状态栏的图标ID,例如lv, hp, up, save, settings等。 +如果clear为true,则会清空当前所有正在显示的提示。 + + +core.clearTip() +清空当前所有正在显示的提示。 core.drawText(content, callback) @@ -1757,6 +1770,7 @@ config为绘制的配置项,目前可以包括如下几项: - fontSize:字体大小,如果不设置则使用剧情文本设置中的正文字体大小。 - lineHeight:绘制的行距值,如果不设置则使用fontSize*1.3(即1.3倍行距)。 - time:打字机效果。若不为0,则会逐个字进行绘制,并设置core.status.event.interval定时器。 + - interval:字符间的间距。值表示绘制每个字符之间间隔的距离,默认为0。 core.drawTextBox(content, showAll) diff --git a/_docs/event.md b/_docs/event.md index aaf97b4a..461b2c9c 100644 --- a/_docs/event.md +++ b/_docs/event.md @@ -413,6 +413,8 @@ textfont为可选项,表示正文字体大小(px为单位)。默认值:` time为可选项,表示文字添加的速度。若此项设置为0将直接全部显示,若大于0则会设置为相邻字符依次显示的时间间隔。 默认值:`0` +interval为可选项,表示文字之间的间距。单位为像素值。默认值:`0` + ### tip:显示一段提示文字 `{"type": "tip"}`可以在左上角显示一段提示文字。 @@ -2193,14 +2195,14 @@ UI绘制事件。此事件可以绘制闪烁光标。 ```js [ - {"type": "drawSelector", "image": "winskin.png", "x": 0, "y": 0, "width": 100, "height": 100}, + {"type": "drawSelector", "image": "winskin.png", "x": 0, "y": 0, "width": 100, "height": 100, "clear": true}, {"type": "drawSelector"} // 清除闪烁光标 ] ``` image为要绘制的WindowSkin图片名;如果不填则视为“清除闪烁光标”。 -x, y, width, height分别为要绘制的起点坐标和长宽。 +x, y, width, height分别为要绘制的起点坐标和长宽。clear可选,如果为true则在绘制前清空已有光标。 请注意,同时只会有一个闪烁光标存在,如果创建多个则后者会替换前者。 @@ -2242,6 +2244,26 @@ core.insertAction([ !> 从V2.5.3开始,提供了一个"不自动执行下一个事件"的选项(`"async": true`)。如果设置了此项,那么在该部分代码执行完毕后,不会立刻执行下一个事件。你需要在脚本中手动调用`core.events.doAction()`来执行下一个事件。可以通过此项来实现一些异步的代码,即在异步函数的回调中再执行下一个事件。使用此选项请谨慎,最好向开发者寻求咨询。 +## 自动事件 + +从V2.6.4开始,提供了自动事件。每个点都可以绑定若干个自动事件,其类似于RM的事件页。 + +自动事件可以设置一个触发条件,当满足此条件时将自动执行。 + +![](img/autoEvent.png) + +自动事件可以设置如下几项内容: + +- 条件:当满足此条件时将自动执行 +- 优先级:当多个自动事件的条件同时满足时,将按照优先级从大到小执行;相同优先级的按照楼层和坐标排序。 +- 仅在本层检测:是否仅在本层检测该条件。 +- 事件流中延迟执行:如果此项为true,则若满足条件时正在事件流的处理中,则将该自动事件延迟到事件流结束时执行。 +- 允许多次执行:如果此项为true,则该自动事件允许被多次触发;否则只会被触发一次。值得注意的是,即使允许多次触发,也不允许在正在执行本自动事件时再触发。(即在执行本自动事件时将暂时禁用自身,直到执行完毕为止) + +自动事件的检测时机为刷新状态栏,即每次刷新状态栏时都会进行检测。 + +可以给自动事件加上【转变图块】,从而达到类似RM的多事件页并转变图块的效果 + ## 独立开关 从V2.5.3开始,针对每个事件都提供了独立开关。 diff --git a/_docs/img/autoEvent.png b/_docs/img/autoEvent.png new file mode 100644 index 00000000..06dd923e Binary files /dev/null and b/_docs/img/autoEvent.png differ diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index 79b11511..49220756 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -26,12 +26,33 @@ return code; */; +//自动事件 事件编辑器入口之一 +autoEvent_m + : '自动事件:' '触发条件' EvalString '优先级' Int BGNL? Newline '仅在本层检测' Bool '事件流中延迟执行' Bool '允许多次执行' Bool BGNL? Newline action+ BEND + + +/* autoEvent_m +tooltip : ????? +helpUrl : https://h5mota.com/games/template/_docs/#/event +default : ["flag:__door__==2",0,true,false,false,null] +var code = { + "condition": EvalString_0, // 条件不可为null + "currentFloor": Bool_0, // 是否仅在本层检测 + "priority": Int_0, // 优先级 + "delayExecute": Bool_1, // 延迟执行 + "multiExecute": Bool_2, // 是否允许多次执行 + "data": 'autoEvent_asdfefw', // 事件列表 +}; +code=JSON.stringify(code,null,2).split('"autoEvent_asdfefw"').join('[\n'+action_0+']\n'); +return code; +*/; + //升级 事件编辑器入口之一 level_m : '等级提升' BGNL? Newline levelCase+ BEND -/* level_m +/* level_mexpression tooltip : 升级事件 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e7%bb%8f%e9%aa%8c%e5%8d%87%e7%ba%a7%ef%bc%88%e8%bf%9b%e9%98%b6%2f%e5%a2%83%e7%95%8c%e5%a1%94%ef%bc%89 var code = '[\n'+levelCase_0+']\n'; @@ -65,6 +86,7 @@ return code; shoplist : shopsub + | shopitem | shopcommonevent | emptyshop ; @@ -79,7 +101,7 @@ return code; */; shopcommonevent - : '商店 id' IdString '快捷商店栏中名称' EvalString BGNL? '未开启状态则不显示在列表中' Bool BGNL? '执行的公共事件 id' EvalString '参数列表' EvalString? + : '公共事件版商店 id' IdString '快捷商店栏中名称' EvalString BGNL? '未开启状态则不显示在列表中' Bool BGNL? '执行的公共事件 id' EvalString '参数列表' EvalString? /* shopcommonevent tooltip : 全局商店, 执行一个公共事件 @@ -156,6 +178,45 @@ var code = idString_e_0+'+='+expression_0+';' return code; */; +shopitem + : '道具商店 id' IdString '快捷商店栏中名称' EvalString BGNL? '未开启状态则不显示在列表中' Bool BGNL? Newline shopItemChoices+ BEND + + +/* shopitem +tooltip : 道具商店 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e5%85%a8%e5%b1%80%e5%95%86%e5%ba%97 +default : ["itemShop","道具商店",false] +var code = { + 'id': IdString_0, + 'item': true, + 'textInList': EvalString_0, + 'mustEnable': Bool_0, + 'choices': 'choices_aqwedsa' +} +code=JSON.stringify(code,null,2).split('"choices_aqwedsa"').join('[\n'+shopItemChoices_0+']\n')+',\n'; +return code; +*/; + +shopItemChoices + : '道具名' IdString '存量' EvalString? '买入价格' EvalString? '卖出价格' EvalString? '出现条件' EvalString? BEND + + + +/* shopItemChoices +tooltip : 道具商店选项,每一项是道具名;买入或卖出可以不填表示只能卖出或买入 +helpUrl : https://h5mota.com/games/template/_docs/#/event?id=%e5%85%a8%e5%b1%80%e5%95%86%e5%ba%97 +default : ["yellowKey","","10","",""] +colour : this.subColor +if (EvalString_0 && !/^\d+$/.test(EvalString_0)) throw "存量必须不填或非负整数"; +EvalString_0 = EvalString_0 ? (', "number": '+EvalString_0) : ''; +EvalString_1 = EvalString_1 ? (', "money": "'+EvalString_1+'"') : ''; +EvalString_2 = EvalString_2 ? (', "sell": "'+EvalString_2+'"') : ''; +if (!EvalString_1 && !EvalString_2) throw "买入金额和卖出金额至少需要填写一个"; +EvalString_3 = EvalString_3 ? (', "condition": "'+EvalString_3+'"') : ''; +var code = '{"id": "' + IdString_0 + '"' + EvalString_0 + EvalString_1 + EvalString_2 + EvalString_3 + '},\n'; +return code; +*/; + //afterBattle 事件编辑器入口之一 afterBattle_m : '战斗结束后' BGNL? Newline action+ BEND @@ -458,13 +519,13 @@ return code; */; setText_s - : '设置剧情文本的属性' '位置' SetTextPosition_List '偏移像素' EvalString? '对齐' TextAlign_List? BGNL? '标题颜色' EvalString? Colour '正文颜色' EvalString? Colour '背景色' EvalString? Colour BGNL? '粗体' B_1_List '标题字体大小' EvalString? '正文字体大小' EvalString? '打字间隔' EvalString? Newline + : '设置剧情文本的属性' '位置' SetTextPosition_List '偏移像素' EvalString? '对齐' TextAlign_List? BGNL? '标题颜色' EvalString? Colour '正文颜色' EvalString? Colour '背景色' EvalString? Colour BGNL? '粗体' B_1_List '标题字体大小' EvalString? '正文字体大小' EvalString? '打字间隔' EvalString? '字符间距' EvalString? Newline /* setText_s -tooltip : setText:设置剧情文本的属性,颜色为RGB三元组或RGBA四元组,打字间隔为剧情文字添加的时间间隔,为整数或不填 +tooltip : setText:设置剧情文本的属性,颜色为RGB三元组或RGBA四元组,打字间隔为剧情文字添加的时间间隔,为整数或不填,字符间距为字符之间的距离,为整数或不填。 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=settext%EF%BC%9A%E8%AE%BE%E7%BD%AE%E5%89%A7%E6%83%85%E6%96%87%E6%9C%AC%E7%9A%84%E5%B1%9E%E6%80%A7 -default : [null,"",null,"",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',null,"","",""] +default : [null,"",null,"",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',null,"","","",""] SetTextPosition_List_0 =SetTextPosition_List_0==='null'?'': ', "position": "'+SetTextPosition_List_0+'"'; TextAlign_List_0 = TextAlign_List_0==='null'?'': ', "align": "'+TextAlign_List_0+'"'; var colorRe = MotaActionFunctions.pattern.colorRe; @@ -503,8 +564,12 @@ if (EvalString_6) { if (!/^\d+$/.test(EvalString_6))throw new Error('打字时间间隔必须是整数或不填'); EvalString_6 = ', "time": '+EvalString_6; } +if (EvalString_7) { + if (!/^\d+$/.test(EvalString_7))throw new Error('字符间距必须是整数或不填'); + EvalString_7 = ', "interval": '+EvalString_7; +} B_1_List_0 = B_1_List_0==='null'?'':', "bold": '+B_1_List_0; -var code = '{"type": "setText"'+SetTextPosition_List_0+EvalString_0+TextAlign_List_0+EvalString_1+EvalString_2+B_1_List_0+EvalString_3+EvalString_4+EvalString_5+EvalString_6+'},\n'; +var code = '{"type": "setText"'+SetTextPosition_List_0+EvalString_0+TextAlign_List_0+EvalString_1+EvalString_2+B_1_List_0+EvalString_3+EvalString_4+EvalString_5+EvalString_6+EvalString_7+'},\n'; return code; */; @@ -2367,27 +2432,28 @@ return code; */; drawSelector_s - : '绘制闪烁光标' EvalString '起点像素' 'x' PosString 'y' PosString '宽' PosString '高' PosString Newline + : '绘制闪烁光标' EvalString '编号' Int '起点像素' 'x' PosString 'y' PosString '宽' PosString '高' PosString Newline /* drawSelector_s tooltip : drawSelector:绘制闪烁光标 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=drawSelector%ef%bc%9a%e7%bb%98%e5%88%b6%e9%97%aa%e7%83%81%e5%85%89%e6%a0%87 -default : ["winskin.png","0","0","100","100"] +default : ["winskin.png","1","0","0","100","100"] colour : this.subColor -var code = '{"type": "drawSelector", "image": "'+EvalString_0+'", "x": '+PosString_0+', "y": '+PosString_1+', "width": '+PosString_2+', "height": '+PosString_3+'},\n'; +var code = '{"type": "drawSelector", "image": "'+EvalString_0+'", "code": '+Int_0+', "x": '+PosString_0+', "y": '+PosString_1+', "width": '+PosString_2+', "height": '+PosString_3+'},\n'; return code; */; drawSelector_1_s - : '清除闪烁光标' Newline + : '清除闪烁光标' '编号' Int Newline /* drawSelector_1_s tooltip : drawSelector:清除闪烁光标 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=showImage%ef%bc%9a%e6%98%be%e7%a4%ba%e5%9b%be%e7%89%87 +default : ["1"] colour : this.subColor -var code = '{"type": "drawSelector"},\n'; +var code = '{"type": "drawSelector", "code": '+Int_0+'},\n'; return code; */; @@ -2495,7 +2561,7 @@ idString_e /* idString_e colour : this.idstring_eColor -default : ["status:hp"] +default : ["变量:生命"] var code = IdString_0; return [code, Blockly.JavaScript.ORDER_ATOMIC]; */; @@ -2509,7 +2575,7 @@ idString_1_e colour : this.idstring_eColor default : [null,"自定义flag"] //todo 将其output改成'idString_e' -var code = Id_List_0+':'+IdText_0; +var code = MotaActionFunctions.replaceFromName(MotaActionFunctions.replaceToName(Id_List_0+':'+IdText_0)); return [code, Blockly.JavaScript.ORDER_ATOMIC]; */; @@ -2755,6 +2821,12 @@ ActionParser.prototype.parse = function (obj,type) { obj.trigger==='action',obj.enable,obj.noPass,obj.displayDamage,this.parseList(obj.data) ]); + case 'autoEvent': + if(!obj)obj={}; + return MotaActionBlocks['autoEvent_m'].xmlText([ + obj.condition,obj.priority,obj.currentFloor,obj.delayExecute,obj.multiExecute,this.parseList(obj.data) + ]); + case 'changeFloor': if(!obj)obj={}; if(!this.isset(obj.loc)) { @@ -2812,11 +2884,25 @@ ActionParser.prototype.parse = function (obj,type) { obj.id,parser.EvalString(obj.textInList),obj.mustEnable,parser.EvalString(obj.commonEvent),obj.args,next ]); } + var builditem = function (obj,parser,next){ + var text_choices = null; + for(var ii=obj.choices.length-1,choice;choice=obj.choices[ii];ii--) { + text_choices = MotaActionBlocks['shopItemChoices'].xmlText([ + choice.id, choice.number == null ? "" : (""+choice.number), choice.money == null ? "" : (""+choice.money), + choice.sell == null ? "" : (""+choice.sell), choice.condition || "", text_choices + ]); + } + return MotaActionBlocks['shopitem'].xmlText([ + obj.id,obj.textInList,obj.mustEnable,text_choices,next + ]); + } var next=null; if(!obj)obj=[]; while(obj.length){ var shopobj=obj.pop() - if(shopobj.choices) + if(shopobj.item) + next=builditem(shopobj,this,next); + else if(shopobj.choices) next=buildsub(shopobj,this,next); else if(shopobj.commonEvent) next=buildcommentevent(shopobj,this,next); @@ -2901,7 +2987,7 @@ ActionParser.prototype.parseAction = function() { this.next = MotaActionBlocks['setText_s'].xmlText([ data.position,data.offset,data.align,data.title,'rgba('+data.title+')', data.text,'rgba('+data.text+')',data.background,'rgba('+data.background+')', - data.bold,data.titlefont,data.textfont,data.time,this.next]); + data.bold,data.titlefont,data.textfont,data.time,data.interval,this.next]); break; case "tip": this.next = MotaActionBlocks['tip_s'].xmlText([ @@ -3513,11 +3599,11 @@ ActionParser.prototype.parseAction = function() { case "drawSelector": // 绘制光标 if (data.image) { this.next = MotaActionBlocks['drawSelector_s'].xmlText([ - data.image, data.x, data.y, data.width, data.height, this.next + data.image, data.code, data.x, data.y, data.width, data.height, this.next ]); } else { - this.next = MotaActionBlocks['drawSelector_1_s'].xmlText([this.next]); + this.next = MotaActionBlocks['drawSelector_1_s'].xmlText([data.code, this.next]); } case "animateImage": // 兼容 animateImage break; @@ -3604,6 +3690,9 @@ MotaActionFunctions.actionParser = new ActionParser(); MotaActionFunctions.workspace = function(){return workspace} MotaActionFunctions.parse = function(obj,type) { + try { + obj = JSON.parse(MotaActionFunctions.replaceToName(JSON.stringify(obj))); + } catch (e) {} MotaActionFunctions.workspace().clear(); xml_text = MotaActionFunctions.actionParser.parse(obj,type||'event'); xml = Blockly.Xml.textToDom(''+xml_text+''); @@ -3612,11 +3701,13 @@ MotaActionFunctions.parse = function(obj,type) { MotaActionFunctions.EvalString_pre = function(EvalString){ if (EvalString.indexOf('__door__')!==-1) throw new Error('请修改开门变量__door__,如door1,door2,door3等依次向后。请勿存在两个门使用相同的开门变量。'); + EvalString = MotaActionFunctions.replaceFromName(EvalString); return EvalString.replace(/([^\\])"/g,'$1\\"').replace(/^"/g,'\\"').replace(/""/g,'"\\"'); } MotaActionFunctions.IdString_pre = function(IdString){ if (IdString.indexOf('__door__')!==-1) throw new Error('请修改开门变量__door__,如door1,door2,door3等依次向后。请勿存在两个门使用相同的开门变量。'); + IdString = MotaActionFunctions.replaceFromName(IdString); if (IdString && !(MotaActionFunctions.pattern.id.test(IdString)) && !(MotaActionFunctions.pattern.idWithoutFlag.test(IdString))) throw new Error('id: '+IdString+'中包含了0-9 a-z A-Z _ - :之外的字符'); return IdString; @@ -3625,7 +3716,7 @@ MotaActionFunctions.IdString_pre = function(IdString){ MotaActionFunctions.PosString_pre = function(PosString){ if (!PosString || /^-?\d+$/.test(PosString)) return PosString; //if (!(MotaActionFunctions.pattern.id.test(PosString)))throw new Error(PosString+'中包含了0-9 a-z A-Z _ 和中文之外的字符,或者是没有以flag: 开头'); - return '"'+PosString+'"'; + return '"'+MotaActionFunctions.replaceFromName(PosString)+'"'; } MotaActionFunctions.StepString_pre = function(StepString){ @@ -3674,4 +3765,113 @@ MotaActionFunctions.pattern.colorRe=/^(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0- MotaActionFunctions.pattern.fontRe=/^(italic )?(bold )?(\d+)px ([a-zA-Z0-9_\u4E00-\u9FCC]+)$/; +MotaActionFunctions.pattern.replaceStatusList = [ + // 保证顺序! + ["hpmax", "生命上限"], + ["hp", "生命"], + ["name", "名称"], + ["lv", "等级"], + ["atk", "攻击"], + ["def", "防御"], + ["mdef", "魔防"], + ["manamax", "魔力上限"], + ["mana", "魔力"], + ["money", "金币"], + ["experience", "经验"], + ["steps", "步数"] +]; + +MotaActionFunctions.pattern.replaceItemList = [ + // 保证顺序! + ["yellowKey", "黄钥匙"], + ["blueKey", "蓝钥匙"], + ["redKey", "红钥匙"], + ["redJewel", "红宝石"], + ["blueJewel", "蓝宝石"], + ["greenJewel", "绿宝石"], + ["yellowJewel", "黄宝石"], + ["redPotion", "红血瓶"], + ["bluePotion", "蓝血瓶"], + ["yellowPotion", "黄血瓶"], + ["greenPotion", "绿血瓶"], + ["sword1", "铁剑"], + ["sword2", "银剑"], + ["sword3", "骑士剑"], + ["sword4", "圣剑"], + ["sword5", "神圣剑"], + ["shield1", "铁盾"], + ["shield2", "银盾"], + ["shield3", "骑士盾"], + ["shield4", "圣盾"], + ["shield5", "神圣盾"], + ["superPotion", "圣水"], + ["moneyPocket", "金钱袋"], + ["book", "怪物手册"], + ["fly", "楼层传送器"], + ["coin", "幸运金币"], + ["snow", "冰冻徽章"], + ["cross", "十字架"], + ["knife", "屠龙匕首"], + ["shoes", "绿鞋"], + ["bigKey", "大黄门钥匙"], + ["greenKey", "绿钥匙"], + ["steelKey", "铁门钥匙"], + ["pickaxe", "破墙镐"], + ["icePickaxe", "破冰镐"], + ["bomb", "炸弹"], + ["centerFly", "中心对称飞行器"], + ["upFly", "上楼器"], + ["downFly", "下楼器"], + ["earthquake", "地震卷轴"], + ["poisonWine", "解毒药水"], + ["weakWine", "解衰药水"], + ["curseWine", "解咒药水"], + ["superWine", "万能药水"], + ["hammer", "圣锤"], + ["lifeWand", "生命魔杖"], + ["jumpShoes", "跳跃靴"], +]; + +MotaActionFunctions.disableReplace = false; + +MotaActionFunctions.replaceToName = function (str) { + if (!str || MotaActionFunctions.disableReplace) return str; + var map = {}, list = []; + MotaActionFunctions.pattern.replaceStatusList.forEach(function (v) { + map[v[0]] = v[1]; list.push(v[0]); + }); + str = str.replace(new RegExp("status:(" + list.join("|") + ")", "g"), function (a, b) { + return map[b] ? ("状态:" + map[b]) : b; + }).replace(/status:/g, "状态:"); + map = {}; list = []; + MotaActionFunctions.pattern.replaceItemList.forEach(function (v) { + map[v[0]] = v[1]; list.push(v[0]); + }); + str = str.replace(new RegExp("item:(" + list.join("|") + ")", "g"), function (a, b) { + return map[b] ? ("物品:" + map[b]) : b; + }).replace(/item:/g, "物品:"); + str = str.replace(/flag:/g, "变量:").replace(/switch:/g, "独立开关:").replace(/global:/g, "全局存储:"); + return str; +} + +MotaActionFunctions.replaceFromName = function (str) { + if (!str || MotaActionFunctions.disableReplace) return str; + var map = {}, list = []; + MotaActionFunctions.pattern.replaceStatusList.forEach(function (v) { + map[v[1]] = v[0]; list.push(v[1]); + }); + str = str.replace(new RegExp("状态[::](" + list.join("|") + ")", "g"), function (a, b) { + return map[b] ? ("status:" + map[b]) : b; + }).replace(/状态[::]/g, "status:"); + map = {}; list = []; + MotaActionFunctions.pattern.replaceItemList.forEach(function (v) { + map[v[1]] = v[0]; list.push(v[1]); + }); + str = str.replace(new RegExp("物品[::](" + list.join("|") + ")", "g"), function (a, b) { + return map[b] ? ("item:" + map[b]) : b; + }).replace(/物品[::]/g, "item:"); + str = str.replace(/变量[::]/g, "flag:").replace(/独立开关[::]/g, "switch:").replace(/全局存储[::]/g, "global:"); + return str; +} + */ \ No newline at end of file diff --git a/_server/README.md b/_server/README.md index e6a12c67..7bd750b1 100644 --- a/_server/README.md +++ b/_server/README.md @@ -1,140 +1,57 @@ # editor -[重构](refactoring.md) +直接使用游戏运行时(之后简称core)的代码来绘制游戏画面, 借助fs.js来实现浏览器编辑文件. 通过表格编辑数据, blockly图块编辑事件, code mirror编辑文本的可视化魔塔编辑器. ->! 以下均是v2.0时的说明, 未及时改动 +![](img_md/view1.png) -本目录下所有文件,以及`../editor.html`和`../启动服务.exe`([源码](http://github.com/ckcz123/mota-js-server/))是地图编辑器的所有组件. +左侧数据区, 中间地图区, 右侧素材区 -`editor.js`,`editor_file.js`和`editor_mode.js`耦合较强,`editor_blockly.js`和`editor_multi.js`和`fs.js`基本可以独立使用. +![](img_md/view2.png) -## 各组件功能 +事件编辑器 -### 总体上 +![](img_md/view3.png) -以`display:none`的形式引入了`index.html`的`dom`,修改了原来的`.gameCanvas #ui #data`等的名字以避免冲突 +脚本编辑器 -通过`main.init('editor')`加载数据 +> 此文件是editor的结构说明, 不是使用文档 -`editor`模式关闭了部分动画 +## 组成 -`core.drawMap`中`editor`模式下不再画图,而是生成画图的函数提供给`editor` +本目录下所有文件,以及`../editor.html`,`../editor-mobile.html`和`../启动服务.exe`,`../server.py`是地图编辑器的所有组件. -`editor`模式下`GlobalAnimate`可以独立的选择是否播放 +### 父目录 ++ editor(-mobile).html + 编辑器的[入口页面](http://127.0.0.1:1055/editor.html) + 以`display:none`的形式引入了core的`index.html`的`dom`,修改了原来的`.gameCanvas #ui #data`等的名字以避免冲突 ++ 启动服务.exe [源码](http://github.com/ckcz123/mota-js-server/) + 为fs.js提供后端支持, 同时集成了一些实用工具 ++ server.py + 非windows平台中为fs.js提供后端支持 -`core.playBgm`和`core.playSound`中非`play`模式不再播放声音 +### core -`core.show`和`core.hide`中非`play`模式不再进行动画而是立刻完成并执行回调 +游戏运行时中部分代码根据`main.mod=='editor'`进行了调整 -`editor`模式不执行`core.resize` ++ 通过`main.init('editor')`加载数据 -### editor.js ++ `editor`模式关闭了部分动画 -``` js -editor.mapInit();//清空地图 -editor.changeFloor('MT2')//切换地图 -editor.util.guid()//产生一个可以作为id的长随机字符串 -``` ++ `core.drawMap`中`editor`模式下不再画图,而是生成画图的函数提+ 供给`editor` -`editor.updateMap`中画未定义快的报错 ++ `editor`模式下`GlobalAnimate`可以独立的选择是否播放 -### editor_file.js ++ `core.playBgm`和`core.playSound`中非`play`模式不再播放声音 -提供了以下函数进行楼层`map`数组相关的操作 -```javascript -editor.file.saveFloorFile -editor.file.saveFloorFileAs -``` ++ `core.show`和`core.hide`中非`play`模式不再进行动画而是立刻+ 完成并执行回调 -编辑模式有关的查询 -```javascript -editor.file.editItem('redJewel',[],function(a){console.log(a)}); -editor.file.editEnemy('redBat',[],function(a){console.log(a)}); -editor.file.editLoc(2,0,[],function(a){console.log(a)}); -editor.file.editFloor([],function(a){console.log(a)}); -editor.file.editTower([],function(a){console.log(a)}); -editor.file.editFunctions([],function(a){console.log(a)}); -``` ++ `editor`模式不执行`core.resize` -编辑模式有关的编辑 -```javascript -editor.info={images: "terrains", y: 9}; -editor.file.changeIdAndIdnum('yellowWall2',16,editor.info,function(a){console.log(a)}); -editor.file.editItem('book',[["change","['items']['name']","怪物手册的新名字"]],function(a){console.log(a)}); -editor.file.editEnemy('redBat',[['change',"['atk']",20]],function(a){console.log(a)}); -editor.file.editLoc(2,6,[["change","['afterBattle']",null]],function(a){console.log(a)}); -editor.file.editFloor([["change","['title']",'样板 33 层']],function(a){console.log(a)}); -editor.file.editTower([["change","['values']['lavaDamage']",200]],function(a){console.log(a)}); -editor.file.editFunctions(["change","['events']['afterChangeLight']","function(x,y){console.log(x,y)}"],function(a){console.log(a)}); -``` - -### editor_mode.js -生成表格并绑定事件的函数 -```javascript -editor.mode.loc(); -editor.mode.enemyitem(); -editor.mode.floor(); -editor.mode.tower(); -editor.mode.functions(); -``` - -切换模式 -```javascript -editor.mode.onmode('');//清空 -editor.mode.onmode('save');//保存 -editor.mode.onmode('nextChange');//下次onmode时前端进行切换 - -editor.mode.onmode('loc'); -editor.mode.onmode('enemyitem'); -editor.mode.onmode('floor'); -editor.mode.onmode('tower'); -editor.mode.onmode('functions'); -editor.mode.onmode('map'); -editor.mode.onmode('appendpic'); -``` -在`onmode('save')`时,改动才会保存到文件,涉及到图片的改动需要刷新页面使得`editor`能看到 - -表格的`onchange`的实现中,获得当前模式的方式.不注意的话,修改`index.html`中页面的结构,会被坑 -```javascript -var node = thisTr.parentNode; -while (!editor_mode._ids.hasOwnProperty(node.getAttribute('id'))) { - node = node.parentNode; -} -editor_mode.onmode(editor_mode._ids[node.getAttribute('id')]); -``` - -`editor.mode.listen`中提供了追加素材的支持. - - -### editor_blockly.js - -把选定`id_`的事件用blockly编辑 -``` js -editor_blockly.import(id_,{type:'event'}); -``` - -把文本区域的代码转换成图块 -``` js -editor_blockly.parse(); -``` - -### editor_multi.js - -用[CodeMirror](https://github.com/codemirror/CodeMirror) 实现有高亮的多行文本编辑 - -编辑选定`id_`的文本域 -``` js -editor_multi.import(id_,{lint:true}) -``` - -编辑blockly方块的特定域 -``` js -editor_multi.multiLineEdit(value,b,f,{lint:true},callback) -``` ### fs.js -模仿node的fs模块提供如下api,与`启动服务.exe`配合为js提供文件读写功能 +依照[issue#31](https://github.com/ckcz123/mota-js/issues/13)的约定, 模仿node的fs模块提供如下api,与`启动服务.exe`,`server.py`配合为js提供文件读写功能, 是编辑器成立的前提 + ``` js fs.readFile('file.in','utf-8',callback) //读文本文件 @@ -162,3 +79,195 @@ fs.readdir(path, callback) //所有参数不允许缺省 ``` +### editor_multi.js + +用[CodeMirror](https://github.com/codemirror/CodeMirror) 实现有高亮的多行文本编辑 + +编辑选定`id_`的文本域 +``` js +editor_multi.import(id_,{lint:true}) +``` + +编辑blockly方块的特定域 +``` js +editor_multi.multiLineEdit(value,b,f,{lint:true},callback) +``` + +配置表格 +``` js +editor_multi.editCommentJs(mod) +``` + +### MotaAction.g4 + +通过[antlr-blockly](https://github.com/zhaouv/antlr-blockly)的语法定义core中各事件对应的方块. + +借助google的[blockly](https://github.com/google/blockly)来实现事件的可视化编辑. + +入口方块以`_m`结尾 + +一般语句写在`action`中, 以`_s`结尾 + +### editor_blockly.js + +把选定`id_`的事件用blockly编辑 +``` js +editor_blockly.import(id_,{type:'event'}); +``` + +把文本区域的代码转换成图块 +``` js +editor_blockly.parse(); +``` + +`initscript中`的`toolboxObj`定义了侧边栏中显示的图块 + +自定义`Blockly.FieldColour.prototype.createWidget_`修改了颜色选择器的行为 + +自定义`Blockly.FieldTextInput.prototype.showInlineEditor_`添加了自动补全 + + +### editor_mode.js + +用于切换数据区 + +加载数据 +```javascript +editor.mode.loc(); +editor.mode.enemyitem(); +editor.mode.floor(); +editor.mode.tower(); +editor.mode.functions(); +``` + +切换模式 +```javascript +editor.mode.onmode('');//清空 +editor.mode.onmode('save');//保存 +editor.mode.onmode('nextChange');//下次onmode时前端进行切换 + +editor.mode.onmode('loc'); +editor.mode.onmode('enemyitem'); +editor.mode.onmode('floor'); +editor.mode.onmode('tower'); +editor.mode.onmode('functions'); +editor.mode.onmode('map'); +editor.mode.onmode('appendpic'); +``` +在`onmode('save')`时,改动才会保存到文件,涉及到图片的改动需要刷新页面使得`editor`能看到 + +数据区一些通用的函数也定义在这里 + +### editor_table.js + +处理表格的生成, 及其响应的事件 + +其接受来自../project/\*.js的数据`obj`和来自table/\*.comment.js的注释`commentObj` + +commentObj的结构如示例 +``` js +{ + "_type": "object", + "_data": { + "events": { + "_type": "object", + "_data": { + "resetGame": { + "_leaf": true, + "_type": "textarea", + "_lint": true, + "_data": "重置整个游戏" + }, + "setInitData": { + "_leaf": true, + "_type": "textarea", + "_lint": true, + "_data": "设置初始属性" + }, +``` +一层正常数据, 一层`_`开头的结构说明, 忽略`_`层的话与obj同结构 + +通过 +``` js +editor.table.objToTable(obj, commentObj) +editor.table.objToTr +editor.table.objToTd +``` +遍历这两个对象来生成表格, 叶节点根据`_type`渲染成对应的dom + +表格的值变化`onchange`, 双击`dblclickfunc`, 删除`deletefunc`, 添加`addfunc`也定义在此文件 + +### editor_mappanel.js + +与地图区相关的功能 ++ 画地图 线/矩形/tileset ++ 通过地图选中事件或素材 ++ 右键菜单 ++ 切换楼层 ++ 大地图移动可视窗口 + +### editor_materialpanel.js + +与素材区相关的功能 ++ 选中 ++ 展开/折叠 + +### editor_datapanel.js + +与数据区相关的功能 (且与表格无关的功能) ++ 地图编辑 + - 创建新地图 + - 批量创建 ++ 地图选点 ++ 图块属性 + - 注册素材 + - 修改id ++ 楼层属性 + - 修改楼层id ++ 全塔属性 ++ 脚本编辑 ++ 追加素材 + - 选择导入的区域 + - 导入图片 + - 改色相 + - 选中图片中的格子 + - 确认追加 ++ 公共事件 ++ 插件编写 + +### editor_ui.js + +ui事件中没有具体到前三个区中的函数 ++ 响应点击 ++ 快捷键 ++ 显示帮助 ++ UI预览 & 地图选点相关 + +### editor_util.js + +一些通用的函数 ++ 生成id ++ HTML转义 ++ 像素处理 ++ base64的encode/decode ++ 检查值是否为空 + +### editor_listen.js + +界面与功能的绑定 + +### editor_file.js + +包装fs.js, 把数据读写到对应的文件 + +### editor_game.js + +游戏数据的处理 + +此部分的重构未完成, 实际上是由editor_file.js和editor_file_unsorted.js来做的 + +### editor.js + +初始化加整合各模块 + +现状是还放了一些游戏数据有关的函数未挪到editor_game, 以及部分和入口页面生成有关的函数 \ No newline at end of file diff --git a/_server/css/editor.css b/_server/css/editor.css index c12e3f07..92172a43 100644 --- a/_server/css/editor.css +++ b/_server/css/editor.css @@ -285,8 +285,10 @@ body { #iconExpandBtn { position: absolute; - left: 10px; + left: 20px; bottom: 30px; + font-size: 15px; + padding: 6px; display: none; } diff --git a/_server/css/editor_mobile.css b/_server/css/editor_mobile.css index c37142e1..40e28ff1 100644 --- a/_server/css/editor_mobile.css +++ b/_server/css/editor_mobile.css @@ -270,8 +270,10 @@ body { #iconExpandBtn { position: absolute; - left: 10px; + left: 20px; bottom: 30px; + font-size: 15px; + padding: 6px; display: none; } diff --git a/_server/css/editor_mode.css b/_server/css/editor_mode.css index a1859f65..d521a617 100644 --- a/_server/css/editor_mode.css +++ b/_server/css/editor_mode.css @@ -121,6 +121,7 @@ display: block; width: 100%; overflow: auto; + word-break: break-all; } .etable table th { @@ -157,14 +158,19 @@ } .etable tr > :nth-child(3) { - width: 60% + width: 35%; +} + +.etable tr > :nth-child(4) { + width: 25%; + padding: 0; } .etable table { overflow: visible; } -.etable tr:not(:first-child) > :last-child:hover { +.etable tr:not(:first-child) > :nth-child(3):hover { border: 1px solid rgb(87, 198, 232); box-shadow: 0px 0px 3px rgb(87, 198, 232); } @@ -175,14 +181,17 @@ box-shadow: 0px 0px 3px rgb(87, 232, 198); } -.etable tr:not(:first-child) > :last-child { +.etable tr:not(:first-child) > :nth-child(3) { margin: 0; padding: 0; height: 100%; - width: 100%; position: relative; } +.etable tr > :nth-child(4) { + text-align: center; +} + div.etableInputDiv { position: absolute; padding: 5px 0 0 5px; diff --git a/_server/css/editor_mode_mobile.css b/_server/css/editor_mode_mobile.css index 3098df27..bb680213 100644 --- a/_server/css/editor_mode_mobile.css +++ b/_server/css/editor_mode_mobile.css @@ -135,6 +135,7 @@ display: block; width: 100%; overflow: auto; + word-break: break-all; } .etable table th { @@ -171,14 +172,19 @@ } .etable tr > :nth-child(3) { - width: 60% + width: 30%; +} + +.etable tr > :nth-child(4) { + width: 30%; + text-align: center; } .etable table { overflow: visible; } -.etable tr:not(:first-child) > :last-child:hover { +.etable tr:not(:first-child) > :nth-child(3):hover { border: 1px solid rgb(87, 198, 232); box-shadow: 0px 0px 3px rgb(87, 198, 232); } @@ -189,11 +195,10 @@ box-shadow: 0px 0px 3px rgb(87, 232, 198); } -.etable tr:not(:first-child) > :last-child { +.etable tr:not(:first-child) > :nth-child(3) { margin: 0; padding: 0; height: 100%; - width: 100%; position: relative; } diff --git a/_server/editor.js b/_server/editor.js index cb7490a3..54b24e35 100644 --- a/_server/editor.js +++ b/_server/editor.js @@ -4,6 +4,88 @@ function editor() { this.layerMod = "map";//["fgmap","map","bgmap"] this.isMobile = false; + this.dom={ + body:document.body, + eui:document.getElementById('eui'), + euiCtx:document.getElementById('eui').getContext('2d'), + mid:document.getElementById('mid'), + mapEdit:document.getElementById('mapEdit'), + selectFloor:document.getElementById('selectFloor'), + iconExpandBtn :document.getElementById('iconExpandBtn'), + dataSelection : document.getElementById('dataSelection'), + iconLib:document.getElementById('iconLib'), + midMenu:document.getElementById('midMenu'), + extraEvent: document.getElementById('extraEvent'), + chooseThis : document.getElementById('chooseThis'), + chooseInRight : document.getElementById('chooseInRight'), + copyLoc : document.getElementById('copyLoc'), + moveLoc : document.getElementById('moveLoc'), + clearEvent : document.getElementById('clearEvent'), + clearLoc : document.getElementById('clearLoc'), + brushMod:document.getElementById('brushMod'), + brushMod2:document.getElementById('brushMod2'), + brushMod3:document.getElementById('brushMod3'), + bgc : document.getElementById('bg'), + fgc : document.getElementById('fg'), + evc : document.getElementById('event'), + ev2c : document.getElementById('event2'), + layerMod:document.getElementById('layerMod'), + layerMod2:document.getElementById('layerMod2'), + layerMod3:document.getElementById('layerMod3'), + viewportButtons:document.getElementById('viewportButtons'), + appendPicCanvas : document.getElementById('appendPicCanvas'), + bg : document.getElementById('appendPicCanvas').children[0], + source : document.getElementById('appendPicCanvas').children[1], + picClick : document.getElementById('appendPicCanvas').children[2], + sprite : document.getElementById('appendPicCanvas').children[3], + sourceCtx:document.getElementById('appendPicCanvas').children[1].getContext('2d'), + spriteCtx:document.getElementById('appendPicCanvas').children[3].getContext('2d'), + appendPicSelection : document.getElementById('appendPicSelection'), + selectAppend : document.getElementById('selectAppend'), + selectFileBtn :document.getElementById('selectFileBtn'), + changeFloorId :document.getElementById('changeFloorId'), + left1 : document.getElementById('left1'), + editModeSelect :document.getElementById('editModeSelect'), + }; + + this.uivalues={ + // 绘制区拖动有关 + holdingPath : 0, + stepPostfix : null,//用于存放寻路检测的第一个点之后的后续移动 + mouseOutCheck : 2, + startPos:null, + endPos:null, + // 撤销/恢复 + currDrawData : { + pos: [], + info: {} + }, + reDo : null, + preMapData : null, + // + shortcut:{}, + copyedInfo : null, + // 折叠素材 + scrollBarHeight :0, + folded:false, + foldPerCol: 50, + // 画图区菜单 + lastRightButtonPos:[{x:0,y:0},{x:0,y:0}], + lastCopyedInfo : [null, null], + // + ratio : 1, + // blockly转义 + disableBlocklyReplace: false, + + // 绑定机关门事件相关 + bindSpecialDoor: { + loc: null, + n: -1, + enemys: [] + } + + }; + window.onerror = function (msg, url, lineNo, columnNo, error) { var string = msg.toLowerCase(); var substring = "script error"; @@ -30,6 +112,8 @@ function editor() { }; } +editor.prototype.uifunctions={}; + /* editor.loc editor.pos @@ -52,7 +136,11 @@ editor.prototype.init = function (callback) { editor_game_wrapper(editor, main, core); editor_file_wrapper(editor); editor_table_wrapper(editor); - editor_unsorted_1_wrapper(editor); + editor_ui_wrapper(editor); + editor_mappanel_wrapper(editor); + editor_datapanel_wrapper(editor); + editor_materialpanel_wrapper(editor); + editor_listen_wrapper(editor); editor.printe=printe; afterMainInit(); }); @@ -65,7 +153,6 @@ editor.prototype.init = function (callback) { editor_file = editor_file(editor, function () { editor.file = editor_file; editor_mode = editor_mode(editor); - editor_unsorted_2_wrapper(editor_mode); editor.mode = editor_mode; core.resetGame(core.firstData.hero, null, core.firstData.floorId, core.clone(core.initStatus.maps)); core.changeFloor(core.status.floorId, null, core.firstData.hero.loc, null, function () { @@ -103,6 +190,11 @@ editor.prototype.init = function (callback) { for (var floorId in editor.main.floors) { editor.addUsedFlags(JSON.stringify(editor.main.floors[floorId])); } + if (events_c12a15a8_c380_4b28_8144_256cba95f760.commonEvent) { + for (var name in events_c12a15a8_c380_4b28_8144_256cba95f760.commonEvent) { + editor.addUsedFlags(JSON.stringify(events_c12a15a8_c380_4b28_8144_256cba95f760.commonEvent[name])); + } + } if (editor.useCompress == null) editor.useCompress = useCompress; if (Boolean(callback)) callback(); @@ -148,7 +240,8 @@ editor.prototype.changeFloor = function (floorId, callback) { }); editor.currentFloorData[name]=mapArray; } - editor.preMapData = null; + editor.uivalues.preMapData = null; + editor.uifunctions._extraEvent_bindSpecialDoor_doAction(true); core.changeFloor(floorId, null, {"x": 0, "y": 0, "direction": "up"}, null, function () { editor.game.fetchMapFromCore(); editor.updateMap(); @@ -169,26 +262,48 @@ editor.prototype.drawEventBlock = function () { var fg=document.getElementById('efg').getContext('2d'); fg.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__); + var firstData = editor.game.getFirstData(); for (var i=0;i= 0) { + fg.textAlign = 'right'; + editor.game.doCoreFunc("fillBoldText", fg, index + 1, + 32 * i + 28, 32 * j + 15, '#FF7F00', '14px Verdana'); + } } } } @@ -266,6 +381,7 @@ editor.prototype.updateMap = function () { editor.prototype.setViewport=function (x, y) { core.bigmap.offsetX = core.clamp(x, 0, 32*core.bigmap.width-core.__PIXELS__); core.bigmap.offsetY = core.clamp(y, 0, 32*core.bigmap.height-core.__PIXELS__); + editor.viewportLoc = editor.viewportLoc || {}; editor.viewportLoc[editor.currentFloorId] = [core.bigmap.offsetX, core.bigmap.offsetY]; core.control.updateViewport(); editor.buildMark(); @@ -284,9 +400,9 @@ editor.prototype.drawInitData = function (icons) { var maxHeight = 700; var sumWidth = 0; editor.widthsX = {}; - editor.folded = core.getLocalStorage('folded', false); - // editor.folded = true; - editor.foldPerCol = 50; + editor.uivalues.folded = core.getLocalStorage('folded', false); + // editor.uivalues.folded = true; + editor.uivalues.foldPerCol = 50; // var imgNames = Object.keys(images); //还是固定顺序吧; var imgNames = ["terrains", "animates", "enemys", "enemy48", "items", "npcs", "npc48", "autotile"]; @@ -297,17 +413,17 @@ editor.prototype.drawInitData = function (icons) { for (var im in autotiles) { tempy += autotiles[im].height; } - var tempx = editor.folded ? 32 : 3 * 32; + var tempx = editor.uivalues.folded ? 32 : 3 * 32; editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + tempx) / 32, tempy]; sumWidth += tempx; maxHeight = Math.max(maxHeight, tempy); continue; } var width = images[img].width, height = images[img].height, mh = height; - if (editor.folded) { + if (editor.uivalues.folded) { var per_height = (img == 'enemy48' || img == 'npc48' ? 48 : 32); - width = Math.ceil(height / per_height / editor.foldPerCol) * 32; - if (width > 32) mh = per_height * editor.foldPerCol; + width = Math.ceil(height / per_height / editor.uivalues.foldPerCol) * 32; + if (width > 32) mh = per_height * editor.uivalues.foldPerCol; } editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + width) / 32, height]; sumWidth += width; @@ -353,9 +469,9 @@ editor.prototype.drawInitData = function (icons) { editor.updateMap(); } })(editor.airwallImg,nowx); - if (editor.folded) { + if (editor.uivalues.folded) { // --- 单列 & 折行 - var subimgs = core.splitImage(images[img], 32, editor.foldPerCol * 32); + var subimgs = core.splitImage(images[img], 32, editor.uivalues.foldPerCol * 32); var frames = images[img].width / 32; for (var i = 0; i < subimgs.length; i+=frames) { drawImage(subimgs[i], nowx, i==0?2*32:0); @@ -370,7 +486,7 @@ editor.prototype.drawInitData = function (icons) { } if (img == 'autotile') { var autotiles = images[img]; - var tempx = editor.folded ? 32 : 96; + var tempx = editor.uivalues.folded ? 32 : 96; for (var im in autotiles) { var subimgs = core.splitImage(autotiles[im], tempx, autotiles[im].height); drawImage(subimgs[0], nowx, nowy); @@ -379,10 +495,10 @@ editor.prototype.drawInitData = function (icons) { nowx += tempx; continue; } - if (editor.folded) { + if (editor.uivalues.folded) { // --- 单列 & 折行 var per_height = img.endsWith('48') ? 48 : 32; - var subimgs = core.splitImage(images[img], 32, editor.foldPerCol * per_height); + var subimgs = core.splitImage(images[img], 32, editor.uivalues.foldPerCol * per_height); var frames = images[img].width / 32; for (var i = 0; i < subimgs.length; i+=frames) { drawImage(subimgs[i], nowx, 0); @@ -471,16 +587,15 @@ editor.prototype.setSelectBoxFromInfo=function(thisevent){ pos.y=thisevent.y; if(thisevent.x)pos.x+=thisevent.x; ysize = thisevent.images.endsWith('48') ? 48 : 32; - if (editor.folded && core.tilesets.indexOf(thisevent.images)==-1) { - pos.x += Math.floor(pos.y / editor.foldPerCol); - pos.y %= editor.foldPerCol; + if (editor.uivalues.folded && core.tilesets.indexOf(thisevent.images)==-1) { + pos.x += Math.floor(pos.y / editor.uivalues.foldPerCol); + pos.y %= editor.uivalues.foldPerCol; } if(pos.x == 0) pos.y+=2; } - var dataSelection = document.getElementById('dataSelection'); - dataSelection.style.left = pos.x * 32 + 'px'; - dataSelection.style.top = pos.y * ysize + 'px'; - dataSelection.style.height = ysize - 6 + 'px'; + editor.dom.dataSelection.style.left = pos.x * 32 + 'px'; + editor.dom.dataSelection.style.top = pos.y * ysize + 'px'; + editor.dom.dataSelection.style.height = ysize - 6 + 'px'; setTimeout(function(){selectBox.isSelected(true);}); editor.info = JSON.parse(JSON.stringify(thisevent)); tip.infos(JSON.parse(JSON.stringify(thisevent))); @@ -489,137 +604,21 @@ editor.prototype.setSelectBoxFromInfo=function(thisevent){ editor_mode.onmode('enemyitem'); } -editor.prototype.listen = function () { - // 移动至 editor_unsorted_1.js -}//绑定事件 - -editor.prototype.mobile_listen=function(){ - // 移动至 editor_unsorted_1.js -} - -editor.prototype.copyFromPos = function (pos) { - var fields = Object.keys(editor.file.comment._data.floors._data.loc._data); - pos = pos || editor.pos; - var map = core.clone(editor.map[pos.y][pos.x]); - var events = {}; - fields.forEach(function(v){ - events[v] = core.clone(editor.currentFloorData[v][pos.x+','+pos.y]); - }) - return {map: map, events: events}; -} - -editor.prototype.pasteToPos = function (info, pos) { - if (info == null) return; - var fields = Object.keys(editor.file.comment._data.floors._data.loc._data); - pos = pos || editor.pos; - editor.map[pos.y][pos.x] = core.clone(info.map); - fields.forEach(function(v){ - if (info.events[v] == null) delete editor.currentFloorData[v][pos.x+","+pos.y]; - else editor.currentFloorData[v][pos.x+","+pos.y] = core.clone(info.events[v]); - }); -} - -editor.prototype.movePos = function (startPos, endPos, callback) { - if (!startPos || !endPos) return; - if (startPos.x == endPos.x && startPos.y == endPos.y) return; - var copyed = editor.copyFromPos(startPos); - editor.pasteToPos({map:0, events: {}}, startPos); - editor.pasteToPos(copyed, endPos); - editor.updateMap(); - editor.file.saveFloorFile(function (err) { - if (err) { - printe(err); - throw(err) - } - ;printf('移动事件成功'); - editor.drawPosSelection(); - if (callback) callback(); - }); -} - -editor.prototype.exchangePos = function (startPos, endPos, callback) { - if (!startPos || !endPos) return; - if (startPos.x == endPos.x && startPos.y == endPos.y) return; - var startInfo = editor.copyFromPos(startPos); - var endInfo = editor.copyFromPos(endPos); - editor.pasteToPos(startInfo, endPos); - editor.pasteToPos(endInfo, startPos); - editor.updateMap(); - editor.file.saveFloorFile(function (err) { - if (err) { - printe(err); - throw(err) - } - ;printf('交换事件成功'); - editor.drawPosSelection(); - if (callback) callback(); - }); -} - -editor.prototype.moveBgFg = function (startPos, endPos, name, callback) { - if (!startPos || !endPos || ["bgmap","fgmap"].indexOf(name)<0) return; - if (startPos.x == endPos.x && startPos.y == endPos.y) return; - editor[name][endPos.y][endPos.x] = editor[name][startPos.y][startPos.x]; - editor[name][startPos.y][startPos.x] = 0; - editor.updateMap(); - editor.file.saveFloorFile(function (err) { - if (err) { - printe(err); - throw(err) - } - ;printf('移动图块成功'); - editor.drawPosSelection(); - if (callback) callback(); - }); -} - -editor.prototype.exchangeBgFg = function (startPos, endPos, name, callback) { - if (!startPos || !endPos || ["bgmap","fgmap"].indexOf(name)<0) return; - if (startPos.x == endPos.x && startPos.y == endPos.y) return; - var value = editor[name][endPos.y][endPos.x]; - editor[name][endPos.y][endPos.x] = editor[name][startPos.y][startPos.x]; - editor[name][startPos.y][startPos.x] = value; - editor.updateMap(); - editor.file.saveFloorFile(function (err) { - if (err) { - printe(err); - throw(err) - } - ;printf('交换图块成功'); - editor.drawPosSelection(); - if (callback) callback(); - }); - -} - -editor.prototype.clearPos = function (clearPos, pos, callback) { - var fields = Object.keys(editor.file.comment._data.floors._data.loc._data); - pos = pos || editor.pos; - editor.hideMidMenu(); - editor.preMapData = null; - editor.info = 0; - editor_mode.onmode(''); - if (clearPos) - editor.map[pos.y][pos.x]=editor.info; - editor.updateMap(); - fields.forEach(function(v){ - delete editor.currentFloorData[v][pos.x+','+pos.y]; - }) - editor.file.saveFloorFile(function (err) { - if (err) { - printe(err); - throw(err) - } - ;printf(clearPos?'清空该点和事件成功':'只清空该点事件成功'); - editor.drawPosSelection(); - if (callback) callback(); - }); -} - editor.prototype.addUsedFlags = function (s) { s.replace(/flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)/g, function (s0, s1) { editor.used_flags[s1] = true; return s0; }); } +editor.prototype.listen = function () { + // 移动至 editor_listen.js +}//绑定事件 + +editor.prototype.mobile_listen=function(){ + // 移动至 editor_listen.js +} + + + + editor = new editor(); \ No newline at end of file diff --git a/_server/editor_blockly.js b/_server/editor_blockly.js index 82d3b9f8..ef318e6a 100644 --- a/_server/editor_blockly.js +++ b/_server/editor_blockly.js @@ -26,6 +26,16 @@ editor_blockly = function () { "本事件触发一次后会消失", {"type": "hide", "time": 500}, ],'event'), + MotaActionFunctions.actionParser.parse({ + "condition": "flag:__door__==2", + "currentFloor": true, + "priority": 0, + "delayExecute": false, + "multiExecute": false, + "data": [ + {"type": "openDoor", "loc": [10,5]} + ], + },'autoEvent'), MotaActionBlocks['changeFloor_m'].xmlText(), MotaActionFunctions.actionParser.parse([{ "id": "moneyShop1", @@ -38,8 +48,13 @@ editor_blockly = function () { "choices": [ {"text": "生命+800", "effect": "status:hp+=800"}, {"text": "攻击+4", "effect": "status:atk+=4"}, - {"text": "防御+4", "effect": "status:def+=4"}, - {"text": "魔防+10", "effect": "status:mdef+=10"} + ] + },{ + "id": "itemShop", + "item": true, + "textInList": "道具商店", + "choices": [ + {"id": "yellowKey", "number": 10, "money": 10} ] },{ "id": "keyShop1", @@ -84,11 +99,11 @@ editor_blockly = function () { ]), ], '数据相关':[ - MotaActionBlocks['setValue_s'].xmlText([ - MotaActionBlocks['idString_1_e'].xmlText(['status','hp']) - ]), MotaActionBlocks['addValue_s'].xmlText([ - MotaActionBlocks['idString_1_e'].xmlText(['status','hp']) + MotaActionBlocks['idString_1_e'].xmlText(['status','生命']) + ]), + MotaActionBlocks['setValue_s'].xmlText([ + MotaActionBlocks['idString_1_e'].xmlText(['status','生命']) ]), MotaActionBlocks['setFloor_s'].xmlText(), MotaActionBlocks['setGlobalAttribute_s'].xmlText(), @@ -127,8 +142,8 @@ editor_blockly = function () { MotaActionBlocks['hideFloorImg_s'].xmlText(), ], '事件控制':[ - MotaActionBlocks['if_s'].xmlText(), MotaActionBlocks['if_1_s'].xmlText(), + MotaActionBlocks['if_s'].xmlText(), MotaActionFunctions.actionParser.parseList({"type": "switch", "condition": "判别值", "caseList": [ {"action": [{"type": "comment", "text": "当判别值是值的场合执行此事件"}]}, {"action": [], "nobreak": true}, @@ -201,11 +216,11 @@ editor_blockly = function () { MotaActionBlocks['unknown_s'].xmlText(), ], '值块':[ - MotaActionBlocks['setValue_s'].xmlText([ - MotaActionBlocks['idString_1_e'].xmlText(['status','hp']) - ]), MotaActionBlocks['addValue_s'].xmlText([ - MotaActionBlocks['idString_1_e'].xmlText(['status','hp']) + MotaActionBlocks['idString_1_e'].xmlText(['status','生命']) + ]), + MotaActionBlocks['setValue_s'].xmlText([ + MotaActionBlocks['idString_1_e'].xmlText(['status','生命']) ]), MotaActionBlocks['expression_arithmetic_0'].xmlText(), MotaActionBlocks['evFlag_e'].xmlText(), @@ -467,6 +482,17 @@ function omitedcheckUpdateFunction(event) { `; /////////////////initscript end ///////////////////////////// + editor.uivalues.disableBlocklyReplace = core.getLocalStorage("disableBlocklyReplace", false); + var replaceCheckbox = document.getElementById('blocklyReplace'); + replaceCheckbox.checked = !editor.uivalues.disableBlocklyReplace; + + editor_blockly.triggerReplace = function () { + editor.uivalues.disableBlocklyReplace = !replaceCheckbox.checked; + core.setLocalStorage("disableBlocklyReplace", !replaceCheckbox.checked); + if (MotaActionFunctions) MotaActionFunctions.disableReplace = !replaceCheckbox.checked; + alert("已" + (replaceCheckbox.checked ? "开启" : "关闭") + "中文变量名替换!\n关闭并重开事件编辑器以生效。"); + } + var input_ = ''; editor_blockly.runOne = function () { //var printf = console.log; @@ -496,6 +522,7 @@ function omitedcheckUpdateFunction(event) { } input_ = xhr.responseText; editor_blockly.runOne(); + MotaActionFunctions.disableReplace = editor.uivalues.disableBlocklyReplace; } xhr.open('GET', '_server/MotaAction.g4', true); xhr.send(null); @@ -612,9 +639,45 @@ function omitedcheckUpdateFunction(event) { var code = Blockly.JavaScript.workspaceToCode(editor_blockly.workspace); code = code.replace(/\\(i|c|d|e)/g, '\\\\$1'); eval('var obj=' + code); + if (this.checkAsync(obj) && confirm("警告!存在不等待执行完毕的事件但却没有用【等待所有异步事件处理完毕】来等待" + + "它们执行完毕,这样可能会导致录像检测系统出问题。\n你要返回修改么?")) return; setvalue(JSON.stringify(obj)); } + // 检查"不等待处理完毕" + editor_blockly.checkAsync = function (obj) { + if (!(obj instanceof Array)) return false; + var hasAsync = false; + for (var i = 0; i < obj.length; ++i) { + var one = obj[i]; + if (one.type == 'if' && (this.checkAsync(one['true']) || this.checkAsync(one['false']))) + return true; + if ((one.type == 'while' || one.type == 'dowhile') && this.checkAsync(one.data)) + return true; + if (one.type == 'if' && (this.checkAsync(one.yes) || this.checkAsync(one.no))) + return true; + if (one.type == 'choices') { + var list = one.choices; + if (list instanceof Array) { + for (var j = 0; j < list.length; j++) { + if (this.checkAsync(list[j].action)) return true; + } + } + } + if (one.type == 'switch') { + var list = one.caseList; + if (list instanceof Array) { + for (var j = 0; j < list.length; j++) { + if (this.checkAsync(list[j].action)) return true; + } + } + } + if (one.async && one.type != 'animate') hasAsync = true; + if (one.type == 'waitAsync') hasAsync = false; + } + return hasAsync; + } + var previewBlock = function (b) { var types = [ "previewUI_s", "clearMap_s", "clearMap_1_s", "setAttribute_s", "fillText_s", @@ -629,8 +692,8 @@ function omitedcheckUpdateFunction(event) { // console.log(obj); if (obj.length > 0 && b.type.startsWith(obj[0].type)) { if (b.type == 'previewUI_s') - uievent.previewUI(obj[0].action); - else uievent.previewUI([obj[0]]); + editor.uievent.previewUI(obj[0].action); + else editor.uievent.previewUI([obj[0]]); } } catch (e) {main.log(e);} return true; @@ -769,7 +832,7 @@ function omitedcheckUpdateFunction(event) { "jump_s": ["PosString_2", "PosString_3"], // 跳跃暂时只考虑终点 "showBgFgMap_s": ["EvalString_0", "EvalString_1", "IdString_0"], "hideBgFgMap_s": ["EvalString_0", "EvalString_1", "IdString_0"], - "setBgFgBlock_s": ["PosString_0", "PosString_1", "IdString_0"], + "setBgFgBlock_s": ["EvalString_1", "EvalString_2", "IdString_0"], "showFloorImg_s": ["EvalString_0", "EvalString_1", "IdString_0"], "hideFloorImg_s": ["EvalString_0", "EvalString_1", "IdString_0"], "trigger_s": ["PosString_0", "PosString_1"], @@ -792,7 +855,7 @@ function omitedcheckUpdateFunction(event) { if (!isNaN(yv)) y = yv; if (arr[2] != null) floorId = block.getFieldValue(arr[2]) || floorId; } - uievent.selectPoint(floorId, x, y, arr && arr[2] == null, function (fv, xv, yv) { + editor.uievent.selectPoint(floorId, x, y, arr && arr[2] == null, function (fv, xv, yv) { if (!arr) return; if (arr[2] != null) { if (fv != editor.currentFloorId) block.setFieldValue(fv, arr[2]); @@ -815,22 +878,35 @@ function omitedcheckUpdateFunction(event) { editor_blockly.getAutoCompletions = function (content) { // --- content为当前框中输入内容;将返回一个列表,为后续所有可补全内容 - // 检查 flag:xxx,item:xxx和flag:xxx - var index = content.lastIndexOf(":"); + // 检查 status:xxx,item:xxx和flag:xxx + var index = Math.max(content.lastIndexOf(":"), content.lastIndexOf(":")); if (index >= 0) { + var ch = content.charAt(index); var before = content.substring(0, index), token = content.substring(index+1); if (/^[a-zA-Z0-9_\u4E00-\u9FCC]*$/.test(token)) { - if (before.endsWith("status")) { - return Object.keys(core.status.hero).filter(function (one) { + if (before.endsWith("状态") || (ch == ':' && before.endsWith("status"))) { + var list = Object.keys(core.status.hero); + if (before.endsWith("状态") && MotaActionFunctions) { + list = MotaActionFunctions.pattern.replaceStatusList.map(function (v) { + return v[1]; + }).concat(list); + } + return list.filter(function (one) { return one != token && one.startsWith(token); }).sort(); } - else if (before.endsWith("item")) { - return Object.keys(core.material.items).filter(function (one) { + else if (before.endsWith("物品") || (ch == ':' && before.endsWith("item"))) { + var list = Object.keys(core.material.items); + if (before.endsWith("物品") && MotaActionFunctions) { + list = MotaActionFunctions.pattern.replaceItemList.map(function (v) { + return v[1]; + }).concat(list); + } + return list.filter(function (one) { return one != token && one.startsWith(token); }).sort(); } - else if (before.endsWith("flag")) { + else if (before.endsWith("变量") || (ch == ':' && before.endsWith("flag"))) { return Object.keys(editor.used_flags || {}).filter(function (one) { return one != token && one.startsWith(token); }).sort(); @@ -963,7 +1039,7 @@ Blockly.FieldTextInput.prototype.showInlineEditor_ = function(quietInput) { // --- awesomplete var awesomplete = new Awesomplete(htmlInput, { - minChars: 4, + minChars: 2, maxItems: 12, autoFirst: true, replace: function (text) { diff --git a/_server/editor_unsorted_2.js b/_server/editor_datapanel.js similarity index 51% rename from _server/editor_unsorted_2.js rename to _server/editor_datapanel.js index 042b617b..5e1baa46 100644 --- a/_server/editor_unsorted_2.js +++ b/_server/editor_datapanel.js @@ -1,6 +1,158 @@ -editor_unsorted_2_wrapper=function(editor_mode){ +editor_datapanel_wrapper = function (editor) { - editor_mode.constructor.prototype.listen=function (callback) { + // 此文件内的内容仅做了分类, 未仔细整理函数 + + /////////////////////////////////////////////////////////////////////// + //////////////////// 地图编辑 ////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + + editor.uifunctions.newMap_func = function () { + + var newMap = document.getElementById('newMap'); + var newFileName = document.getElementById('newFileName'); + newMap.onclick = function () { + if (!newFileName.value) return; + if (core.floorIds.indexOf(newFileName.value) >= 0) { + printe("该楼层已存在!"); + return; + } + if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(newFileName.value)) { + printe("楼层名不合法!请使用字母、数字、下划线,且不能以数字开头!"); + return; + } + var width = parseInt(document.getElementById('newMapWidth').value); + var height = parseInt(document.getElementById('newMapHeight').value); + if (!core.isset(width) || !core.isset(height) || width < core.__SIZE__ || height < core.__SIZE__ || width * height > 1000) { + printe("新建地图的宽高都不得小于" + core.__SIZE__ + ",且宽高之积不能超过1000"); + return; + } + + editor_mode.onmode(''); + editor.file.saveNewFile(newFileName.value, function (err) { + if (err) { + printe(err); + throw (err) + } + core.floorIds.push(newFileName.value); + editor.file.editTower([['change', "['main']['floorIds']", core.floorIds]], function (objs_) {//console.log(objs_); + if (objs_.slice(-1)[0] != null) { + printe(objs_.slice(-1)[0]); + throw (objs_.slice(-1)[0]) + } + ; printe('新建成功,请F5刷新编辑器生效'); + }); + }); + } + + } + + + editor.uifunctions.createNewMaps_func = function () { + var newMaps = document.getElementById('newMaps'); + var newFloors = document.getElementById('newFloors'); + newMaps.onclick = function () { + if (newFloors.style.display == 'none') newFloors.style.display = 'block'; + else newFloors.style.display = 'none'; + } + + var createNewMaps = document.getElementById('createNewMaps'); + createNewMaps.onclick = function () { + var floorIds = document.getElementById('newFloorIds').value; + if (!floorIds) return; + var from = parseInt(document.getElementById('newMapsFrom').value), + to = parseInt(document.getElementById('newMapsTo').value); + if (!core.isset(from) || !core.isset(to) || from > to || from < 0 || to < 0) { + printe("请输入有效的起始和终止楼层"); + return; + } + if (to - from >= 100) { + printe("一次最多创建99个楼层"); + return; + } + var floorIdList = []; + for (var i = from; i <= to; i++) { + var floorId = floorIds.replace(/\${(.*?)}/g, function (word, value) { + return eval(value); + }); + if (core.floorIds.indexOf(floorId) >= 0) { + printe("要创建的楼层 " + floorId + " 已存在!"); + return; + } + if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(floorId)) { + printe("楼层名 " + floorId + " 不合法!请使用字母、数字、下划线,且不能以数字开头!"); + return; + } + if (floorIdList.indexOf(floorId) >= 0) { + printe("尝试重复创建楼层 " + floorId + " !"); + return; + } + floorIdList.push(floorId); + } + + var width = parseInt(document.getElementById('newMapsWidth').value); + var height = parseInt(document.getElementById('newMapsHeight').value); + if (!core.isset(width) || !core.isset(height) || width < core.__SIZE__ || height < core.__SIZE__ || width * height > 1000) { + printe("新建地图的宽高都不得小于" + core.__SIZE__ + ",且宽高之积不能超过1000"); + return; + } + editor_mode.onmode(''); + + editor.file.saveNewFiles(floorIdList, from, to, function (err) { + if (err) { + printe(err); + throw (err) + } + core.floorIds = core.floorIds.concat(floorIdList); + editor.file.editTower([['change', "['main']['floorIds']", core.floorIds]], function (objs_) {//console.log(objs_); + if (objs_.slice(-1)[0] != null) { + printe(objs_.slice(-1)[0]); + throw (objs_.slice(-1)[0]) + } + ; printe('批量创建 ' + floorIdList[0] + '~' + floorIdList[floorIdList.length - 1] + ' 成功,请F5刷新编辑器生效'); + }); + }); + } + + } + + + + /////////////////////////////////////////////////////////////////////// + //////////////////// 地图选点 ////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + + // 添加自动事件页,无需双击 + editor.uifunctions.addAutoEvent = function () { + if (editor_mode.mode != 'loc') return false; + var newid = '2'; + var ae = editor.currentFloorData.autoEvent[editor_mode.pos.x + ',' + editor_mode.pos.y]; + if (ae != null) { + var testid; + for (testid = 2; Object.hasOwnProperty.call(ae, testid); testid++); + newid = testid + ''; + } + editor_mode.addAction(['add', "['autoEvent']['" + newid + "']", null]); + editor_mode.onmode('save'); + } + + + + + + + + + + + + + /////////////////////////////////////////////////////////////////////// + //////////////////// 图块属性 ////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + editor.uifunctions.newIdIdnum_func = function () { var newIdIdnum = document.getElementById('newIdIdnum'); newIdIdnum.children[2].onclick = function () { if (newIdIdnum.children[0].value && newIdIdnum.children[1].value) { @@ -17,7 +169,7 @@ editor_unsorted_2_wrapper=function(editor_mode){ editor.file.changeIdAndIdnum(id, idnum, editor_mode.info, function (err) { if (err) { printe(err); - throw(err) + throw (err) } printe('添加id和idnum成功,请F5刷新编辑器'); }); @@ -25,17 +177,18 @@ editor_unsorted_2_wrapper=function(editor_mode){ printe('请输入id和idnum'); } } - newIdIdnum.children[4].onclick = function () { editor.file.autoRegister(editor_mode.info, function (err) { if (err) { printe(err); - throw(err) + throw (err) } printe('该列所有剩余项全部自动注册成功,请F5刷新编辑器'); }) } + } + editor.uifunctions.changeId_func = function () { var changeId = document.getElementById('changeId'); changeId.children[1].onclick = function () { var id = changeId.children[0].value; @@ -47,7 +200,7 @@ editor_unsorted_2_wrapper=function(editor_mode){ editor.file.changeIdAndIdnum(id, null, editor_mode.info, function (err) { if (err) { printe(err); - throw(err); + throw (err); } printe('修改id成功,请F5刷新编辑器'); }); @@ -55,146 +208,34 @@ editor_unsorted_2_wrapper=function(editor_mode){ printe('请输入要修改到的ID'); } } + } - var selectFloor = document.getElementById('selectFloor'); - editor.game.getFloorFileList(function (floors) { - var outstr = []; - floors[0].forEach(function (floor) { - outstr.push(["\n'].join('')); - }); - selectFloor.innerHTML = outstr.join(''); - selectFloor.value = core.status.floorId; - selectFloor.onchange = function () { - editor_mode.onmode('nextChange'); - editor_mode.onmode('floor'); - editor.changeFloor(selectFloor.value); - } - }); - var saveFloor = document.getElementById('saveFloor'); - editor_mode.saveFloor = function () { - editor_mode.onmode(''); - editor.file.saveFloorFile(function (err) { - if (err) { - printe(err); - throw(err) - } - ;printf('保存成功'); - }); - } - saveFloor.onclick = editor_mode.saveFloor; - var newMap = document.getElementById('newMap'); - var newFileName = document.getElementById('newFileName'); - newMap.onclick = function () { - if (!newFileName.value) return; - if (core.floorIds.indexOf(newFileName.value)>=0) { - printe("该楼层已存在!"); - return; - } - if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(newFileName.value)) { - printe("楼层名不合法!请使用字母、数字、下划线,且不能以数字开头!"); - return; - } - var width = parseInt(document.getElementById('newMapWidth').value); - var height = parseInt(document.getElementById('newMapHeight').value); - if (!core.isset(width) || !core.isset(height) || width1000) { - printe("新建地图的宽高都不得小于"+core.__SIZE__+",且宽高之积不能超过1000"); - return; - } - editor_mode.onmode(''); - editor.file.saveNewFile(newFileName.value, function (err) { - if (err) { - printe(err); - throw(err) - } - core.floorIds.push(newFileName.value); - editor.file.editTower([['change', "['main']['floorIds']", core.floorIds]], function (objs_) {//console.log(objs_); - if (objs_.slice(-1)[0] != null) { - printe(objs_.slice(-1)[0]); - throw(objs_.slice(-1)[0]) - } - ;printe('新建成功,请F5刷新编辑器生效'); - }); - }); - } - var newMaps = document.getElementById('newMaps'); - var newFloors = document.getElementById('newFloors'); - newMaps.onclick = function () { - if (newFloors.style.display == 'none') newFloors.style.display = 'block'; - else newFloors.style.display = 'none'; - } - var createNewMaps = document.getElementById('createNewMaps'); - createNewMaps.onclick = function () { - var floorIds = document.getElementById('newFloorIds').value; - if (!floorIds) return; - var from = parseInt(document.getElementById('newMapsFrom').value), - to = parseInt(document.getElementById('newMapsTo').value); - if (!core.isset(from) || !core.isset(to) || from>to || from<0 || to<0) { - printe("请输入有效的起始和终止楼层"); - return; - } - if (to-from >= 100) { - printe("一次最多创建99个楼层"); - return; - } - var floorIdList = []; - for (var i = from; i<=to; i++) { - var floorId = floorIds.replace(/\${(.*?)}/g, function (word, value) { - return eval(value); - }); - if (core.floorIds.indexOf(floorId)>=0) { - printe("要创建的楼层 "+floorId+" 已存在!"); - return; - } - if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(floorId)) { - printe("楼层名 "+floorId+" 不合法!请使用字母、数字、下划线,且不能以数字开头!"); - return; - } - if (floorIdList.indexOf(floorId)>=0) { - printe("尝试重复创建楼层 "+floorId+" !"); - return; - } - floorIdList.push(floorId); - } - var width = parseInt(document.getElementById('newMapsWidth').value); - var height = parseInt(document.getElementById('newMapsHeight').value); - if (!core.isset(width) || !core.isset(height) || width1000) { - printe("新建地图的宽高都不得小于"+core.__SIZE__+",且宽高之积不能超过1000"); - return; - } - editor_mode.onmode(''); - - editor.file.saveNewFiles(floorIdList, from, to, function (err) { - if (err) { - printe(err); - throw(err) - } - core.floorIds = core.floorIds.concat(floorIdList); - editor.file.editTower([['change', "['main']['floorIds']", core.floorIds]], function (objs_) {//console.log(objs_); - if (objs_.slice(-1)[0] != null) { - printe(objs_.slice(-1)[0]); - throw(objs_.slice(-1)[0]) - } - ;printe('批量创建 '+floorIdList[0]+'~'+floorIdList[floorIdList.length-1]+' 成功,请F5刷新编辑器生效'); - }); - }); - } - var changeFloorId = document.getElementById('changeFloorId'); - changeFloorId.children[1].onclick = function () { - var floorId = changeFloorId.children[0].value; + + + /////////////////////////////////////////////////////////////////////// + //////////////////// 楼层属性 ////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + + + editor.uifunctions.changeFloorId_func = function () { + + editor.dom.changeFloorId.children[1].onclick = function () { + var floorId = editor.dom.changeFloorId.children[0].value; if (floorId) { if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(floorId)) { - printe("楼层名 "+floorId+" 不合法!请使用字母、数字、下划线,且不能以数字开头!"); + printe("楼层名 " + floorId + " 不合法!请使用字母、数字、下划线,且不能以数字开头!"); return; } - if (main.floorIds.indexOf(floorId)>=0) { - printe("楼层名 "+floorId+" 已存在!"); + if (main.floorIds.indexOf(floorId) >= 0) { + printe("楼层名 " + floorId + " 已存在!"); return; } var currentFloorId = editor.currentFloorId; @@ -203,13 +244,13 @@ editor_unsorted_2_wrapper=function(editor_mode){ editor.file.saveFloorFile(function (err) { if (err) { printe(err); - throw(err); + throw (err); } core.floorIds[core.floorIds.indexOf(currentFloorId)] = floorId; editor.file.editTower([['change', "['main']['floorIds']", core.floorIds]], function (objs_) {//console.log(objs_); if (objs_.slice(-1)[0] != null) { printe(objs_.slice(-1)[0]); - throw(objs_.slice(-1)[0]) + throw (objs_.slice(-1)[0]) } alert("修改floorId成功,需要刷新编辑器生效。\n请注意,原始的楼层文件没有删除,请根据需要手动删除。"); window.location.reload(); @@ -219,47 +260,89 @@ editor_unsorted_2_wrapper=function(editor_mode){ printe('请输入要修改到的floorId'); } } + } - var ratio = 1; - var appendPicCanvas = document.getElementById('appendPicCanvas'); - var bg = appendPicCanvas.children[0]; - var source = appendPicCanvas.children[1]; - var source_ctx=source.getContext('2d'); - var picClick = appendPicCanvas.children[2]; - var sprite = appendPicCanvas.children[3]; - var sprite_ctx=sprite.getContext('2d'); - var appendPicSelection = document.getElementById('appendPicSelection'); - - [source_ctx,sprite_ctx].forEach(function(ctx){ + + + + + + + + + /////////////////////////////////////////////////////////////////////// + //////////////////// 全塔属性 ////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + + + + + + + + + + + + + /////////////////////////////////////////////////////////////////////// + //////////////////// 脚本编辑 ////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + + + + + + + + + + + + + /////////////////////////////////////////////////////////////////////// + //////////////////// 追加素材 ////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + + + + + + editor.uifunctions.fixCtx_func = function () { + [editor.dom.sourceCtx, editor.dom.spriteCtx].forEach(function (ctx) { ctx.mozImageSmoothingEnabled = false; ctx.webkitImageSmoothingEnabled = false; ctx.msImageSmoothingEnabled = false; ctx.imageSmoothingEnabled = false; }) + } + + editor.uifunctions.selectAppend_func = function () { - var selectAppend = document.getElementById('selectAppend'); var selectAppend_str = []; ["terrains", "animates", "enemys", "enemy48", "items", "npcs", "npc48", "autotile"].forEach(function (image) { selectAppend_str.push(["\n'].join('')); }); - selectAppend.innerHTML = selectAppend_str.join(''); - selectAppend.onchange = function () { + editor.dom.selectAppend.innerHTML = selectAppend_str.join(''); + editor.dom.selectAppend.onchange = function () { - var value = selectAppend.value; + var value = editor.dom.selectAppend.value; if (value == 'autotile') { editor_mode.appendPic.imageName = 'autotile'; - for (var jj=0;jj<4;jj++) appendPicSelection.children[jj].style = 'display:none'; + for (var jj = 0; jj < 4; jj++) editor.dom.appendPicSelection.children[jj].style = 'display:none'; if (editor_mode.appendPic.img) { - sprite.style.width = (sprite.width = editor_mode.appendPic.img.width) / ratio + 'px'; - sprite.style.height = (sprite.height = editor_mode.appendPic.img.height) / ratio + 'px'; - sprite_ctx.clearRect(0, 0, sprite.width, sprite.height); - sprite_ctx.drawImage(editor_mode.appendPic.img, 0, 0); + editor.dom.sprite.style.width = (editor.dom.sprite.width = editor_mode.appendPic.img.width) / editor.uivalues.ratio + 'px'; + editor.dom.sprite.style.height = (editor.dom.sprite.height = editor_mode.appendPic.img.height) / editor.uivalues.ratio + 'px'; + editor.dom.spriteCtx.clearRect(0, 0, editor.dom.sprite.width, editor.dom.sprite.height); + editor.dom.spriteCtx.drawImage(editor_mode.appendPic.img, 0, 0); } return; } - var ysize = selectAppend.value.endsWith('48') ? 48 : 32; + var ysize = editor.dom.selectAppend.value.endsWith('48') ? 48 : 32; editor_mode.appendPic.imageName = value; var img = core.material.images[value]; editor_mode.appendPic.toImg = img; @@ -268,21 +351,21 @@ editor_unsorted_2_wrapper=function(editor_mode){ editor_mode.appendPic.index = 0; var selectStr = ''; for (var ii = 0; ii < num; ii++) { - appendPicSelection.children[ii].style = 'left:0;top:0;height:' + (ysize - 6) + 'px'; + editor.dom.appendPicSelection.children[ii].style = 'left:0;top:0;height:' + (ysize - 6) + 'px'; selectStr += '{"x":0,"y":0},' } editor_mode.appendPic.selectPos = eval('[' + selectStr + ']'); for (var jj = num; jj < 4; jj++) { - appendPicSelection.children[jj].style = 'display:none'; + editor.dom.appendPicSelection.children[jj].style = 'display:none'; } - sprite.style.width = (sprite.width = img.width) / ratio + 'px'; - sprite.style.height = (sprite.height = img.height + ysize) / ratio + 'px'; - sprite_ctx.drawImage(img, 0, 0); + editor.dom.sprite.style.width = (editor.dom.sprite.width = img.width) / editor.uivalues.ratio + 'px'; + editor.dom.sprite.style.height = (editor.dom.sprite.height = img.height + ysize) / editor.uivalues.ratio + 'px'; + editor.dom.spriteCtx.drawImage(img, 0, 0); } - selectAppend.onchange(); + editor.dom.selectAppend.onchange(); + } - var getPixel=editor.util.getPixel - var setPixel=editor.util.setPixel + editor.uifunctions.selectFileBtn_func = function () { var autoAdjust = function (image, callback) { var changed = false; @@ -297,21 +380,21 @@ editor_unsorted_2_wrapper=function(editor_mode){ tempCanvas.imageSmoothingEnabled = false; tempCanvas.drawImage(image, 0, 0); var imgData = tempCanvas.getImageData(0, 0, image.width, image.height); - var trans = 0, white = 0, black=0; - for (var i=0;iblack && white>trans*10 && confirm("看起来这张图片是以纯白为底色,是否自动调整为透明底色?")) { - for (var i=0;i black && white > trans * 10 && confirm("看起来这张图片是以纯白为底色,是否自动调整为透明底色?")) { + for (var i = 0; i < image.width; i++) { + for (var j = 0; j < image.height; j++) { + var pixel = editor.util.getPixel(imgData, i, j); + if (pixel[0] == 255 && pixel[1] == 255 && pixel[2] == 255 && pixel[3] == 255) { + editor.util.setPixel(imgData, i, j, [0, 0, 0, 0]); } } } @@ -323,9 +406,9 @@ editor_unsorted_2_wrapper=function(editor_mode){ if (black>white && black>trans*10 && confirm("看起来这张图片是以纯黑为底色,是否自动调整为透明底色?")) { for (var i=0;i= num) editor_mode.appendPic.index = ii + 1 - num; else editor_mode.appendPic.index++; editor_mode.appendPic.selectPos[ii] = pos; - appendPicSelection.children[ii].style = [ + editor.dom.appendPicSelection.children[ii].style = [ 'left:', pos.x * 32, 'px;', 'top:', pos.y * pos.ysize, 'px;', 'height:', pos.ysize - 6, 'px;' ].join(''); } + } + + editor.uifunctions.appendConfirm_func = function () { var appendConfirm = document.getElementById('appendConfirm'); appendConfirm.onclick = function () { var confirmAutotile = function () { var image = editor_mode.appendPic.img; - if (image.width % 96 !=0 || image.height != 128) { + if (image.width % 96 != 0 || image.height != 128) { printe("不合法的Autotile图片!"); return; } - var imgData = source_ctx.getImageData(0,0,image.width,image.height); - sprite_ctx.putImageData(imgData, 0, 0); - var imgbase64 = sprite.toDataURL().split(',')[1]; + var imgData = editor.dom.sourceCtx.getImageData(0, 0, image.width, image.height); + editor.dom.spriteCtx.putImageData(imgData, 0, 0); + var imgbase64 = editor.dom.sprite.toDataURL().split(',')[1]; // Step 1: List文件名 fs.readdir('./project/images', function (err, data) { if (err) { printe(err); - throw(err); + throw (err); } // Step 2: 选择Autotile文件名 var filename; - for (var i=1;;++i) { - filename = 'autotile'+i; - if (data.indexOf(filename+".png")==-1) break; + for (var i = 1; ; ++i) { + filename = 'autotile' + i; + if (data.indexOf(filename + ".png") == -1) break; } // Step 3: 写入文件 - fs.writeFile('./project/images/'+filename+".png", imgbase64, 'base64', function (err, data) { + fs.writeFile('./project/images/' + filename + ".png", imgbase64, 'base64', function (err, data) { if (err) { printe(err); - throw(err); + throw (err); } // Step 4: 自动注册 editor.file.registerAutotile(filename, function (err) { if (err) { printe(err); - throw(err); + throw (err); } - printe('自动元件'+filename+'注册成功,请F5刷新编辑器'); + printe('自动元件' + filename + '注册成功,请F5刷新编辑器'); }) }) @@ -542,98 +634,96 @@ editor_unsorted_2_wrapper=function(editor_mode){ } - if (selectAppend.value == 'autotile') { + if (editor.dom.selectAppend.value == 'autotile') { confirmAutotile(); return; } - var ysize = selectAppend.value.endsWith('48') ? 48 : 32; + var ysize = editor.dom.selectAppend.value.endsWith('48') ? 48 : 32; for (var ii = 0, v; v = editor_mode.appendPic.selectPos[ii]; ii++) { - // var imgData = source_ctx.getImageData(v.x * 32, v.y * ysize, 32, ysize); - // sprite_ctx.putImageData(imgData, ii * 32, sprite.height - ysize); - // sprite_ctx.drawImage(editor_mode.appendPic.img, v.x * 32, v.y * ysize, 32, ysize, ii * 32, height, 32, ysize) + // var imgData = editor.dom.sourceCtx.getImageData(v.x * 32, v.y * ysize, 32, ysize); + // editor.dom.spriteCtx.putImageData(imgData, ii * 32, editor.dom.sprite.height - ysize); + // editor.dom.spriteCtx.drawImage(editor_mode.appendPic.img, v.x * 32, v.y * ysize, 32, ysize, ii * 32, height, 32, ysize) - sprite_ctx.drawImage(source_ctx.canvas, v.x*32, v.y*ysize, 32, ysize, 32*ii, sprite.height - ysize, 32, ysize); + editor.dom.spriteCtx.drawImage(editor.dom.sourceCtx.canvas, v.x * 32, v.y * ysize, 32, ysize, 32 * ii, editor.dom.sprite.height - ysize, 32, ysize); } - var dt = sprite_ctx.getImageData(0, 0, sprite.width, sprite.height); - var imgbase64 = sprite.toDataURL().split(',')[1]; + var dt = editor.dom.spriteCtx.getImageData(0, 0, editor.dom.sprite.width, editor.dom.sprite.height); + var imgbase64 = editor.dom.sprite.toDataURL().split(',')[1]; fs.writeFile('./project/images/' + editor_mode.appendPic.imageName + '.png', imgbase64, 'base64', function (err, data) { if (err) { printe(err); - throw(err) + throw (err) } - printe('追加素材成功,请F5刷新编辑器,或继续追加当前素材'); - sprite.style.height = (sprite.height = (sprite.height+ysize)) + "px"; - sprite_ctx.putImageData(dt, 0, 0); + printf('追加素材成功,你可以继续追加其他素材,最后再刷新以显示在素材区'); + editor.dom.sprite.style.height = (editor.dom.sprite.height = (editor.dom.sprite.height + ysize)) + "px"; + editor.dom.spriteCtx.putImageData(dt, 0, 0); }); } - editor_mode.change = function (value) { - editor_mode.onmode('nextChange'); - editor_mode.onmode(value); - if(editor.isMobile)editor.showdataarea(false); - } - var editModeSelect = document.getElementById('editModeSelect'); - editModeSelect.onchange = function () { - editor_mode.change(editModeSelect.value); - } + var quickAppendConfirm = document.getElementById('quickAppendConfirm'); + quickAppendConfirm.onclick = function () { + var value = editor.dom.selectAppend.value; + if (value != 'enemys' && value != 'enemy48' && value != 'npcs' && value != 'npc48') + return printe("只有怪物或NPC才能快速导入!"); + var ysize = value.endsWith('48') ? 48 : 32; + if (editor.dom.sourceCtx.canvas.width != 128 || editor.dom.sourceCtx.canvas.height != 4 * ysize) + return printe("只有 4*4 的素材图片才可以快速导入!"); - editor_mode.checkUnique = function (thiseval) { - if (!(thiseval instanceof Array)) return false; - var map = {}; - for (var i = 0; i, + * "plugins": + * } + * 的形式记录所有更改过的文件,save时写入 + * 的内容暂时还没想好 + */ + this.fileMark = {} } // 这个函数之后挪到editor.table? - editor_file_proto.prototype.loadCommentjs=function(callback){ + editor_file_proto.prototype.loadCommentjs = function (callback) { var commentjs = { 'comment': 'comment', 'data.comment': 'dataComment', @@ -33,5 +42,107 @@ editor_file_wrapper = function (editor) { } } + editor_file_proto.prototype.alertWhenCompress = function () { + if (editor.useCompress === true) { + editor.useCompress = 'alerted'; + setTimeout("alert('当前游戏使用的是压缩文件,修改完成后请使用启动服务.exe->Js代码压缩工具重新压缩,或者把main.js的useCompress改成false来使用原始文件')", 1000) + } + } + + editor_file_proto.prototype.formatMap = function (mapArr, trySimplify) { + if (!mapArr || JSON.stringify(mapArr) == JSON.stringify([])) return ''; + if (trySimplify) { + //检查是否是全0二维数组 + var jsoncheck = JSON.stringify(mapArr).replace(/\D/g, ''); + if (jsoncheck == Array(jsoncheck.length + 1).join('0')) return ''; + } + //把二维数组格式化 + var formatArrStr = ''; + var arr = JSON.stringify(mapArr).replace(/\s+/g, '').split('],['); + var si = mapArr.length - 1, sk = mapArr[0].length - 1; + for (var i = 0; i <= si; i++) { + var a = []; + formatArrStr += ' ['; + if (i == 0 || i == si) a = arr[i].split(/\D+/).join(' ').trim().split(' '); + else a = arr[i].split(/\D+/); + for (var k = 0; k <= sk; k++) { + var num = parseInt(a[k]); + formatArrStr += Array(Math.max(4 - String(num).length, 0)).join(' ') + num + (k == sk ? '' : ','); + } + formatArrStr += ']' + (i == si ? '' : ',\n'); + } + return formatArrStr; + } + + editor_file_proto.prototype.saveFloor = function (floorData, callback) { + //callback(err:String) + var floorId = floorData.floorId; + var filename = 'project/floors/' + floorId + '.js'; + var datastr = ['main.floors.', floorId, '=\n']; + + var tempJsonObj = Object.assign({}, floorData); + var tempMap = [['map', editor.util.guid()], ['bgmap', editor.util.guid()], ['fgmap', editor.util.guid()]]; + tempMap.forEach(function (v) { + v[2] = tempJsonObj[v[0]]; + tempJsonObj[v[0]] = v[1]; + }); + var tempJson = JSON.stringify(tempJsonObj, editor.game.replacerForSaving, 4); + tempMap.forEach(function (v) { + tempJson = tempJson.replace('"' + v[1] + '"', '[\n' + editor.file.formatMap(v[2], v[0] != 'map') + '\n]') + }); + datastr = datastr.concat([tempJson]); + datastr = datastr.join(''); + editor.file.alertWhenCompress(); + editor.fs.writeFile(filename, editor.util.encode64(datastr), 'base64', function (err, data) { + editor.addUsedFlags(datastr); + callback(err); + }); + } + + editor_file_proto.prototype.saveScript = function (name, varName, dataObj, callback) { + // 此处格式化以及写入 project/xxx.js 形式的文件 + editor.file.alertWhenCompress(); + + if (['maps', 'enemys'].indexOf(name) === -1) { + // 全部用\t展开 + var content = JSON.stringify(dataObj, editor.game.replacerForSaving, '\t'); + } else { + // 只用\t展开第一层 + var emap = {}; + var estr = JSON.stringify(dataObj, function (_k, v) { + if (v.id != null) { + var id_ = editor.util.guid(); + emap[id_] = JSON.stringify(v, editor.game.replacerForSaving); + return id_; + } else return v + }, '\t'); + for (var id_ in emap) { + estr = estr.replace('"' + id_ + '"', emap[id_]); + } + var content = estr; + } + + var strToWrite = `var ${varName} = \n${content}`; + editor.fs.writeFile(`project/${name}.js`, editor.util.encode64(strToWrite), 'base64', function (err, data) { + callback(err); + }); + } + + editor_file_proto.prototype.saveCommentJs = function () { + // 无需格式化的写入, 把multi的那部分略微修改 + } + + editor_file_proto.prototype.saveImage = function () { + // 给追加素材使用 + } + + editor_file_proto.prototype.addMark = function (name) { + // 把name对应的文件在editor.file.fileMark添加标记 + } + + editor_file_proto.prototype.save = function (callback) { + // 根据 editor.file.fileMark 把游戏对象格式化写入文件 + } + } \ No newline at end of file diff --git a/_server/editor_file_unsorted.js b/_server/editor_file_unsorted.js index cbf79655..42509f14 100644 --- a/_server/editor_file_unsorted.js +++ b/_server/editor_file_unsorted.js @@ -5,9 +5,8 @@ editor_file = function (editor, callback) { editor.file.loadCommentjs(callback); - /////////////////////////////////////////////////////////////////////////// - editor.file.saveFloorFile = function (callback) { + //callback(err:String) checkCallback(callback); /* if (!isset(editor.currentFloorId) || !isset(editor.currentFloorData)) { callback('未选中文件或无数据'); @@ -25,27 +24,11 @@ editor_file = function (editor, callback) { editor.currentFloorData[name]=mapArray; } } - - // format 更改实现方式以支持undefined删除 - var tempJsonObj=Object.assign({},editor.currentFloorData); - var tempMap=[['map',editor.util.guid()],['bgmap',editor.util.guid()],['fgmap',editor.util.guid()]]; - tempMap.forEach(function(v){ - v[2]=tempJsonObj[v[0]]; - tempJsonObj[v[0]]=v[1]; - }); - var tempJson=JSON.stringify(tempJsonObj, null, 4); - tempMap.forEach(function(v){ - tempJson=tempJson.replace('"'+v[1]+'"','[\n'+ formatMap(v[2],v[0]!='map')+ '\n]') - }); - datastr = datastr.concat([tempJson]); - datastr = datastr.join(''); - alertWhenCompress(); - fs.writeFile(filename, encode(datastr), 'base64', function (err, data) { - editor.addUsedFlags(datastr); - callback(err); - }); + editor.file.saveFloor(editor.currentFloorData, callback) } - //callback(err:String) + + /////////////////////////////////////////////////////////////////////////// + editor.file.saveNewFile = function (saveFilename, callback) { //saveAsFilename不含'/'不含'.js' checkCallback(callback); @@ -135,7 +118,7 @@ editor_file = function (editor, callback) { delete data[t]; else { if (t=='map') { - datastr = datastr.concat(['\n"', t, '": [\n', formatMap(data[t]), '\n],']); + datastr = datastr.concat(['\n"', t, '": [\n', editor.file.formatMap(data[t]), '\n],']); } else { datastr = datastr.concat(['\n"', t, '": ', JSON.stringify(data[t], null, 4), ',']); @@ -146,7 +129,7 @@ editor_file = function (editor, callback) { datastr = datastr.join(''); datas.push(encode(datastr)); } - alertWhenCompress(); + editor.file.alertWhenCompress(); fs.writeMultiFiles(filenames, datas, function (err, data) { callback(err); }); @@ -469,7 +452,8 @@ editor_file = function (editor, callback) { checkCallback(callback); if (isset(actionList) && actionList.length > 0) { actionList.forEach(function (value) { - value[1] = value[1] + "['" + x + "," + y + "']"; + if(/\['autoEvent'\]\['\d+'\]$/.test(value[1]))value[1]=value[1].replace(/\['\d+'\]$/,function(v){return "['" + x + "," + y + "']"+v}) + else value[1] = value[1] + "['" + x + "," + y + "']"; }); saveSetting('floorloc', actionList, function (err) { callback([err]); @@ -700,32 +684,7 @@ editor_file = function (editor, callback) { } } - var formatMap = function (mapArr,trySimplify) { - if(!mapArr || JSON.stringify(mapArr)==JSON.stringify([]))return ''; - if(trySimplify){ - //检查是否是全0二维数组 - var jsoncheck=JSON.stringify(mapArr).replace(/\D/g,''); - if(jsoncheck==Array(jsoncheck.length+1).join('0'))return ''; - } - //把二维数组格式化 - var formatArrStr = ''; - var arr = JSON.stringify(mapArr).replace(/\s+/g, '').split('],['); - var si=mapArr.length-1,sk=mapArr[0].length-1; - for (var i = 0; i <= si; i++) { - var a = []; - formatArrStr += ' ['; - if (i == 0 || i == si) a = arr[i].split(/\D+/).join(' ').trim().split(' '); - else a = arr[i].split(/\D+/); - for (var k = 0; k <= sk; k++) { - var num = parseInt(a[k]); - formatArrStr += Array(Math.max(4 - String(num).length, 0)).join(' ') + num + (k == sk ? '' : ','); - } - formatArrStr += ']' + (i == si ? '' : ',\n'); - } - return formatArrStr; - } - - var encode = editor.util.encode64 + var encode = editor.util.encode64; var alertWhenCompress = function(){ if(editor.useCompress===true){ @@ -761,7 +720,7 @@ editor_file = function (editor, callback) { var saveSetting = function (file, actionList, callback) { //console.log(file); //console.log(actionList); - alertWhenCompress(); + editor.file.alertWhenCompress(); if (file == 'icons') { actionList.forEach(function (value) { @@ -863,7 +822,13 @@ editor_file = function (editor, callback) { if (file == 'floorloc') { actionList.forEach(function (value) { // 检测null/undefined - if (value[2]==null) + if(/\['autoEvent'\]\['\d+,\d+'\]\['\d+'\]$/.test(value[1])){ + var tempvalue=value[1].replace(/\['\d+'\]$/,'') + tempvalue="editor.currentFloorData" +tempvalue + tempvalue=tempvalue+'='+tempvalue+'||{}' + eval(tempvalue) + } + if (value[2]==null && value[0]!=='add') eval("delete editor.currentFloorData" + value[1]); else eval("editor.currentFloorData" + value[1] + '=' + JSON.stringify(value[2])); diff --git a/_server/editor_game.js b/_server/editor_game.js index 278dd67e..27c51001 100644 --- a/_server/editor_game.js +++ b/_server/editor_game.js @@ -146,6 +146,9 @@ editor_game_wrapper = function (editor, main, core) { }); editor.currentFloorId = core.status.floorId; editor.currentFloorData = core.floors[core.status.floorId]; + // 补出缺省的数据 + editor.currentFloorData.autoEvent = editor.currentFloorData.autoEvent || {}; + // for (var ii = 0, name; name = ['bgmap', 'fgmap'][ii]; ii++) { var mapArray = editor.currentFloorData[name]; if (!mapArray || JSON.stringify(mapArray) == JSON.stringify([])) {//未设置或空数组 @@ -175,6 +178,18 @@ editor_game_wrapper = function (editor, main, core) { callback([editor.core.floorIds, null]); } + editor_game.prototype.doCoreFunc = function (funcname) { + return core[funcname].apply(core, Array.prototype.slice.call(arguments, 1)); + } + + editor_game.prototype.getEnemy = function (id) { + return core.material.enemys[id]; + } + + editor_game.prototype.getFirstData = function () { + return core.firstData; + } + editor.constructor.prototype.game = new editor_game(); } //editor_game_wrapper(editor); \ No newline at end of file diff --git a/_server/editor_unsorted_3.js b/_server/editor_legacy.js similarity index 61% rename from _server/editor_unsorted_3.js rename to _server/editor_legacy.js index 7f1d0edc..1313ebbc 100644 --- a/_server/editor_unsorted_3.js +++ b/_server/editor_legacy.js @@ -1,4 +1,6 @@ - +// 由于历史遗留原因, 以下变量作为全局变量使用 +// exportMap mapEditArea pout mapEditArea copyMap clearMapButton deleteMap printf printe tip selectBox +// 除对这些量的功能修改外, 误在此文件中增加新变量或函数 exportMap = document.getElementById('exportMap') exportMap.isExport=false exportMap.onclick=function(){ @@ -361,7 +363,6 @@ tip.whichShow=function(value){ return tip._whichShow } selectBox=document.getElementById('selectBox') -dataSelection=document.getElementById('dataSelection') selectBox._isSelected=false selectBox.isSelected=function(value){ if(value!=null){ @@ -369,206 +370,9 @@ selectBox.isSelected=function(value){ tip.isSelectedBlock(value); tip.whichShow(0); clearTimeout(tip.timer); - dataSelection.style.display=value?'':'none' + editor.dom.dataSelection.style.display=value?'':'none' } return selectBox._isSelected } -// ------ UI预览 & 地图选点相关 ------ // - -uievent = { - elements: {}, - values: {}, - isOpen: false, - mode: "" -}; - -uievent.elements.div = document.getElementById('uieventDiv'); -uievent.elements.title = document.getElementById('uieventTitle'); -uievent.elements.yes = document.getElementById('uieventYes'); -uievent.elements.no = document.getElementById('uieventNo'); -uievent.elements.selectBackground = document.getElementById('uieventBackground'); -uievent.elements.selectPoint = document.getElementById('selectPoint'); -uievent.elements.selectFloor = document.getElementById('selectPointFloor'); -uievent.elements.selectPointBox = document.getElementById('selectPointBox'); -uievent.elements.body = document.getElementById('uieventBody'); -uievent.elements.selectPointButtons = document.getElementById('selectPointButtons'); - -uievent.confirm = function () { - var callback = uievent.values.callback, floorId = uievent.values.floorId, - x = uievent.values.x, y = uievent.values.y; - uievent.close(); - if (callback) { - callback(floorId, x, y); - } -} -uievent.elements.yes.onclick = uievent.confirm; - -uievent.close = function () { - uievent.isOpen = false; - uievent.elements.div.style.display = 'none'; - uievent.values = {}; -} -uievent.elements.no.onclick = uievent.close; - -uievent.elements.selectBackground.onchange = function () { - uievent.drawPreviewUI(); -} - -uievent.drawPreviewUI = function () { - core.setAlpha('uievent', 1); - core.clearMap('uievent'); - - // 绘制UI - var background = uievent.elements.selectBackground.value; - if (background == 'thumbnail') { - core.drawThumbnail(editor.currentFloorId, null, {}, 'uievent'); - } - else { - core.fillRect('uievent', 0, 0, core.__PIXELS__, core.__PIXELS__, background); - } - - if (uievent.values.list instanceof Array) { - uievent.values.list.forEach(function (data) { - var type = data.type; - if (!type || !core.ui["_uievent_"+type]) return; - core.ui["_uievent_"+type](data); - }) - } -} - -uievent.previewUI = function (list) { - uievent.isOpen = true; - uievent.elements.div.style.display = 'block'; - uievent.mode = 'previewUI'; - uievent.elements.selectPoint.style.display = 'none'; - uievent.elements.yes.style.display = 'none'; - uievent.elements.title.innerText = 'UI绘制预览'; - uievent.elements.selectBackground.style.display = 'inline'; - uievent.elements.selectBackground.value = 'thumbnail'; - uievent.elements.selectPointBox.style.display = 'none'; - - uievent.values.list = list; - uievent.drawPreviewUI(); -} - -uievent.selectPoint = function (floorId, x, y, hideFloor, callback) { - uievent.values.hideFloor = hideFloor; - uievent.values.callback = callback; - uievent.values.size = editor.isMobile ? window.innerWidth / core.__SIZE__ : 32; - uievent.elements.selectPointBox.style.width = (uievent.values.size - 6) + "px"; - uievent.elements.selectPointBox.style.height = (uievent.values.size - 6) + "px"; - - uievent.isOpen = true; - uievent.elements.div.style.display = 'block'; - uievent.mode = 'selectPoint'; - uievent.elements.selectPoint.style.display = 'block'; - uievent.elements.yes.style.display = 'inline'; - uievent.elements.selectBackground.style.display = 'none'; - uievent.elements.selectFloor.style.display = hideFloor ? 'none': 'inline'; - uievent.elements.selectPointBox.style.display = 'block'; - - // Append children - var floors = ""; - core.floorIds.forEach(function (f) { - floors += ""; - }) - uievent.elements.selectFloor.innerHTML = floors; - - this.setPoint(floorId || editor.currentFloorId, core.calValue(x) || 0, core.calValue(y) || 0); -} - -uievent.updateSelectPoint = function (redraw) { - uievent.elements.title.innerText = '地图选点 ('+uievent.values.x+","+uievent.values.y+')'; - if (redraw) { - core.setAlpha('uievent', 1); - core.clearMap('uievent'); - core.drawThumbnail(uievent.values.floorId, null, null, - {ctx: 'uievent', centerX: uievent.values.left + core.__HALF_SIZE__, - centerY: uievent.values.top + core.__HALF_SIZE__}); - } - uievent.elements.selectPointBox.style.left = uievent.values.size * (uievent.values.x - uievent.values.left) + "px"; - uievent.elements.selectPointBox.style.top = uievent.values.size * (uievent.values.y - uievent.values.top) + "px"; -} - -uievent.setPoint = function (floorId, x, y) { - if (core.floorIds.indexOf(floorId) == -1) floorId = editor.currentFloorId; - uievent.values.floorId = floorId; - uievent.elements.selectFloor.value = floorId; - uievent.values.x = x != null ? x : ( uievent.values.x || 0); - uievent.values.y = y != null ? y : ( uievent.values.y || 0); - uievent.values.width = core.floors[uievent.values.floorId].width || core.__SIZE__; - uievent.values.height = core.floors[uievent.values.floorId].height || core.__SIZE__; - uievent.values.left = core.clamp(uievent.values.x - core.__HALF_SIZE__, 0, uievent.values.width - core.__SIZE__); - uievent.values.top = core.clamp(uievent.values.y - core.__HALF_SIZE__, 0, uievent.values.height - core.__SIZE__); - uievent.updateSelectPoint(true); -} - -uievent.elements.selectFloor.onchange = function () { - uievent.setPoint(uievent.elements.selectFloor.value); -} - -uievent.elements.selectPointBox.onclick = function (e) { - e.stopPropagation(); -} - -uievent.elements.body.onclick = function (e) { - if (uievent.mode != 'selectPoint') return; - uievent.values.x = uievent.values.left + Math.floor(e.offsetX / uievent.values.size); - uievent.values.y = uievent.values.top + Math.floor(e.offsetY / uievent.values.size); - uievent.updateSelectPoint(false); -} - -uievent.move = function (dx, dy) { - if (uievent.mode != 'selectPoint') return; - uievent.values.left = core.clamp(uievent.values.left + dx, 0, uievent.values.width - core.__SIZE__); - uievent.values.top = core.clamp(uievent.values.top + dy, 0, uievent.values.height - core.__SIZE__); - this.updateSelectPoint(true); -}; - -(function() { - - var viewportButtons = uievent.elements.selectPointButtons; - var pressTimer = null; - for(var ii=0,node;node=viewportButtons.children[ii];ii++){ - (function(x,y){ - var move = function () { - uievent.move(x, y); - } - node.onmousedown = function () { - clearTimeout(pressTimer); - pressTimer = setTimeout(function () { - pressTimer = -1; - var f = function () { - if (pressTimer != null) { - move(); - setTimeout(f, 150); - } - } - f(); - }, 500); - }; - node.onmouseup = function () { - if (pressTimer > 0) { - clearTimeout(pressTimer); - move(); - } - pressTimer = null; - } - })([-1,0,0,1][ii],[0,-1,1,0][ii]); - } -})(); - -uievent.elements.div.onmousewheel = function (e) { - if (uievent.mode != 'selectPoint' || uievent.values.hideFloor) return; - var index = core.floorIds.indexOf(uievent.values.floorId); - try { - if (e.wheelDelta) - index+=Math.sign(e.wheelDelta); - else if (e.detail) - index+=Math.sign(e.detail); - } catch (ee) { main.log(ee); } - index = core.clamp(index, 0, core.floorIds.length - 1); - uievent.setPoint(core.floorIds[index]); -} - +// 修改此文件前先看文件开头的说明 \ No newline at end of file diff --git a/_server/editor_listen.js b/_server/editor_listen.js new file mode 100644 index 00000000..dec2bc2f --- /dev/null +++ b/_server/editor_listen.js @@ -0,0 +1,159 @@ +editor_listen_wrapper = function (editor) { + + editor.constructor.prototype.listen = function () { + + editor.dom.body.onmousedown = editor.uifunctions.body_click; + + editor.dom.eui.oncontextmenu = function (e) { e.preventDefault() } // 自定义了右键菜单, 阻止默认行为 + editor.dom.midMenu.oncontextmenu = function (e) { e.preventDefault() } + + editor.dom.eui.ondblclick = editor.uifunctions.map_doubleClick + + editor.dom.eui.onmousedown = editor.uifunctions.map_ondown + editor.dom.eui.onmousemove = editor.uifunctions.map_onmove + editor.dom.eui.onmouseup = editor.uifunctions.map_onup + + editor.dom.mid.onmousewheel = editor.uifunctions.map_mousewheel + + editor.uivalues.shortcut = core.getLocalStorage('shortcut', { 48: 0, 49: 0, 50: 0, 51: 0, 52: 0, 53: 0, 54: 0, 55: 0, 56: 0, 57: 0 }); + editor.dom.body.onkeydown = editor.uifunctions.body_shortcut + + editor.uivalues.scrollBarHeight = editor.uifunctions.getScrollBarHeight(); + editor.dom.iconExpandBtn.style.display = 'block'; + editor.dom.iconExpandBtn.innerText = editor.uivalues.folded ? "展开素材区" : "折叠素材区"; + editor.dom.iconExpandBtn.onclick = editor.uifunctions.fold_material_click + + editor.dom.iconLib.onmousedown = editor.uifunctions.material_ondown + + editor.dom.extraEvent.onmousedown = editor.uifunctions.extraEvent_click + editor.dom.chooseThis.onmousedown = editor.uifunctions.chooseThis_click + editor.dom.chooseInRight.onmousedown = editor.uifunctions.chooseInRight_click + editor.dom.copyLoc.onmousedown = editor.uifunctions.copyLoc_click + editor.dom.moveLoc.onmousedown = editor.uifunctions.moveLoc_click + editor.dom.clearEvent.onmousedown = editor.uifunctions.clearEvent_click + editor.dom.clearLoc.onmousedown = editor.uifunctions.clearLoc_click + + editor.dom.brushMod.onchange = editor.uifunctions.brushMod_onchange + if (editor.dom.brushMod2) editor.dom.brushMod2.onchange = editor.uifunctions.brushMod2_onchange; + if (editor.dom.brushMod3) editor.dom.brushMod3.onchange = editor.uifunctions.brushMod3_onchange; + + editor.dom.layerMod.onchange = editor.uifunctions.layerMod_onchange + if (editor.dom.layerMod2) editor.dom.layerMod2.onchange = editor.uifunctions.layerMod2_onchange; + if (editor.dom.layerMod3) editor.dom.layerMod3.onchange = editor.uifunctions.layerMod3_onchange; + + editor.uifunctions.viewportButtons_func() + } + + editor.constructor.prototype.mobile_listen = function () { + if (!editor.isMobile) return; + + var mobileview = document.getElementById('mobileview'); + var mid = document.getElementById('mid'); + var right = document.getElementById('right'); + // var mobileeditdata = document.getElementById('mobileeditdata'); + + + editor.showdataarea = function (callShowMode) { + mid.style = 'z-index:-1;opacity: 0;'; + right.style = 'z-index:-1;opacity: 0;'; + // mobileeditdata.style = ''; + if (callShowMode) editor.mode.showMode(editor.dom.editModeSelect.value); + editor.uifunctions.hideMidMenu(); + } + mobileview.children[0].onclick = function () { + editor.showdataarea(true) + } + mobileview.children[1].onclick = function () { + mid.style = ''; + right.style = 'z-index:-1;opacity: 0;'; + // mobileeditdata.style = 'z-index:-1;opacity: 0;'; + editor.lastClickId = ''; + } + mobileview.children[3].onclick = function () { + mid.style = 'z-index:-1;opacity: 0;'; + right.style = ''; + // mobileeditdata.style = 'z-index:-1;opacity: 0;'; + editor.lastClickId = ''; + } + + /* + var gettrbyid = function () { + if (!editor.lastClickId) return false; + thisTr = document.getElementById(editor.lastClickId); + input = thisTr.children[2].children[0].children[0]; + field = thisTr.children[0].getAttribute('title'); + cobj = JSON.parse(thisTr.children[1].getAttribute('cobj')); + return [thisTr, input, field, cobj]; + } + mobileeditdata.children[0].onclick = function () { + var info = gettrbyid() + if (!info) return; + info[1].ondblclick() + } + mobileeditdata.children[1].onclick = function () { + var info = gettrbyid() + if (!info) return; + printf(info[2]) + } + mobileeditdata.children[2].onclick = function () { + var info = gettrbyid() + if (!info) return; + printf(info[0].children[1].getAttribute('title')) + } + */ + + //===== + + document.body.ontouchstart = document.body.onmousedown; + document.body.onmousedown = null; + + editor.dom.eui.ontouchstart = editor.dom.eui.onmousedown + editor.dom.eui.onmousedown = null + editor.dom.eui.ontouchmove = editor.dom.eui.onmousemove + editor.dom.eui.onmousemove = null + editor.dom.eui.ontouchend = editor.dom.eui.onmouseup + editor.dom.eui.onmouseup = null + + + editor.dom.chooseThis.ontouchstart = editor.dom.chooseThis.onmousedown + editor.dom.chooseThis.onmousedown = null + editor.dom.chooseInRight.ontouchstart = editor.dom.chooseInRight.onmousedown + editor.dom.chooseInRight.onmousedown = null + editor.dom.copyLoc.ontouchstart = editor.dom.copyLoc.onmousedown + editor.dom.copyLoc.onmousedown = null + editor.dom.moveLoc.ontouchstart = editor.dom.moveLoc.onmousedown + editor.dom.moveLoc.onmousedown = null + editor.dom.clearLoc.ontouchstart = editor.dom.clearLoc.onmousedown + editor.dom.clearLoc.onmousedown = null + } + + editor.constructor.prototype.mode_listen = function (callback) { + + // 这里的函数还没有写jsdoc, 通过_func()的方式先完成分类 + + editor.uifunctions.newIdIdnum_func() + editor.uifunctions.changeId_func() + + editor.uifunctions.selectFloor_func() + editor.uifunctions.saveFloor_func() + + editor.uifunctions.newMap_func() + + editor.uifunctions.createNewMaps_func() + + editor.uifunctions.changeFloorId_func() + + editor.uifunctions.fixCtx_func() + + editor.uifunctions.selectAppend_func() + editor.uifunctions.selectFileBtn_func() + editor.uifunctions.changeColorInput_func() + editor.uifunctions.picClick_func() + editor.uifunctions.appendConfirm_func() + + editor.dom.editModeSelect.onchange = editor.mode.editModeSelect_onchange + + if (Boolean(callback)) callback(); + } + +} \ No newline at end of file diff --git a/_server/editor_mappanel.js b/_server/editor_mappanel.js new file mode 100644 index 00000000..9e50b957 --- /dev/null +++ b/_server/editor_mappanel.js @@ -0,0 +1,839 @@ +editor_mappanel_wrapper = function (editor) { + + // 暂时先 注释+分类 内部函数未完成重构 + + /** + * 在绘图区格子内画一个随机色块 + */ + editor.uifunctions.fillPos = function (pos) { + editor.dom.euiCtx.fillStyle = '#' + ~~(Math.random() * 8) + ~~(Math.random() * 8) + ~~(Math.random() * 8); + editor.dom.euiCtx.fillRect(pos.x * 32 + 12 - core.bigmap.offsetX, pos.y * 32 + 12 - core.bigmap.offsetY, 8, 8); + } + + /** + * 从鼠标点击返回可用的组件内坐标 + */ + editor.uifunctions.eToLoc = function (e) { + var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft + var scrollTop = document.documentElement.scrollTop || document.body.scrollTop + var xx = e.clientX, yy = e.clientY + if (editor.isMobile) { xx = e.touches[0].clientX, yy = e.touches[0].clientY } + editor.loc = { + 'x': scrollLeft + xx - editor.dom.mid.offsetLeft - editor.dom.mapEdit.offsetLeft, + 'y': scrollTop + yy - editor.dom.mid.offsetTop - editor.dom.mapEdit.offsetTop, + 'size': editor.isMobile ? (32 * innerWidth * 0.96 / core.__PIXELS__) : 32 + }; + return editor.loc; + } + + /** + * 组件内坐标转地图位置 + * @param {Boolean} addViewportOffset 是否加上大地图的偏置 + */ + editor.uifunctions.locToPos = function (loc, addViewportOffset) { + var offsetX = 0, offsetY = 0; + if (addViewportOffset) { + offsetX = core.bigmap.offsetX / 32; + offsetY = core.bigmap.offsetY / 32; + } + editor.pos = { 'x': ~~(loc.x / loc.size) + offsetX, 'y': ~~(loc.y / loc.size) + offsetY } + return editor.pos; + } + + /** + * editor.dom.eui.ondblclick + * 双击地图可以选中素材 + */ + editor.uifunctions.map_doubleClick = function (e) { + if (editor.uivalues.bindSpecialDoor.loc != null) return; + var loc = editor.uifunctions.eToLoc(e); + var pos = editor.uifunctions.locToPos(loc, true); + editor.setSelectBoxFromInfo(editor[editor.layerMod][pos.y][pos.x]); + return; + } + + /** + * 用于鼠标移出map后清除状态 + */ + editor.uifunctions.clearMapStepStatus = function () { + if (editor.uivalues.mouseOutCheck > 1) { + editor.uivalues.mouseOutCheck--; + setTimeout(editor.uifunctions.clearMapStepStatus, 1000); + return; + } + editor.uivalues.holdingPath = 0; + editor.uivalues.stepPostfix = []; + editor.dom.euiCtx.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__); + editor.uivalues.startPos = editor.uivalues.endPos = null; + } + + /** + * editor.dom.eui.onmousedown + * + 绑定机关门事件的选择怪物 + * + 右键进入菜单 + * + 非绘图时选中 + * + 绘图时画个矩形在那个位置 + */ + editor.uifunctions.map_ondown = function (e) { + var loc = editor.uifunctions.eToLoc(e); + var pos = editor.uifunctions.locToPos(loc, true); + if (editor.uivalues.bindSpecialDoor.loc != null) { + var x = editor.pos.x, y = editor.pos.y, id = (editor.map[y][x] || {}).id; + // 检测是否是怪物 + if (id && editor.game.getEnemy(id)) { + var locstr = x + "," + y, index = editor.uivalues.bindSpecialDoor.enemys.indexOf(locstr); + if (index >= 0) editor.uivalues.bindSpecialDoor.enemys.splice(index, 1); + else editor.uivalues.bindSpecialDoor.enemys.push(locstr); + editor.drawEventBlock(); + editor.uifunctions._extraEvent_bindSpecialDoor_doAction(); + } + return false; + } + if (e.button == 2) { + editor.uifunctions.showMidMenu(e.clientX, e.clientY); + return false; + } + if (!selectBox.isSelected()) { + editor_mode.onmode('nextChange'); + editor_mode.onmode('loc'); + //editor_mode.loc(); + //tip.whichShow(1); + tip.showHelp(6); + editor.uivalues.startPos = pos; + editor.dom.euiCtx.strokeStyle = '#FF0000'; + editor.dom.euiCtx.lineWidth = 3; + if (editor.isMobile) editor.uifunctions.showMidMenu(e.clientX, e.clientY); + return false; + } + + editor.uivalues.holdingPath = 1; + editor.uivalues.mouseOutCheck = 2; + setTimeout(editor.uifunctions.clearMapStepStatus); + editor.dom.euiCtx.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__); + editor.uivalues.stepPostfix = []; + editor.uivalues.stepPostfix.push(pos); + if (editor.brushMod == 'line') editor.uifunctions.fillPos(pos); + return false; + } + + /** + * editor.dom.eui.onmousemove + * + 非绘图模式时维护起止位置并画箭头 + * + 绘图模式时找到与队列尾相邻的鼠标方向的点画个矩形 + */ + editor.uifunctions.map_onmove = function (e) { + if (!selectBox.isSelected()) { + if (editor.uivalues.startPos == null) return; + //tip.whichShow(1); + var loc = editor.uifunctions.eToLoc(e); + var pos = editor.uifunctions.locToPos(loc, true); + if (editor.uivalues.endPos != null && editor.uivalues.endPos.x == pos.x && editor.uivalues.endPos.y == pos.y) return; + if (editor.uivalues.endPos != null) { + editor.dom.euiCtx.clearRect(Math.min(32 * editor.uivalues.startPos.x - core.bigmap.offsetX, 32 * editor.uivalues.endPos.x - core.bigmap.offsetX), + Math.min(32 * editor.uivalues.startPos.y - core.bigmap.offsetY, 32 * editor.uivalues.endPos.y - core.bigmap.offsetY), + (Math.abs(editor.uivalues.startPos.x - editor.uivalues.endPos.x) + 1) * 32, (Math.abs(editor.uivalues.startPos.y - editor.uivalues.endPos.y) + 1) * 32) + } + editor.uivalues.endPos = pos; + if (editor.uivalues.startPos != null) { + if (editor.uivalues.startPos.x != editor.uivalues.endPos.x || editor.uivalues.startPos.y != editor.uivalues.endPos.y) { + core.drawArrow('eui', + 32 * editor.uivalues.startPos.x + 16 - core.bigmap.offsetX, 32 * editor.uivalues.startPos.y + 16 - core.bigmap.offsetY, + 32 * editor.uivalues.endPos.x + 16 - core.bigmap.offsetX, 32 * editor.uivalues.endPos.y + 16 - core.bigmap.offsetY); + } + } + // editor_mode.onmode('nextChange'); + // editor_mode.onmode('loc'); + //editor_mode.loc(); + //tip.whichShow(1); + // tip.showHelp(6); + return false; + } + + if (editor.uivalues.holdingPath == 0) { + return false; + } + editor.uivalues.mouseOutCheck = 2; + var loc = editor.uifunctions.eToLoc(e); + var pos = editor.uifunctions.locToPos(loc, true); + var pos0 = editor.uivalues.stepPostfix[editor.uivalues.stepPostfix.length - 1] + var directionDistance = [pos.y - pos0.y, pos0.x - pos.x, pos0.y - pos.y, pos.x - pos0.x] + var max = 0, index = 4; + for (var i = 0; i < 4; i++) { + if (directionDistance[i] > max) { + index = i; + max = directionDistance[i]; + } + } + var pos = [{ 'x': 0, 'y': 1 }, { 'x': -1, 'y': 0 }, { 'x': 0, 'y': -1 }, { 'x': 1, 'y': 0 }, false][index] + if (pos) { + pos.x += pos0.x; + pos.y += pos0.y; + if (editor.brushMod == 'line') editor.uifunctions.fillPos(pos); + else { + var x0 = editor.uivalues.stepPostfix[0].x; + var y0 = editor.uivalues.stepPostfix[0].y; + var x1 = pos.x; + var y1 = pos.y; + if (x0 > x1) { x0 ^= x1; x1 ^= x0; x0 ^= x1; }//swap + if (y0 > y1) { y0 ^= y1; y1 ^= y0; y0 ^= y1; }//swap + // draw rect + editor.dom.euiCtx.clearRect(0, 0, editor.dom.euiCtx.canvas.width, editor.dom.euiCtx.canvas.height); + editor.dom.euiCtx.fillStyle = 'rgba(0, 127, 255, 0.4)'; + editor.dom.euiCtx.fillRect(32 * x0 - core.bigmap.offsetX, 32 * y0 - core.bigmap.offsetY, + 32 * (x1 - x0) + 32, 32 * (y1 - y0) + 32); + } + editor.uivalues.stepPostfix.push(pos); + } + return false; + } + + /** + * editor.dom.eui.onmouseup + * + 非绘图模式时, 交换首末点的内容 + * + 绘图模式时, 根据画线/画矩形/画tileset 做对应的绘制 + */ + editor.uifunctions.map_onup = function (e) { + if (!selectBox.isSelected()) { + //tip.whichShow(1); + // editor.movePos(editor.uivalues.startPos, editor.uivalues.endPos); + if (editor.layerMod == 'map') + editor.exchangePos(editor.uivalues.startPos, editor.uivalues.endPos); + else + editor.exchangeBgFg(editor.uivalues.startPos, editor.uivalues.endPos, editor.layerMod); + editor.uivalues.startPos = editor.uivalues.endPos = null; + editor.dom.euiCtx.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__); + return false; + } + editor.uivalues.holdingPath = 0; + if (editor.uivalues.stepPostfix && editor.uivalues.stepPostfix.length) { + editor.uivalues.preMapData = JSON.parse(JSON.stringify({ map: editor.map, fgmap: editor.fgmap, bgmap: editor.bgmap })); + if (editor.brushMod !== 'line') { + var x0 = editor.uivalues.stepPostfix[0].x; + var y0 = editor.uivalues.stepPostfix[0].y; + var x1 = editor.uivalues.stepPostfix[editor.uivalues.stepPostfix.length - 1].x; + var y1 = editor.uivalues.stepPostfix[editor.uivalues.stepPostfix.length - 1].y; + if (x0 > x1) { x0 ^= x1; x1 ^= x0; x0 ^= x1; }//swap + if (y0 > y1) { y0 ^= y1; y1 ^= y0; y0 ^= y1; }//swap + editor.uivalues.stepPostfix = []; + for (var jj = y0; jj <= y1; jj++) { + for (var ii = x0; ii <= x1; ii++) { + editor.uivalues.stepPostfix.push({ x: ii, y: jj }) + } + } + } + editor.uivalues.currDrawData.pos = JSON.parse(JSON.stringify(editor.uivalues.stepPostfix)); + editor.uivalues.currDrawData.info = JSON.parse(JSON.stringify(editor.info)); + editor.uivalues.reDo = null; + // console.log(editor.uivalues.stepPostfix); + if (editor.brushMod === 'tileset' && core.tilesets.indexOf(editor.info.images) !== -1) { + var imgWidth = ~~(core.material.images.tilesets[editor.info.images].width / 32); + var x0 = editor.uivalues.stepPostfix[0].x; + var y0 = editor.uivalues.stepPostfix[0].y; + var idnum = editor.info.idnum; + for (var ii = 0; ii < editor.uivalues.stepPostfix.length; ii++) { + if (editor.uivalues.stepPostfix[ii].y != y0) { + y0++; + idnum += imgWidth; + } + editor[editor.layerMod][editor.uivalues.stepPostfix[ii].y][editor.uivalues.stepPostfix[ii].x] = editor.ids[editor.indexs[idnum + editor.uivalues.stepPostfix[ii].x - x0]]; + } + } else { + for (var ii = 0; ii < editor.uivalues.stepPostfix.length; ii++) + editor[editor.layerMod][editor.uivalues.stepPostfix[ii].y][editor.uivalues.stepPostfix[ii].x] = editor.info; + } + // console.log(editor.map); + editor.updateMap(); + editor.uivalues.holdingPath = 0; + editor.uivalues.stepPostfix = []; + editor.dom.euiCtx.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__); + } + return false; + } + + /** + * editor.dom.mid.onmousewheel + * 在地图编辑区域滚轮切换楼层 + */ + editor.uifunctions.map_mousewheel = function (e) { + var wheel = function (direct) { + var index = editor.core.floorIds.indexOf(editor.currentFloorId); + var toId = editor.currentFloorId; + + if (direct > 0 && index < editor.core.floorIds.length - 1) + toId = editor.core.floorIds[index + 1]; + else if (direct < 0 && index > 0) + toId = editor.core.floorIds[index - 1]; + else return; + + editor_mode.onmode('nextChange'); + editor_mode.onmode('floor'); + editor.dom.selectFloor.value = toId; + editor.changeFloor(toId); + } + + try { + if (e.wheelDelta) + wheel(Math.sign(e.wheelDelta)) + else if (e.detail) + wheel(Math.sign(e.detail)); + } + catch (ee) { + console.log(ee); + } + return false; + } + + /** + * 显示右键菜单 + */ + editor.uifunctions.showMidMenu = function (x, y) { + editor.uivalues.lastRightButtonPos = JSON.parse(JSON.stringify( + [editor.pos, editor.uivalues.lastRightButtonPos[0]] + )); + // --- copy + editor.uivalues.lastCopyedInfo = [editor.copyFromPos(), editor.uivalues.lastCopyedInfo[0]]; + var locStr = '(' + editor.uivalues.lastRightButtonPos[1].x + ',' + editor.uivalues.lastRightButtonPos[1].y + ')'; + var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft; + var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; + + // 检测是否是上下楼 + var thisevent = editor.map[editor.pos.y][editor.pos.x]; + if (thisevent == 0) { + editor.dom.extraEvent.style.display = 'block'; + editor.dom.extraEvent.children[0].innerHTML = '绑定出生点为此点'; + } + else if (thisevent.id == 'upFloor') { + editor.dom.extraEvent.style.display = 'block'; + editor.dom.extraEvent.children[0].innerHTML = '绑定上楼事件'; + } + else if (thisevent.id == 'downFloor') { + editor.dom.extraEvent.style.display = 'block'; + editor.dom.extraEvent.children[0].innerHTML = '绑定下楼事件'; + } + else if (['leftPortal', 'rightPortal', 'downPortal', 'upPortal'].indexOf(thisevent.id) >= 0) { + editor.dom.extraEvent.style.display = 'block'; + editor.dom.extraEvent.children[0].innerHTML = '绑定楼传事件'; + } + else if (thisevent.id == 'specialDoor') { + editor.dom.extraEvent.style.display = 'block'; + editor.dom.extraEvent.children[0].innerHTML = '绑定机关门事件'; + } + else editor.dom.extraEvent.style.display = 'none'; + + editor.dom.chooseThis.children[0].innerHTML = '选中此点' + '(' + editor.pos.x + ',' + editor.pos.y + ')' + editor.dom.copyLoc.children[0].innerHTML = '复制事件' + locStr + '到此处'; + editor.dom.moveLoc.children[0].innerHTML = '交换事件' + locStr + '与此事件的位置'; + editor.dom.midMenu.style = 'top:' + (y + scrollTop) + 'px;left:' + (x + scrollLeft) + 'px;'; + } + + /** + * 隐藏右键菜单 + */ + editor.uifunctions.hideMidMenu = function () { + if (editor.isMobile) { + setTimeout(function () { + editor.dom.midMenu.style = 'display:none'; + }, 200) + } else { + editor.dom.midMenu.style = 'display:none'; + } + } + + /** + * editor.dom.extraEvent.onmousedown + * 菜单 附加点操作 + */ + editor.uifunctions.extraEvent_click = function (e) { + editor.uifunctions.hideMidMenu(); + e.stopPropagation(); + + var thisevent = editor.map[editor.pos.y][editor.pos.x]; + return editor.uifunctions._extraEvent_bindStartPoint(thisevent) + || editor.uifunctions._extraEvent_bindStair(thisevent) + || editor.uifunctions._extraEvent_bindSpecialDoor(thisevent); + } + + /** + * 绑定该空地点为起始点 + */ + editor.uifunctions._extraEvent_bindStartPoint = function (thisevent) { + if (thisevent != 0) return false; + editor.mode.onmode('tower'); + editor.mode.addAction(["change", "['firstData']['floorId']", editor.currentFloorId]); + editor.mode.addAction(["change", "['firstData']['hero']['loc']['x']", editor.pos.x]); + editor.mode.addAction(["change", "['firstData']['hero']['loc']['y']", editor.pos.y]); + editor.mode.onmode('save', function () { + core.firstData.floorId = editor.currentFloorId; + core.firstData.hero.loc.x = editor.pos.x; + core.firstData.hero.loc.y = editor.pos.y; + editor.drawPosSelection(); + editor.drawEventBlock(); + editor.mode.tower(); + printf('绑定初始点成功'); + }); + } + + /** + * 绑定该楼梯的楼传事件 + */ + editor.uifunctions._extraEvent_bindStair = function (thisevent) { + if (['upFloor', 'downFloor', 'leftPortal', 'rightPortal', 'upPortal', 'downPortal'].indexOf(thisevent.id) < 0) + return false; + var loc = editor.pos.x + "," + editor.pos.y; + if (thisevent.id == 'upFloor') { + editor.currentFloorData.changeFloor[loc] = { "floorId": ":next", "stair": "downFloor" }; + } + else if (thisevent.id == 'downFloor') { + editor.currentFloorData.changeFloor[loc] = { "floorId": ":before", "stair": "upFloor" }; + } + else if (thisevent.id == 'leftPortal' || thisevent.id == 'rightPortal') { + editor.currentFloorData.changeFloor[loc] = { "floorId": ":next", "stair": ":symmetry_x" } + } + else if (thisevent.id == 'upPortal' || thisevent.id == 'downPortal') { + editor.currentFloorData.changeFloor[loc] = { "floorId": ":next", "stair": ":symmetry_y" } + } + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw (err) + } + editor.drawPosSelection(); + editor.drawEventBlock(); + editor_mode.showMode('loc'); + printf('添加楼梯事件成功'); + }); + return true; + } + + /** + * 绑定该机关门的事件 + */ + editor.uifunctions._extraEvent_bindSpecialDoor = function (thisevent) { + if (thisevent.id != 'specialDoor') return false; + var number = parseInt(prompt("请输入该机关门的怪物数量", "0"))|| 0; + if (number <= 0) return true; + editor.uivalues.bindSpecialDoor.n = number; + editor.uivalues.bindSpecialDoor.loc = editor.pos.x + ',' + editor.pos.y; + editor.uivalues.bindSpecialDoor.enemys = []; + printf("请点击选择" + number + "个怪物;切换楼层或刷新页面取消操作。"); + } + + /** + * 确定绑定该机关门的事件 + * cancel:是否取消此模式 + */ + editor.uifunctions._extraEvent_bindSpecialDoor_doAction = function (cancel) { + var bindSpecialDoor = editor.uivalues.bindSpecialDoor; + if (cancel) { + bindSpecialDoor.loc = null; + bindSpecialDoor.enemys = []; + bindSpecialDoor.n = 0; + editor.drawEventBlock(); + printf(""); + return; + } + if (bindSpecialDoor.loc == null || bindSpecialDoor.enemys.length != bindSpecialDoor.n) return; + // 添加机关门自动事件 + var doorFlag = "flag:door_" + editor.currentFloorId + "_" + bindSpecialDoor.loc.replace(',', '_'); + editor.currentFloorData.autoEvent[bindSpecialDoor.loc] = { + '0': { + "condition": doorFlag + "==" + bindSpecialDoor.n, + "currentFloor": true, + "priority": 0, + "delayExecute": false, + "multiExecute": false, + "data": [ + {"type": "openDoor"} + ] + } + }; + bindSpecialDoor.enemys.forEach(function (loc) { + editor.currentFloorData.afterBattle[loc] = [ + {"type": "addValue", "name": doorFlag, "value": "1"} + ] + }); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw (err) + } + editor.drawEventBlock(); + editor.drawPosSelection(); + editor_mode.showMode('loc'); + printf('绑定机关门事件成功'); + }); + bindSpecialDoor.loc = null; + bindSpecialDoor.enemys = []; + bindSpecialDoor.n = 0; + } + + /** + * editor.dom.chooseThis.onmousedown + * 菜单 选中此点 + */ + editor.uifunctions.chooseThis_click = function (e) { + editor.uifunctions.hideMidMenu(); + e.stopPropagation(); + selectBox.isSelected(false); + + editor_mode.onmode('nextChange'); + editor_mode.onmode('loc'); + //editor_mode.loc(); + //tip.whichShow(1); + if (editor.isMobile) editor.showdataarea(false); + } + + /** + * editor.dom.chooseInRight.onmousedown + * 菜单 在素材区选中此图块 + */ + editor.uifunctions.chooseInRight_click = function (e) { + editor.uifunctions.hideMidMenu(); + e.stopPropagation(); + var thisevent = editor[editor.layerMod][editor.pos.y][editor.pos.x]; + editor.setSelectBoxFromInfo(thisevent); + } + + /** + * editor.dom.copyLoc.onmousedown + * 菜单 复制此事件 + */ + editor.uifunctions.copyLoc_click = function (e) { + editor.uifunctions.hideMidMenu(); + e.stopPropagation(); + editor.uivalues.preMapData = null; + editor.uivalues.reDo = null; + editor_mode.onmode(''); + var now = editor.pos, last = editor.uivalues.lastRightButtonPos[1]; + if (now.x == last.x && now.y == last.y) return; + editor.pasteToPos(editor.uivalues.lastCopyedInfo[1]); + editor.updateMap(); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw (err) + } + ; printf('复制事件成功'); + editor.drawPosSelection(); + }); + } + + /** + * editor.dom.moveLoc.onmousedown + * 菜单 移动此事件 + */ + editor.uifunctions.moveLoc_click = function (e) { + editor.uifunctions.hideMidMenu(); + e.stopPropagation(); + editor.uivalues.preMapData = null; + editor.uivalues.reDo = null; + editor_mode.onmode(''); + editor.exchangePos(editor.pos, editor.uivalues.lastRightButtonPos[1]); + } + + /** + * editor.dom.clearEvent.onmousedown + * 菜单 仅清空此点事件 + */ + editor.uifunctions.clearEvent_click = function (e) { + e.stopPropagation(); + editor.uivalues.reDo = null; + editor.clearPos(false); + } + + /** + * editor.dom.clearLoc.onmousedown + * 菜单 清空此点及事件 + */ + editor.uifunctions.clearLoc_click = function (e) { + e.stopPropagation(); + editor.uivalues.reDo = null; + editor.clearPos(true); + } + + /** + * editor.dom.brushMod.onchange + * 切换画笔模式 + */ + editor.uifunctions.brushMod_onchange = function () { + editor.brushMod = editor.dom.brushMod.value; + } + + /** + * editor.dom.brushMod2.onchange + * 切换画笔模式 + */ + editor.uifunctions.brushMod2_onchange = function () { + editor.brushMod = editor.dom.brushMod2.value; + } + + /** + * editor.dom.brushMod3.onchange + * 切换画笔模式 + */ + editor.uifunctions.brushMod3_onchange = function () { + // tip.showHelp(5) + tip.isSelectedBlock(false) + tip.msgs[11] = String('tileset贴图模式下可以按选中tileset素材,并在地图上拖动来一次绘制一个区域'); + tip.whichShow(12); + editor.brushMod = editor.dom.brushMod3.value; + } + + /** + * editor.dom.layerMod.onchange + * 切换编辑的层 + */ + editor.uifunctions.layerMod_onchange = function () { + editor.layerMod = editor.dom.layerMod.value; + [editor.dom.bgc, editor.dom.fgc, editor.dom.evc, editor.dom.ev2c].forEach(function (x) { + x.style.opacity = 1; + }); + + // 手机端.... + if (editor.isMobile) { + if (editor.dom.layerMod.value == 'bgmap') { + [editor.dom.fgc, editor.dom.evc, editor.dom.ev2c].forEach(function (x) { + x.style.opacity = 0.3; + }); + } + if (editor.dom.layerMod.value == 'fgmap') { + [editor.dom.bgc, editor.dom.evc, editor.dom.ev2c].forEach(function (x) { + x.style.opacity = 0.3; + }); + } + } + } + + /** + * editor.dom.layerMod2.onchange + * 切换编辑的层 + */ + editor.uifunctions.layerMod2_onchange = function () { + editor.layerMod = editor.dom.layerMod2.value; + [editor.dom.fgc, editor.dom.evc, editor.dom.ev2c].forEach(function (x) { + x.style.opacity = 0.3; + }); + editor.dom.bgc.style.opacity = 1; + } + + /** + * editor.dom.layerMod3.onchange + * 切换编辑的层 + */ + editor.uifunctions.layerMod3_onchange = function () { + editor.layerMod = editor.dom.layerMod3.value; + [editor.dom.bgc, editor.dom.evc, editor.dom.ev2c].forEach(function (x) { + x.style.opacity = 0.3; + }); + editor.dom.fgc.style.opacity = 1; + } + + /** + * 移动大地图可视窗口的绑定 + */ + editor.uifunctions.viewportButtons_func = function () { + var pressTimer = null; + for (var ii = 0, node; node = editor.dom.viewportButtons.children[ii]; ii++) { + (function (x, y) { + var move = function () { + editor.moveViewport(x, y); + } + node.onmousedown = function () { + clearTimeout(pressTimer); + pressTimer = setTimeout(function () { + pressTimer = -1; + var f = function () { + if (pressTimer != null) { + move(); + setTimeout(f, 150); + } + } + f(); + }, 500); + }; + node.onmouseup = function () { + if (pressTimer > 0) { + clearTimeout(pressTimer); + move(); + } + pressTimer = null; + } + })([-1, 0, 0, 1][ii], [0, -1, 1, 0][ii]); + } + } + + editor.uifunctions.selectFloor_func = function () { + var selectFloor = document.getElementById('selectFloor'); + editor.game.getFloorFileList(function (floors) { + var outstr = []; + floors[0].forEach(function (floor) { + outstr.push(["\n'].join('')); + }); + selectFloor.innerHTML = outstr.join(''); + selectFloor.value = core.status.floorId; + selectFloor.onchange = function () { + editor_mode.onmode('nextChange'); + editor_mode.onmode('floor'); + editor.changeFloor(selectFloor.value); + } + }); + } + + + editor.uifunctions.saveFloor_func = function () { + var saveFloor = document.getElementById('saveFloor'); + editor_mode.saveFloor = function () { + editor_mode.onmode(''); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw (err) + } + ; printf('保存成功'); + }); + } + saveFloor.onclick = editor_mode.saveFloor; + } + + + + ///////////////////////////////////////////////////////////////////////////// + + + editor.constructor.prototype.copyFromPos = function (pos) { + var fields = Object.keys(editor.file.comment._data.floors._data.loc._data); + pos = pos || editor.pos; + var map = core.clone(editor.map[pos.y][pos.x]); + var events = {}; + fields.forEach(function(v){ + events[v] = core.clone(editor.currentFloorData[v][pos.x+','+pos.y]); + }) + return {map: map, events: events}; + } + + editor.constructor.prototype.pasteToPos = function (info, pos) { + if (info == null) return; + var fields = Object.keys(editor.file.comment._data.floors._data.loc._data); + pos = pos || editor.pos; + editor.map[pos.y][pos.x] = core.clone(info.map); + fields.forEach(function(v){ + if (info.events[v] == null) delete editor.currentFloorData[v][pos.x+","+pos.y]; + else editor.currentFloorData[v][pos.x+","+pos.y] = core.clone(info.events[v]); + }); + } + + editor.constructor.prototype.movePos = function (startPos, endPos, callback) { + if (!startPos || !endPos) return; + if (startPos.x == endPos.x && startPos.y == endPos.y) return; + var copyed = editor.copyFromPos(startPos); + editor.pasteToPos({map:0, events: {}}, startPos); + editor.pasteToPos(copyed, endPos); + editor.updateMap(); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw(err) + } + ;printf('移动事件成功'); + editor.drawPosSelection(); + if (callback) callback(); + }); + } + + editor.constructor.prototype.exchangePos = function (startPos, endPos, callback) { + if (!startPos || !endPos) return; + if (startPos.x == endPos.x && startPos.y == endPos.y) return; + var startInfo = editor.copyFromPos(startPos); + var endInfo = editor.copyFromPos(endPos); + editor.pasteToPos(startInfo, endPos); + editor.pasteToPos(endInfo, startPos); + editor.updateMap(); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw(err) + } + ;printf('交换事件成功'); + editor.drawPosSelection(); + if (callback) callback(); + }); + } + + editor.constructor.prototype.moveBgFg = function (startPos, endPos, name, callback) { + if (!startPos || !endPos || ["bgmap","fgmap"].indexOf(name)<0) return; + if (startPos.x == endPos.x && startPos.y == endPos.y) return; + editor[name][endPos.y][endPos.x] = editor[name][startPos.y][startPos.x]; + editor[name][startPos.y][startPos.x] = 0; + editor.updateMap(); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw(err) + } + ;printf('移动图块成功'); + editor.drawPosSelection(); + if (callback) callback(); + }); + } + + editor.constructor.prototype.exchangeBgFg = function (startPos, endPos, name, callback) { + if (!startPos || !endPos || ["bgmap","fgmap"].indexOf(name)<0) return; + if (startPos.x == endPos.x && startPos.y == endPos.y) return; + var value = editor[name][endPos.y][endPos.x]; + editor[name][endPos.y][endPos.x] = editor[name][startPos.y][startPos.x]; + editor[name][startPos.y][startPos.x] = value; + editor.updateMap(); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw(err) + } + ;printf('交换图块成功'); + editor.drawPosSelection(); + if (callback) callback(); + }); + + } + + editor.constructor.prototype.clearPos = function (clearPos, pos, callback) { + var fields = Object.keys(editor.file.comment._data.floors._data.loc._data); + pos = pos || editor.pos; + editor.uifunctions.hideMidMenu(); + editor.uivalues.preMapData = null; + editor.info = 0; + editor_mode.onmode(''); + if (clearPos) + editor.map[pos.y][pos.x]=editor.info; + editor.updateMap(); + fields.forEach(function(v){ + delete editor.currentFloorData[v][pos.x+','+pos.y]; + }) + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw(err) + } + ;printf(clearPos?'清空该点和事件成功':'只清空该点事件成功'); + editor.drawPosSelection(); + if (callback) callback(); + }); + } + + + + + + + + + + + + + + + + + + +} \ No newline at end of file diff --git a/_server/editor_materialpanel.js b/_server/editor_materialpanel.js new file mode 100644 index 00000000..2ba50d82 --- /dev/null +++ b/_server/editor_materialpanel.js @@ -0,0 +1,130 @@ +editor_materialpanel_wrapper = function (editor) { + + editor.uifunctions.getScrollBarHeight = function () { + var outer = document.createElement("div"); + outer.style.visibility = "hidden"; + outer.style.width = "100px"; + outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps + + document.body.appendChild(outer); + + var widthNoScroll = outer.offsetWidth; + // force scrollbars + outer.style.overflow = "scroll"; + + // add innerdiv + var inner = document.createElement("div"); + inner.style.width = "100%"; + outer.appendChild(inner); + + var widthWithScroll = inner.offsetWidth; + + // remove divs + outer.parentNode.removeChild(outer); + + return widthNoScroll - widthWithScroll; + } + + /** + * editor.dom.iconExpandBtn.onclick + */ + editor.uifunctions.fold_material_click = function () { + if (confirm(editor.uivalues.folded ? "你想要展开素材吗?\n展开模式下将显示全素材内容。" + : ("你想要折叠素材吗?\n折叠模式下每个素材将仅显示单列,并且每" + editor.uivalues.foldPerCol + "个自动换列。"))) { + core.setLocalStorage('folded', !editor.uivalues.folded); + window.location.reload(); + } + } + + /** + * editor.dom.iconLib.onmousedown + * 素材区的单击事件 + */ + editor.uifunctions.material_ondown = function (e) { + e.stopPropagation(); + if (!editor.isMobile && e.clientY >= editor.dom.iconLib.offsetHeight - editor.uivalues.scrollBarHeight) return; + var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft; + var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; + var loc = { + 'x': scrollLeft + e.clientX + editor.dom.iconLib.scrollLeft - right.offsetLeft - editor.dom.iconLib.offsetLeft, + 'y': scrollTop + e.clientY + editor.dom.iconLib.scrollTop - right.offsetTop - editor.dom.iconLib.offsetTop, + 'size': 32 + }; + editor.loc = loc; + var pos = editor.uifunctions.locToPos(loc); + for (var spriter in editor.widthsX) { + if (pos.x >= editor.widthsX[spriter][1] && pos.x < editor.widthsX[spriter][2]) { + var ysize = spriter.endsWith('48') ? 48 : 32; + loc.ysize = ysize; + pos.images = editor.widthsX[spriter][0]; + pos.y = ~~(loc.y / loc.ysize); + if (!editor.uivalues.folded && core.tilesets.indexOf(pos.images) == -1) pos.x = editor.widthsX[spriter][1]; + var autotiles = core.material.images['autotile']; + if (pos.images == 'autotile') { + var imNames = Object.keys(autotiles); + if ((pos.y + 1) * ysize > editor.widthsX[spriter][3]) + pos.y = ~~(editor.widthsX[spriter][3] / ysize) - 4; + else { + for (var i = 0; i < imNames.length; i++) { + if (pos.y >= 4 * i && pos.y < 4 * (i + 1)) { + pos.images = imNames[i]; + pos.y = 4 * i; + } + } + } + } + else { + var height = editor.widthsX[spriter][3], col = height / ysize; + if (editor.uivalues.folded && core.tilesets.indexOf(pos.images) == -1) { + col = (pos.x == editor.widthsX[spriter][2] - 1) ? ((col - 1) % editor.uivalues.foldPerCol + 1) : editor.uivalues.foldPerCol; + } + if (spriter == 'terrains' && pos.x == editor.widthsX[spriter][1]) col += 2; + pos.y = Math.min(pos.y, col - 1); + } + + selectBox.isSelected(true); + // console.log(pos,core.material.images[pos.images].height) + editor.dom.dataSelection.style.left = pos.x * 32 + 'px'; + editor.dom.dataSelection.style.top = pos.y * ysize + 'px'; + editor.dom.dataSelection.style.height = ysize - 6 + 'px'; + + if (pos.x == 0 && pos.y == 0) { + // editor.info={idnum:0, id:'empty','images':'清除块', 'y':0}; + editor.info = 0; + } else if (pos.x == 0 && pos.y == 1) { + editor.info = editor.ids[editor.indexs[17]]; + } else { + if (autotiles[pos.images]) editor.info = { 'images': pos.images, 'y': 0 }; + else if (core.tilesets.indexOf(pos.images) != -1) editor.info = { 'images': pos.images, 'y': pos.y, 'x': pos.x - editor.widthsX[spriter][1] }; + else { + var y = pos.y; + if (editor.uivalues.folded) { + y += editor.uivalues.foldPerCol * (pos.x - editor.widthsX[spriter][1]); + } + if (pos.images == 'terrains' && pos.x == 0) y -= 2; + editor.info = { 'images': pos.images, 'y': y } + } + + for (var ii = 0; ii < editor.ids.length; ii++) { + if ((core.tilesets.indexOf(pos.images) != -1 && editor.info.images == editor.ids[ii].images + && editor.info.y == editor.ids[ii].y && editor.info.x == editor.ids[ii].x) + || (Object.prototype.hasOwnProperty.call(autotiles, pos.images) && editor.info.images == editor.ids[ii].id + && editor.info.y == editor.ids[ii].y) + || (core.tilesets.indexOf(pos.images) == -1 && editor.info.images == editor.ids[ii].images + && editor.info.y == editor.ids[ii].y) + ) { + + editor.info = editor.ids[ii]; + break; + } + } + } + tip.infos(JSON.parse(JSON.stringify(editor.info))); + editor_mode.onmode('nextChange'); + editor_mode.onmode('enemyitem'); + //editor_mode.enemyitem(); + } + } + } + +} \ No newline at end of file diff --git a/_server/editor_mode.js b/_server/editor_mode.js index aadbec9a..8e42b7e0 100644 --- a/_server/editor_mode.js +++ b/_server/editor_mode.js @@ -21,7 +21,7 @@ editor_mode = function (editor) { this.mode = ''; this.info = {}; this.appendPic = {}; - this.doubleClickMode='change'; + this.doubleClickMode = 'change'; } editor_mode.prototype.init = function (callback) { @@ -49,15 +49,16 @@ editor_mode = function (editor) { editor_mode.actionList.push(action); } - editor_mode.prototype.doActionList = function (mode, actionList) { + editor_mode.prototype.doActionList = function (mode, actionList, callback) { if (actionList.length == 0) return; printf('修改中...'); - var cb=function(objs_){ + var cb = function (objs_) { if (objs_.slice(-1)[0] != null) { printe(objs_.slice(-1)[0]); - throw(objs_.slice(-1)[0]) + throw (objs_.slice(-1)[0]) } - ;printf('修改成功' + (data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.name == 'template' ? '\n\n请注意:全塔属性的name尚未修改,请及时予以设置' : '')); + ; printf('修改成功' + (data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.name == 'template' ? '\n\n请注意:全塔属性的name尚未修改,请及时予以设置' : '')); + if (callback) callback(); } switch (mode) { case 'loc': @@ -95,9 +96,9 @@ editor_mode = function (editor) { } } - editor_mode.prototype.onmode = function (mode) { + editor_mode.prototype.onmode = function (mode, callback) { if (editor_mode.mode != mode) { - if (mode === 'save') editor_mode.doActionList(editor_mode.mode, editor_mode.actionList); + if (mode === 'save') editor_mode.doActionList(editor_mode.mode, editor_mode.actionList, callback); if (editor_mode.mode === 'nextChange' && mode) editor_mode.showMode(mode); if (mode !== 'save') editor_mode.mode = mode; editor_mode.actionList = []; @@ -109,14 +110,78 @@ editor_mode = function (editor) { editor_mode.dom[name].style = 'z-index:-1;opacity: 0;'; } editor_mode.dom[mode].style = ''; - editor_mode.doubleClickMode='change'; + editor_mode.doubleClickMode = 'change'; // clear editor.drawEventBlock(); if (editor_mode[mode]) editor_mode[mode](); - document.getElementById('editModeSelect').value = mode; + editor.dom.editModeSelect.value = mode; if (!selectBox.isSelected()) tip.showHelp(); } + editor_mode.prototype.change = function (value) { + editor_mode.onmode('nextChange'); + editor_mode.onmode(value); + if (editor.isMobile) editor.showdataarea(false); + } + + + editor_mode.prototype.checkUnique = function (thiseval) { + if (!(thiseval instanceof Array)) return false; + var map = {}; + for (var i = 0; i < thiseval.length; ++i) { + if (map[thiseval[i]]) { + alert("警告:存在重复定义!"); + return false; + } + map[thiseval[i]] = true; + } + return true; + } + + editor_mode.prototype.checkFloorIds = function (thiseval) { + if (!editor_mode.checkUnique(thiseval)) return false; + var oldvalue = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main.floorIds; + fs.readdir('project/floors', function (err, data) { + if (err) { + printe(err); + throw Error(err); + } + var newfiles = thiseval.map(function (v) { return v + '.js' }); + var notExist = ''; + for (var name, ii = 0; name = newfiles[ii]; ii++) { + if (data.indexOf(name) === -1) notExist = name; + } + if (notExist) { + var discard = confirm('文件' + notExist + '不存在, 保存会导致工程无法打开, 是否放弃更改'); + if (discard) { + editor.file.editTower([['change', "['main']['floorIds']", oldvalue]], function (objs_) {//console.log(objs_); + if (objs_.slice(-1)[0] != null) { + printe(objs_.slice(-1)[0]); + throw (objs_.slice(-1)[0]) + } + ; printe('已放弃floorIds的修改,请F5进行刷新'); + }); + } + } + }); + return true + } + + editor_mode.prototype.changeDoubleClickModeByButton = function (mode) { + ({ + delete: function () { + printf('下一次双击表格的项删除,切换下拉菜单可取消;编辑后需刷新浏览器生效。'); + editor_mode.doubleClickMode = mode; + }, + add: function () { + printf('下一次双击表格的项则在同级添加新项,切换下拉菜单可取消;编辑后需刷新浏览器生效。'); + editor_mode.doubleClickMode = mode; + } + }[mode])(); + } + + ///////////////////////////////////////////////////////////////////////////// + editor_mode.prototype.loc = function (callback) { //editor.pos={x: 0, y: 0}; if (!core.isset(editor.pos)) return; @@ -140,7 +205,7 @@ editor_mode = function (editor) { //editor.info=editor.ids[editor.indexs[201]]; if (!core.isset(editor.info)) return; - if (Object.keys(editor.info).length !== 0 && editor.info.idnum!=17) editor_mode.info = editor.info;//避免editor.info被清空导致无法获得是物品还是怪物 + if (Object.keys(editor.info).length !== 0 && editor.info.idnum != 17) editor_mode.info = editor.info;//避免editor.info被清空导致无法获得是物品还是怪物 if (!core.isset(editor_mode.info.id)) { // document.getElementById('table_a3f03d4c_55b8_4ef6_b362_b345783acd72').innerHTML = ''; @@ -232,7 +297,7 @@ editor_mode = function (editor) { tableinfo.listen(tableinfo.guids); if (Boolean(callback)) callback(); } - + editor_mode.prototype.plugins = function (callback) { var objs = []; editor.file.editPlugins([], function (objs_) { @@ -246,11 +311,17 @@ editor_mode = function (editor) { if (Boolean(callback)) callback(); } -///////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + + /** + * editor.dom.editModeSelect.onchange + */ + editor_mode.prototype.editModeSelect_onchange = function () { + editor_mode.change(editor.dom.editModeSelect.value); + } editor_mode.prototype.listen = function (callback) { - - // 移动至 editor_unsorted_2.js + // 移动至 editor_listen.js -> editor.constructor.prototype.mode_listen } var editor_mode = new editor_mode(); diff --git a/_server/editor_multi.js b/_server/editor_multi.js index ecfd6b7d..b694bf51 100644 --- a/_server/editor_multi.js +++ b/_server/editor_multi.js @@ -121,6 +121,7 @@ editor_multi = function () { } codeEditor.setValue(tstr || ''); } + document.getElementById('showPlugins').style.display = editor_mode.mode == 'plugins' ? 'block': 'none'; editor_multi.show(); return true; } @@ -186,6 +187,11 @@ editor_multi = function () { setvalue(codeEditor.getValue() || ''); } + editor_multi.showPlugins = function () { + if (editor.isMobile && !confirm("你确定要跳转到云端插件列表吗?")) return; + window.open("https://h5mota.com/plugins/", "_blank"); + } + var multiLineArgs = [null, null, null]; editor_multi.multiLineEdit = function (value, b, f, args, callback) { editor_multi.id = 'callFromBlockly'; diff --git a/_server/editor_table.js b/_server/editor_table.js index e141e5ff..b2e8cf3f 100644 --- a/_server/editor_table.js +++ b/_server/editor_table.js @@ -26,13 +26,19 @@ editor_table_wrapper = function (editor) { editor_table.prototype.textarea = function (value, indent) { return /* html */`\n` } + editor_table.prototype.editGrid = function (showComment) { + var html = ""; + if (showComment) html += "
"; + html += ""; + return html; + } editor_table.prototype.title = function () { - return /* html */`\n条目注释值\n` + return /* html */`\n条目注释值操作\n` } editor_table.prototype.gap = function (field) { - return /* html */`--------${field}\n` + return /* html */`--------${field}----\n` } editor_table.prototype.tr = function (guid, field, shortField, commentHTMLescape, cobjstr, shortCommentHTMLescape, tdstr) { @@ -40,6 +46,7 @@ editor_table_wrapper = function (editor) { ${shortField} ${shortCommentHTMLescape}
${tdstr}
+ ${editor.table.editGrid(commentHTMLescape != shortCommentHTMLescape)} \n` } @@ -145,6 +152,7 @@ editor_table_wrapper = function (editor) { if (key === '_data') continue; if (cobj[key] instanceof Function) cobj[key] = cobj[key](args); } + pvobj[ii] = vobj = args.vobj; // 标记为_hide的属性不展示 if (cobj._hide) continue; if (!cobj._leaf) { @@ -193,7 +201,7 @@ editor_table_wrapper = function (editor) { // "['a']['b']" => "b" var shortField = field.split("']").slice(-2)[0].split("['").slice(-1)[0]; // 把长度超过 charlength 的字符改成 固定长度+...的形式 - shortField = (shortField.length < charlength ? shortField : shortField.slice(0, charlength) + '...'); + // shortField = (shortField.length < charlength ? shortField : shortField.slice(0, charlength) + '...'); // 完整的内容转义后供悬停查看 var commentHTMLescape = editor.util.HTMLescape(comment); @@ -298,6 +306,25 @@ editor_table_wrapper = function (editor) { } } + /** + * 当"显示完整注释"被按下时 + */ + editor_table.prototype.onCommentBtnClick = function (button) { + var tr = button.parentNode.parentNode; + printf(tr.children[1].getAttribute('title')); + } + + /** + * 当"编辑表格内容"被按下时 + */ + editor_table.prototype.onEditBtnClick = function (button) { + var tr = button.parentNode.parentNode; + var guid = tr.getAttribute('id'); + var cobj = JSON.parse(tr.children[1].getAttribute('cobj')); + if (cobj._type === 'event') editor_blockly.import(guid, { type: cobj._event }); + if (cobj._type === 'textarea') editor_multi.import(guid, { lint: cobj._lint, string: cobj._string }); + } + /** * 双击表格时 * 正常编辑: 尝试用事件编辑器或多行文本编辑器打开 @@ -337,12 +364,22 @@ editor_table_wrapper = function (editor) { editor_table.prototype.addfunc = function (guid, obj, commentObj, thisTr, input, field, cobj, modeNode) { editor_mode.onmode(editor_mode._ids[modeNode.getAttribute('id')]); - var mode = document.getElementById('editModeSelect').value; + var mode = editor.dom.editModeSelect.value; // 1.输入id - var newid = prompt('请输入新项的ID(仅公共事件支持中文ID)'); - if (newid == null || newid.length == 0) { - return; + var newid = '2'; + if (mode == 'loc') { + var ae = editor.currentFloorData.autoEvent[editor_mode.pos.x + ',' + editor_mode.pos.y]; + if (ae != null) { + var testid; + for (testid = 2; Object.hasOwnProperty.call(ae, testid); testid++); // 从3开始是因为comment中设置了始终显示012 + newid = testid + ''; + } + } else { + newid = prompt('请输入新项的ID(仅公共事件支持中文ID)'); + if (newid == null || newid.length == 0) { + return; + } } // 检查commentEvents diff --git a/_server/editor_ui.js b/_server/editor_ui.js new file mode 100644 index 00000000..589b19d0 --- /dev/null +++ b/_server/editor_ui.js @@ -0,0 +1,566 @@ +editor_ui_wrapper = function (editor) { + + + /** + * 根据鼠标点击, 得到从元素向上到body的所有id + */ + editor.uifunctions.getClickpath = function (e) { + //console.log(e); + var clickpath = []; + var getpath = function (e) { + var path = []; + var currentElem = e.target; + while (currentElem) { + path.push(currentElem); + currentElem = currentElem.parentElement; + } + if (path.indexOf(window) === -1 && path.indexOf(document) === -1) + path.push(document); + if (path.indexOf(window) === -1) + path.push(window); + return path; + } + getpath(e).forEach(function (node) { + if (!node.getAttribute) return; + var id_ = node.getAttribute('id'); + if (id_) { + if (['left', 'left1', 'left2', 'left3', 'left4', 'left5', 'left8', 'mobileview'].indexOf(id_) !== -1) clickpath.push('edit'); + clickpath.push(id_); + } + }); + return clickpath; + } + + /** + * editor.dom.body.onmousedown + * 检测鼠标点击, + * + 如果选中了绘图区域之外, 就保存地图 + * + 维护绘图区的菜单的隐藏 + * + 记录最后一次点击的id(主要为了数据区服务) + */ + editor.uifunctions.body_click = function (e) { + var clickpath = editor.uifunctions.getClickpath(e); + + var unselect = true; + for (var ii = 0, thisId; thisId = ['edit', 'tip', 'brushMod', 'brushMod2', 'brushMod3', 'layerMod', 'layerMod2', 'layerMod3', 'viewportButtons'][ii]; ii++) { + if (clickpath.indexOf(thisId) !== -1) { + unselect = false; + break; + } + } + if (unselect) { + if (clickpath.indexOf('eui') === -1) { + if (selectBox.isSelected()) { + editor_mode.onmode(''); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw (err) + } + ; printf('地图保存成功'); + }); + } + selectBox.isSelected(false); + editor.info = {}; + } + } + //editor.mode.onmode(''); + if (e.button != 2 && !editor.isMobile) { + editor.uifunctions.hideMidMenu(); + } + if (clickpath.indexOf('down') !== -1 && editor.isMobile && clickpath.indexOf('midMenu') === -1) { + editor.uifunctions.hideMidMenu(); + } + if (clickpath.length >= 2 && clickpath[0].indexOf('id_') === 0) { editor.lastClickId = clickpath[0] } + } + + /** + * editor.dom.body.onkeydown + * 绑定快捷键 + */ + editor.uifunctions.body_shortcut = function (e) { + + // UI预览 & 地图选点 + if (uievent && uievent.isOpen) { + e.preventDefault(); + if (e.keyCode == 27) uievent.close(); + else if (e.keyCode == 13) uievent.confirm(); + else if (e.keyCode == 87) uievent.move(0, -1) + else if (e.keyCode == 65) uievent.move(-1, 0) + else if (e.keyCode == 83) uievent.move(0, 1); + else if (e.keyCode == 68) uievent.move(1, 0); + return; + } + + // 监听Ctrl+S保存 + if (e.ctrlKey && e.keyCode == 83) { + e.preventDefault(); + if (editor_multi.id != "") { + editor_multi.confirm(); // 保存脚本编辑器 + } + else if (editor_blockly.id != "") { + editor_blockly.confirm(); // 保存事件编辑器 + } + else { + editor_mode.saveFloor(); + } + return; + } + + // 如果是开启事件/脚本编辑器状态,则忽略 + if (editor_multi.id != "" || editor_blockly.id != "") + return; + + // 禁止快捷键的默认行为 + if (e.ctrlKey && [89, 90, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57].indexOf(e.keyCode) !== -1) + e.preventDefault(); + if (e.altKey && [48, 49, 50, 51, 52, 53, 54, 55, 56, 57].indexOf(e.keyCode) !== -1) + e.preventDefault(); + //Ctrl+z 撤销上一步undo + if (e.keyCode == 90 && e.ctrlKey && editor.uivalues.preMapData && editor.uivalues.currDrawData.pos.length && selectBox.isSelected()) { + editor.map = JSON.parse(JSON.stringify(editor.uivalues.preMapData.map)); + editor.fgmap = JSON.parse(JSON.stringify(editor.uivalues.preMapData.fgmap)); + editor.bgmap = JSON.parse(JSON.stringify(editor.uivalues.preMapData.bgmap)); + editor.updateMap(); + editor.uivalues.reDo = JSON.parse(JSON.stringify(editor.uivalues.currDrawData)); + editor.uivalues.currDrawData = { pos: [], info: {} }; + editor.uivalues.preMapData = null; + return; + } + //Ctrl+y 重做一步redo + if (e.keyCode == 89 && e.ctrlKey && editor.uivalues.reDo && editor.uivalues.reDo.pos.length && selectBox.isSelected()) { + editor.uivalues.preMapData = JSON.parse(JSON.stringify({ map: editor.map, fgmap: editor.fgmap, bgmap: editor.bgmap })); + for (var j = 0; j < editor.uivalues.reDo.pos.length; j++) + editor.map[editor.uivalues.reDo.pos[j].y][editor.uivalues.reDo.pos[j].x] = JSON.parse(JSON.stringify(editor.uivalues.reDo.info)); + + editor.updateMap(); + editor.uivalues.currDrawData = JSON.parse(JSON.stringify(editor.uivalues.reDo)); + editor.uivalues.reDo = null; + return; + } + + // PGUP和PGDOWN切换楼层 + if (e.keyCode == 33 || e.keyCode == 34) { + e.preventDefault(); + var index = editor.core.floorIds.indexOf(editor.currentFloorId); + var nextIndex = index + (e.keyCode == 33 ? 1 : -1); + if (nextIndex >= 0 && nextIndex < editor.core.floorIds.length) { + var toId = editor.core.floorIds[nextIndex]; + editor_mode.onmode('nextChange'); + editor_mode.onmode('floor'); + document.getElementById('selectFloor').value = toId; + editor.changeFloor(toId); + } + return; + } + //ctrl + 0~9 切换到快捷图块 + if (e.ctrlKey && [48, 49, 50, 51, 52, 53, 54, 55, 56, 57].indexOf(e.keyCode) !== -1) { + editor.setSelectBoxFromInfo(JSON.parse(JSON.stringify(editor.uivalues.shortcut[e.keyCode] || 0))); + return; + } + //alt + 0~9 改变快捷图块 + if (e.altKey && [48, 49, 50, 51, 52, 53, 54, 55, 56, 57].indexOf(e.keyCode) !== -1) { + var infoToSave = JSON.stringify(editor.info || 0); + if (infoToSave == JSON.stringify({})) return; + editor.uivalues.shortcut[e.keyCode] = JSON.parse(infoToSave); + printf('已保存该快捷图块, ctrl + ' + (e.keyCode - 48) + ' 使用.') + core.setLocalStorage('shortcut', editor.uivalues.shortcut); + return; + } + var focusElement = document.activeElement; + if (!focusElement || focusElement.tagName.toLowerCase() == 'body') { + // Ctrl+C, Ctrl+X, Ctrl+V + if (e.ctrlKey && e.keyCode == 67 && !selectBox.isSelected()) { + e.preventDefault(); + editor.uivalues.copyedInfo = editor.copyFromPos(); + printf('该点事件已复制'); + return; + } + if (e.ctrlKey && e.keyCode == 88 && !selectBox.isSelected()) { + e.preventDefault(); + editor.uivalues.copyedInfo = editor.copyFromPos(); + editor.clearPos(true, null, function () { + printf('该点事件已剪切'); + }) + return; + } + if (e.ctrlKey && e.keyCode == 86 && !selectBox.isSelected()) { + e.preventDefault(); + if (!editor.uivalues.copyedInfo) { + printe("没有复制的事件"); + return; + } + editor.pasteToPos(editor.uivalues.copyedInfo); + editor.updateMap(); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw (err) + } + ; printf('粘贴事件成功'); + editor.drawPosSelection(); + }); + return; + } + // DELETE + if (e.keyCode == 46 && !selectBox.isSelected()) { + editor.clearPos(true); + return; + } + // ESC + if (e.keyCode == 27) { + if (selectBox.isSelected()) { + editor_mode.onmode(''); + editor.file.saveFloorFile(function (err) { + if (err) { + printe(err); + throw (err) + } + ; printf('地图保存成功'); + }); + } + selectBox.isSelected(false); + editor.info = {}; + return; + } + switch (e.keyCode) { + // WASD + case 87: editor.moveViewport(0, -1); break; + case 65: editor.moveViewport(-1, 0); break; + case 83: editor.moveViewport(0, 1); break; + case 68: editor.moveViewport(1, 0); break; + // Z~. + case 90: editor_mode.change('map'); break; // Z + case 88: editor_mode.change('loc'); break; // X + case 67: editor_mode.change('enemyitem'); break; // C + case 86: editor_mode.change('floor'); break; // V + case 66: editor_mode.change('tower'); break; // B + case 78: editor_mode.change('functions'); break; // N + case 77: editor_mode.change('appendpic'); break; // M + case 188: editor_mode.change('commonevent'); break; // , + case 190: editor_mode.change('plugins'); break; // . + // H + case 72: editor.uifunctions.showHelp(); break; + } + return; + } + } + + editor.uifunctions.showHelp = function () { + alert( + "快捷操作帮助:\n" + + "ESC / 点击空白处:自动保存当前修改" + + "WASD / 长按箭头:平移大地图\n" + + "PgUp, PgDn / 鼠标滚轮:上下切换楼层\n" + + "Z~.(键盘的第三排):快捷切换标签\n" + + "双击地图:选中对应点的素材\n" + + "右键地图:弹出菜单栏\n" + + "Alt+0~9:保存当前使用的图块\n" + + "Ctrl+0~9:选中保存的图块\n" + + "Ctrl+Z / Ctrl+Y:撤销/重做上次绘制\n" + + "Ctrl+S:事件与脚本编辑器的保存并退出\n" + + "双击事件编辑器:长文本编辑/脚本编辑/地图选点/UI绘制预览" + ); + } + + + // ------ UI预览 & 地图选点相关 ------ // + + var uievent = { + elements: {}, + values: {}, + isOpen: false, + mode: "" + }; + + uievent.elements.div = document.getElementById('uieventDiv'); + uievent.elements.title = document.getElementById('uieventTitle'); + uievent.elements.yes = document.getElementById('uieventYes'); + uievent.elements.no = document.getElementById('uieventNo'); + uievent.elements.selectBackground = document.getElementById('uieventBackground'); + uievent.elements.selectPoint = document.getElementById('selectPoint'); + uievent.elements.selectFloor = document.getElementById('selectPointFloor'); + uievent.elements.selectPointBox = document.getElementById('selectPointBox'); + uievent.elements.body = document.getElementById('uieventBody'); + uievent.elements.selectPointButtons = document.getElementById('selectPointButtons'); + uievent.elements.canvas = document.getElementById('uievent'); + uievent.elements.usedFlags = document.getElementById('uieventUsedFlags'); + uievent.elements.usedFlagList = document.getElementById('uieventUsedFlagList'); + + uievent.confirm = function () { + var callback = uievent.values.callback, floorId = uievent.values.floorId, + x = uievent.values.x, y = uievent.values.y; + uievent.close(); + if (callback) { + callback(floorId, x, y); + } + } + uievent.elements.yes.onclick = uievent.confirm; + + uievent.close = function () { + uievent.isOpen = false; + uievent.elements.div.style.display = 'none'; + uievent.values = {}; + } + uievent.elements.no.onclick = uievent.close; + + uievent.elements.selectBackground.onchange = function () { + uievent.drawPreviewUI(); + } + + uievent.drawPreviewUI = function () { + core.setAlpha('uievent', 1); + core.clearMap('uievent'); + + // 绘制UI + var background = uievent.elements.selectBackground.value; + if (background == 'thumbnail') { + core.drawThumbnail(editor.currentFloorId, null, {}, 'uievent'); + } + else { + core.fillRect('uievent', 0, 0, core.__PIXELS__, core.__PIXELS__, background); + } + + if (uievent.values.list instanceof Array) { + uievent.values.list.forEach(function (data) { + var type = data.type; + if (!type || !core.ui["_uievent_" + type]) return; + core.ui["_uievent_" + type](data); + }) + } + } + + uievent.previewUI = function (list) { + uievent.isOpen = true; + uievent.elements.div.style.display = 'block'; + uievent.mode = 'previewUI'; + uievent.elements.selectPoint.style.display = 'none'; + uievent.elements.yes.style.display = 'none'; + uievent.elements.title.innerText = 'UI绘制预览'; + uievent.elements.selectBackground.style.display = 'inline'; + uievent.elements.selectBackground.value = 'thumbnail'; + uievent.elements.selectFloor.style.display = 'none'; + uievent.elements.selectPointBox.style.display = 'none'; + uievent.elements.canvas.style.display = 'block'; + uievent.elements.usedFlags.style.display = 'none'; + uievent.elements.usedFlagList.style.display = 'none'; + uievent.elements.body.style.overflow = "hidden"; + + uievent.values.list = list; + uievent.drawPreviewUI(); + } + + uievent.selectPoint = function (floorId, x, y, hideFloor, callback) { + uievent.values.hideFloor = hideFloor; + uievent.values.callback = callback; + uievent.values.size = editor.isMobile ? window.innerWidth / core.__SIZE__ : 32; + uievent.elements.selectPointBox.style.width = (uievent.values.size - 6) + "px"; + uievent.elements.selectPointBox.style.height = (uievent.values.size - 6) + "px"; + + uievent.isOpen = true; + uievent.elements.div.style.display = 'block'; + uievent.mode = 'selectPoint'; + uievent.elements.selectPoint.style.display = 'block'; + uievent.elements.yes.style.display = 'inline'; + uievent.elements.selectBackground.style.display = 'none'; + uievent.elements.selectFloor.style.display = hideFloor ? 'none' : 'inline'; + uievent.elements.selectPointBox.style.display = 'block'; + uievent.elements.canvas.style.display = 'block'; + uievent.elements.usedFlags.style.display = 'none'; + uievent.elements.usedFlagList.style.display = 'none'; + uievent.elements.body.style.overflow = "hidden"; + + // Append children + var floors = ""; + core.floorIds.forEach(function (f) { + floors += ""; + }) + uievent.elements.selectFloor.innerHTML = floors; + + this.setPoint(floorId || editor.currentFloorId, core.calValue(x) || 0, core.calValue(y) || 0); + } + + uievent.updateSelectPoint = function (redraw) { + uievent.elements.title.innerText = '地图选点 (' + uievent.values.x + "," + uievent.values.y + ')'; + if (redraw) { + core.setAlpha('uievent', 1); + core.clearMap('uievent'); + core.drawThumbnail(uievent.values.floorId, null, null, + { + ctx: 'uievent', centerX: uievent.values.left + core.__HALF_SIZE__, + centerY: uievent.values.top + core.__HALF_SIZE__ + }); + } + uievent.elements.selectPointBox.style.left = uievent.values.size * (uievent.values.x - uievent.values.left) + "px"; + uievent.elements.selectPointBox.style.top = uievent.values.size * (uievent.values.y - uievent.values.top) + "px"; + } + + uievent.setPoint = function (floorId, x, y) { + if (core.floorIds.indexOf(floorId) == -1) floorId = editor.currentFloorId; + uievent.values.floorId = floorId; + uievent.elements.selectFloor.value = floorId; + uievent.values.x = x != null ? x : (uievent.values.x || 0); + uievent.values.y = y != null ? y : (uievent.values.y || 0); + uievent.values.width = core.floors[uievent.values.floorId].width || core.__SIZE__; + uievent.values.height = core.floors[uievent.values.floorId].height || core.__SIZE__; + uievent.values.left = core.clamp(uievent.values.x - core.__HALF_SIZE__, 0, uievent.values.width - core.__SIZE__); + uievent.values.top = core.clamp(uievent.values.y - core.__HALF_SIZE__, 0, uievent.values.height - core.__SIZE__); + uievent.updateSelectPoint(true); + } + + uievent.elements.selectFloor.onchange = function () { + uievent.setPoint(uievent.elements.selectFloor.value); + } + + uievent.elements.selectPointBox.onclick = function (e) { + e.stopPropagation(); + } + + uievent.elements.body.onclick = function (e) { + if (uievent.mode != 'selectPoint') return; + uievent.values.x = uievent.values.left + Math.floor(e.offsetX / uievent.values.size); + uievent.values.y = uievent.values.top + Math.floor(e.offsetY / uievent.values.size); + uievent.updateSelectPoint(false); + } + + uievent.move = function (dx, dy) { + if (uievent.mode != 'selectPoint') return; + uievent.values.left = core.clamp(uievent.values.left + dx, 0, uievent.values.width - core.__SIZE__); + uievent.values.top = core.clamp(uievent.values.top + dy, 0, uievent.values.height - core.__SIZE__); + this.updateSelectPoint(true); + }; + + (function () { + + var viewportButtons = uievent.elements.selectPointButtons; + var pressTimer = null; + for (var ii = 0, node; node = viewportButtons.children[ii]; ii++) { + (function (x, y) { + var move = function () { + uievent.move(x, y); + } + node.onmousedown = function () { + clearTimeout(pressTimer); + pressTimer = setTimeout(function () { + pressTimer = -1; + var f = function () { + if (pressTimer != null) { + move(); + setTimeout(f, 150); + } + } + f(); + }, 500); + }; + node.onmouseup = function () { + if (pressTimer > 0) { + clearTimeout(pressTimer); + move(); + } + pressTimer = null; + } + })([-1, 0, 0, 1][ii], [0, -1, 1, 0][ii]); + } + })(); + + uievent.elements.div.onmousewheel = function (e) { + if (uievent.mode != 'selectPoint' || uievent.values.hideFloor) return; + var index = core.floorIds.indexOf(uievent.values.floorId); + try { + if (e.wheelDelta) + index += Math.sign(e.wheelDelta); + else if (e.detail) + index += Math.sign(e.detail); + } catch (ee) { main.log(ee); } + index = core.clamp(index, 0, core.floorIds.length - 1); + uievent.setPoint(core.floorIds[index]); + } + + // ------ 搜索变量出现的位置,也放在uievent好了 ------ // + + uievent.searchUsedFlags = function () { + uievent.isOpen = true; + uievent.elements.div.style.display = 'block'; + uievent.mode = 'searchUsedFlags'; + uievent.elements.selectPoint.style.display = 'none'; + uievent.elements.yes.style.display = 'none'; + uievent.elements.title.innerText = '搜索变量'; + uievent.elements.selectBackground.style.display = 'none'; + uievent.elements.selectFloor.style.display = 'none'; + uievent.elements.selectPointBox.style.display = 'none'; + uievent.elements.canvas.style.display = 'none'; + uievent.elements.usedFlags.style.display = 'inline'; + uievent.elements.usedFlagList.style.display = 'block'; + uievent.elements.body.style.overflow = "auto"; + + // build flags + var html = ""; + Object.keys(editor.used_flags).sort().forEach(function (v) { + v = "flag:" + v; + html += ""; + }); + uievent.elements.usedFlags.innerHTML = html; + + uievent.doSearchUsedFlags(); + } + + uievent.doSearchUsedFlags = function () { + var flag = uievent.elements.usedFlags.value; + + var html = "

该变量出现的所有位置如下:

    "; + var list = uievent._searchUsedFlags(flag); + list.forEach(function (v) { + var x = "
  • "; + if (v[0] != null) x += v[0] + "层 "; + else x += "公共事件 "; + x += v[1]; + if (v[2] != null) x += " 的 (" + v[2] + ") 点"; + x += "
  • "; + html += x; + }); + html += "
"; + uievent.elements.usedFlagList.innerHTML = html; + } + + var hasUsedFlags = function (obj, flag) { + if (obj == null) return false; + if (typeof obj != 'string') return hasUsedFlags(JSON.stringify(obj), flag); + + var index = -1, length = flag.length; + while (true) { + index = obj.indexOf(flag, index + 1); + if (index < 0) return false; + if (!/^[a-zA-Z0-9_\u4E00-\u9FCC]$/.test(obj.charAt(index + length))) return true; + } + } + + uievent._searchUsedFlags = function (flag) { + var list = []; + var events = ["events", "autoEvent", "changeFloor", "afterBattle", "afterGetItem", "afterOpenDoor"] + for (var floorId in core.floors) { + var floor = core.floors[floorId]; + if (hasUsedFlags(floor.firstArrive, flag)) list.push([floorId, "firstArrive"]); + if (hasUsedFlags(floor.eachArrive, flag)) list.push([floorId, "eachArrive"]); + events.forEach(function (e) { + if (floor[e]) { + for (var loc in floor[e]) { + if (hasUsedFlags(floor[e][loc], flag)) { + list.push([floorId, e, loc]); + } + } + } + }); + } + // 公共事件 + if (core.events.commonEvent) { + for (var name in core.events.commonEvent) { + if (hasUsedFlags(core.events.commonEvent[name], flag)) + list.push([null, name]); + } + } + return list; + } + + editor.constructor.prototype.uievent=uievent; + +} \ No newline at end of file diff --git a/_server/editor_unsorted_1.js b/_server/editor_unsorted_1.js deleted file mode 100644 index 2ff64a08..00000000 --- a/_server/editor_unsorted_1.js +++ /dev/null @@ -1,957 +0,0 @@ -editor_unsorted_1_wrapper=function(editor){ - -editor.constructor.prototype.listen=function () { - document.body.onmousedown = function (e) { - //console.log(e); - var clickpath = []; - var getpath=function(e) { - var path = []; - var currentElem = e.target; - while (currentElem) { - path.push(currentElem); - currentElem = currentElem.parentElement; - } - if (path.indexOf(window) === -1 && path.indexOf(document) === -1) - path.push(document); - if (path.indexOf(window) === -1) - path.push(window); - return path; - } - getpath(e).forEach(function (node) { - if (!node.getAttribute) return; - var id_ = node.getAttribute('id'); - if (id_) { - if (['left', 'left1', 'left2', 'left3', 'left4', 'left5', 'left8', 'mobileview'].indexOf(id_) !== -1) clickpath.push('edit'); - clickpath.push(id_); - } - }); - - var unselect=true; - for(var ii=0,thisId;thisId=['edit','tip','brushMod','brushMod2','brushMod3','layerMod','layerMod2','layerMod3','viewportButtons'][ii];ii++){ - if (clickpath.indexOf(thisId) !== -1){ - unselect=false; - break; - } - } - if (unselect) { - if (clickpath.indexOf('eui') === -1) { - if (selectBox.isSelected()) { - editor_mode.onmode(''); - editor.file.saveFloorFile(function (err) { - if (err) { - printe(err); - throw(err) - } - ;printf('地图保存成功'); - }); - } - selectBox.isSelected(false); - editor.info = {}; - } - } - //editor.mode.onmode(''); - if (e.button!=2 && !editor.isMobile){ - editor.hideMidMenu(); - } - if (clickpath.indexOf('down') !== -1 && editor.isMobile && clickpath.indexOf('midMenu') === -1){ - editor.hideMidMenu(); - } - if(clickpath.length>=2 && clickpath[0].indexOf('id_')===0){editor.lastClickId=clickpath[0]} - } - - var eui=document.getElementById('eui'); - var uc = eui.getContext('2d'); - - function fillPos(pos) { - uc.fillStyle = '#' + ~~(Math.random() * 8) + ~~(Math.random() * 8) + ~~(Math.random() * 8); - uc.fillRect(pos.x * 32 + 12 - core.bigmap.offsetX, pos.y * 32 + 12 - core.bigmap.offsetY, 8, 8); - }//在格子内画一个随机色块 - - function eToLoc(e) { - var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft - var scrollTop = document.documentElement.scrollTop || document.body.scrollTop - var xx=e.clientX,yy=e.clientY - if(editor.isMobile){xx=e.touches[0].clientX,yy=e.touches[0].clientY} - editor.loc = { - 'x': scrollLeft + xx - mid.offsetLeft - mapEdit.offsetLeft, - 'y': scrollTop + yy - mid.offsetTop - mapEdit.offsetTop, - 'size': editor.isMobile?(32*innerWidth*0.96/core.__PIXELS__):32 - }; - return editor.loc; - }//返回可用的组件内坐标 - - function locToPos(loc, addViewportOffset) { - var offsetX=0, offsetY=0; - if (addViewportOffset){ - offsetX=core.bigmap.offsetX/32; - offsetY=core.bigmap.offsetY/32; - } - editor.pos = {'x': ~~(loc.x / loc.size)+offsetX, 'y': ~~(loc.y / loc.size)+offsetY} - return editor.pos; - } - - var holdingPath = 0; - var stepPostfix = null;//用于存放寻路检测的第一个点之后的后续移动 - - var mouseOutCheck = 2; - - function clear1() { - if (mouseOutCheck > 1) { - mouseOutCheck--; - setTimeout(clear1, 1000); - return; - } - holdingPath = 0; - stepPostfix = []; - uc.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__); - startPos = endPos = null; - }//用于鼠标移出canvas时的自动清除状态 - - eui.oncontextmenu=function(e){e.preventDefault()} - - eui.ondblclick = function(e) { - // 双击地图可以选中素材 - var loc = eToLoc(e); - var pos = locToPos(loc,true); - editor.setSelectBoxFromInfo(editor[editor.layerMod][pos.y][pos.x]); - return; - } - - var startPos=null, endPos=null; - eui.onmousedown = function (e) { - if (e.button==2){ - var loc = eToLoc(e); - var pos = locToPos(loc,true); - editor.showMidMenu(e.clientX,e.clientY); - return false; - } - if (!selectBox.isSelected()) { - var loc = eToLoc(e); - var pos = locToPos(loc,true); - editor_mode.onmode('nextChange'); - editor_mode.onmode('loc'); - //editor_mode.loc(); - //tip.whichShow(1); - tip.showHelp(6); - startPos = pos; - uc.strokeStyle = '#FF0000'; - uc.lineWidth = 3; - if(editor.isMobile)editor.showMidMenu(e.clientX,e.clientY); - return false; - } - - holdingPath = 1; - mouseOutCheck = 2; - setTimeout(clear1); - uc.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__); - var loc = eToLoc(e); - var pos = locToPos(loc,true); - stepPostfix = []; - stepPostfix.push(pos); - fillPos(pos); - return false; - } - - eui.onmousemove = function (e) { - if (!selectBox.isSelected()) { - if (startPos == null) return; - //tip.whichShow(1); - var loc = eToLoc(e); - var pos = locToPos(loc,true); - if (endPos != null && endPos.x == pos.x && endPos.y == pos.y) return; - if (endPos != null) { - uc.clearRect(Math.min(32 * startPos.x - core.bigmap.offsetX, 32 * endPos.x - core.bigmap.offsetX), - Math.min(32 * startPos.y - core.bigmap.offsetY, 32 * endPos.y - core.bigmap.offsetY), - (Math.abs(startPos.x - endPos.x) + 1) * 32, (Math.abs(startPos.y - endPos.y) + 1) * 32) - } - endPos = pos; - if (startPos != null) { - if (startPos.x != endPos.x || startPos.y != endPos.y) { - core.drawArrow('eui', - 32 * startPos.x + 16 - core.bigmap.offsetX, 32 * startPos.y + 16 - core.bigmap.offsetY, - 32 * endPos.x + 16 - core.bigmap.offsetX, 32 * endPos.y + 16 - core.bigmap.offsetY); - } - } - // editor_mode.onmode('nextChange'); - // editor_mode.onmode('loc'); - //editor_mode.loc(); - //tip.whichShow(1); - // tip.showHelp(6); - return false; - } - - if (holdingPath == 0) { - return false; - } - mouseOutCheck = 2; - var loc = eToLoc(e); - var pos = locToPos(loc,true); - var pos0 = stepPostfix[stepPostfix.length - 1] - var directionDistance = [pos.y - pos0.y, pos0.x - pos.x, pos0.y - pos.y, pos.x - pos0.x] - var max = 0, index = 4; - for (var i = 0; i < 4; i++) { - if (directionDistance[i] > max) { - index = i; - max = directionDistance[i]; - } - } - var pos = [{'x': 0, 'y': 1}, {'x': -1, 'y': 0}, {'x': 0, 'y': -1}, {'x': 1, 'y': 0}, false][index] - if (pos) { - pos.x += pos0.x; - pos.y += pos0.y; - stepPostfix.push(pos); - fillPos(pos); - } - return false; - } - - eui.onmouseup = function (e) { - if (!selectBox.isSelected()) { - //tip.whichShow(1); - // editor.movePos(startPos, endPos); - if (editor.layerMod == 'map') - editor.exchangePos(startPos, endPos); - else - editor.exchangeBgFg(startPos, endPos, editor.layerMod); - startPos = endPos = null; - uc.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__); - return false; - } - holdingPath = 0; - if (stepPostfix && stepPostfix.length) { - editor.preMapData = JSON.parse(JSON.stringify({map:editor.map,fgmap:editor.fgmap,bgmap:editor.bgmap})); - if(editor.brushMod!=='line'){ - var x0=stepPostfix[0].x; - var y0=stepPostfix[0].y; - var x1=stepPostfix[stepPostfix.length-1].x; - var y1=stepPostfix[stepPostfix.length-1].y; - if(x0>x1){x0^=x1;x1^=x0;x0^=x1;}//swap - if(y0>y1){y0^=y1;y1^=y0;y0^=y1;}//swap - stepPostfix=[]; - for(var jj=y0;jj<=y1;jj++){ - for(var ii=x0;ii<=x1;ii++){ - stepPostfix.push({x:ii,y:jj}) - } - } - } - currDrawData.pos = JSON.parse(JSON.stringify(stepPostfix)); - currDrawData.info = JSON.parse(JSON.stringify(editor.info)); - reDo = null; - // console.log(stepPostfix); - if(editor.brushMod==='tileset' && core.tilesets.indexOf(editor.info.images)!==-1){ - var imgWidth=~~(core.material.images.tilesets[editor.info.images].width/32); - var x0=stepPostfix[0].x; - var y0=stepPostfix[0].y; - var idnum=editor.info.idnum; - for (var ii = 0; ii < stepPostfix.length; ii++){ - if(stepPostfix[ii].y!=y0){ - y0++; - idnum+=imgWidth; - } - editor[editor.layerMod][stepPostfix[ii].y][stepPostfix[ii].x] = editor.ids[editor.indexs[idnum+stepPostfix[ii].x-x0]]; - } - } else { - for (var ii = 0; ii < stepPostfix.length; ii++) - editor[editor.layerMod][stepPostfix[ii].y][stepPostfix[ii].x] = editor.info; - } - // console.log(editor.map); - editor.updateMap(); - holdingPath = 0; - stepPostfix = []; - uc.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__); - } - return false; - } - - /* - document.getElementById('mid').onkeydown = function (e) { - console.log(e); - if (e.keyCode==37) { - editor.moveViewport(-1, 0); - } - if (e.keyCode==38) { - editor.moveViewport(0, -1); - } - if (e.keyCode==39) { - editor.moveViewport(1, 0); - } - if (e.keyCode==40) { - editor.moveViewport(0, 1); - } - } - */ - - document.getElementById('mid').onmousewheel = function (e) { - var wheel = function (direct) { - var index=editor.core.floorIds.indexOf(editor.currentFloorId); - var toId = editor.currentFloorId; - - if (direct>0 && index0) - toId = editor.core.floorIds[index-1]; - else return; - - editor_mode.onmode('nextChange'); - editor_mode.onmode('floor'); - document.getElementById('selectFloor').value = toId; - editor.changeFloor(toId); - } - - try { - if (e.wheelDelta) - wheel(Math.sign(e.wheelDelta)) - else if (e.detail) - wheel(Math.sign(e.detail)); - } - catch (ee) { - console.log(ee); - } - return false; - } - - editor.preMapData = null; - var currDrawData = { - pos: [], - info: {} - }; - var reDo = null; - var shortcut = core.getLocalStorage('shortcut',{48: 0, 49: 0, 50: 0, 51: 0, 52: 0, 53: 0, 54: 0, 55: 0, 56: 0, 57: 0}); - var copyedInfo = null; - document.body.onkeydown = function (e) { - - // UI预览 & 地图选点 - if (uievent && uievent.isOpen) { - e.preventDefault(); - if (e.keyCode == 27) uievent.close(); - else if (e.keyCode == 13) uievent.confirm(); - else if (e.keyCode==87) uievent.move(0,-1) - else if (e.keyCode==65) uievent.move(-1,0) - else if (e.keyCode==83) uievent.move(0,1); - else if (e.keyCode==68) uievent.move(1,0); - return; - } - - // 监听Ctrl+S保存 - if (e.ctrlKey && e.keyCode == 83) { - e.preventDefault(); - if (editor_multi.id != "") { - editor_multi.confirm(); // 保存脚本编辑器 - } - else if (editor_blockly.id != "") { - editor_blockly.confirm(); // 保存事件编辑器 - } - else { - editor_mode.saveFloor(); - } - return; - } - - // 如果是开启事件/脚本编辑器状态,则忽略 - if (editor_multi.id!="" || editor_blockly.id!="") - return; - - // 禁止快捷键的默认行为 - if (e.ctrlKey && [89, 90, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57].indexOf(e.keyCode) !== -1) - e.preventDefault(); - if (e.altKey && [48, 49, 50, 51, 52, 53, 54, 55, 56, 57].indexOf(e.keyCode) !== -1) - e.preventDefault(); - //Ctrl+z 撤销上一步undo - if (e.keyCode == 90 && e.ctrlKey && editor.preMapData && currDrawData.pos.length && selectBox.isSelected()) { - editor.map = JSON.parse(JSON.stringify(editor.preMapData.map)); - editor.fgmap = JSON.parse(JSON.stringify(editor.preMapData.fgmap)); - editor.bgmap = JSON.parse(JSON.stringify(editor.preMapData.bgmap)); - editor.updateMap(); - reDo = JSON.parse(JSON.stringify(currDrawData)); - currDrawData = {pos: [], info: {}}; - editor.preMapData = null; - return; - } - //Ctrl+y 重做一步redo - if (e.keyCode == 89 && e.ctrlKey && reDo && reDo.pos.length && selectBox.isSelected()) { - editor.preMapData = JSON.parse(JSON.stringify({map:editor.map,fgmap:editor.fgmap,bgmap:editor.bgmap})); - for (var j = 0; j < reDo.pos.length; j++) - editor.map[reDo.pos[j].y][reDo.pos[j].x] = JSON.parse(JSON.stringify(reDo.info)); - - editor.updateMap(); - currDrawData = JSON.parse(JSON.stringify(reDo)); - reDo = null; - return; - } - - // PGUP和PGDOWN切换楼层 - if (e.keyCode==33 || e.keyCode==34) { - e.preventDefault(); - var index=editor.core.floorIds.indexOf(editor.currentFloorId); - var nextIndex = index + (e.keyCode==33?1:-1); - if (nextIndex>=0 && nextIndex=iconLib.offsetHeight - scrollBarHeight) return; - var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft; - var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; - var loc = { - 'x': scrollLeft + e.clientX + iconLib.scrollLeft - right.offsetLeft - iconLib.offsetLeft, - 'y': scrollTop + e.clientY + iconLib.scrollTop - right.offsetTop - iconLib.offsetTop, - 'size': 32 - }; - editor.loc = loc; - var pos = locToPos(loc); - for (var spriter in editor.widthsX) { - if (pos.x >= editor.widthsX[spriter][1] && pos.x < editor.widthsX[spriter][2]) { - var ysize = spriter.endsWith('48') ? 48 : 32; - loc.ysize = ysize; - pos.images = editor.widthsX[spriter][0]; - pos.y = ~~(loc.y / loc.ysize); - if(!editor.folded && core.tilesets.indexOf(pos.images)==-1) pos.x = editor.widthsX[spriter][1]; - var autotiles = core.material.images['autotile']; - if (pos.images == 'autotile') { - var imNames = Object.keys(autotiles); - if ((pos.y + 1) * ysize > editor.widthsX[spriter][3]) - pos.y = ~~(editor.widthsX[spriter][3] / ysize) - 4; - else { - for (var i = 0; i < imNames.length; i++) { - if (pos.y >= 4 * i && pos.y < 4 * (i + 1)) { - pos.images = imNames[i]; - pos.y = 4 * i; - } - } - } - } - else { - var height = editor.widthsX[spriter][3], col = height / ysize; - if (editor.folded && core.tilesets.indexOf(pos.images)==-1) { - col = (pos.x == editor.widthsX[spriter][2] - 1) ? ((col - 1) % editor.foldPerCol + 1) : editor.foldPerCol; - } - if (spriter == 'terrains' && pos.x == editor.widthsX[spriter][1]) col += 2; - pos.y = Math.min(pos.y, col - 1); - } - - selectBox.isSelected(true); - // console.log(pos,core.material.images[pos.images].height) - dataSelection.style.left = pos.x * 32 + 'px'; - dataSelection.style.top = pos.y * ysize + 'px'; - dataSelection.style.height = ysize - 6 + 'px'; - - if (pos.x == 0 && pos.y == 0) { - // editor.info={idnum:0, id:'empty','images':'清除块', 'y':0}; - editor.info = 0; - } else if(pos.x == 0 && pos.y == 1){ - editor.info = editor.ids[editor.indexs[17]]; - } else { - if (autotiles[pos.images]) editor.info = {'images': pos.images, 'y': 0}; - else if (core.tilesets.indexOf(pos.images)!=-1) editor.info = {'images': pos.images, 'y': pos.y, 'x': pos.x-editor.widthsX[spriter][1]}; - else { - var y = pos.y; - if (editor.folded) { - y += editor.foldPerCol * (pos.x-editor.widthsX[spriter][1]); - } - if (pos.images == 'terrains' && pos.x == 0) y -= 2; - editor.info = {'images': pos.images, 'y': y} - } - - for (var ii = 0; ii < editor.ids.length; ii++) { - if ((core.tilesets.indexOf(pos.images)!=-1 && editor.info.images == editor.ids[ii].images - && editor.info.y == editor.ids[ii].y && editor.info.x == editor.ids[ii].x) - || (Object.prototype.hasOwnProperty.call(autotiles, pos.images) && editor.info.images == editor.ids[ii].id - && editor.info.y == editor.ids[ii].y) - || (core.tilesets.indexOf(pos.images)==-1 && editor.info.images == editor.ids[ii].images - && editor.info.y == editor.ids[ii].y ) - ) { - - editor.info = editor.ids[ii]; - break; - } - } - } - tip.infos(JSON.parse(JSON.stringify(editor.info))); - editor_mode.onmode('nextChange'); - editor_mode.onmode('enemyitem'); - //editor_mode.enemyitem(); - } - } - } - - var midMenu=document.getElementById('midMenu'); - midMenu.oncontextmenu=function(e){e.preventDefault()} - editor.lastRightButtonPos=[{x:0,y:0},{x:0,y:0}]; - editor.lastCopyedInfo = [null, null]; - editor.showMidMenu=function(x,y){ - editor.lastRightButtonPos=JSON.parse(JSON.stringify( - [editor.pos,editor.lastRightButtonPos[0]] - )); - // --- copy - editor.lastCopyedInfo = [editor.copyFromPos(), editor.lastCopyedInfo[0]]; - var locStr='('+editor.lastRightButtonPos[1].x+','+editor.lastRightButtonPos[1].y+')'; - var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft; - var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; - - // 检测是否是上下楼 - var thisevent = editor.map[editor.pos.y][editor.pos.x]; - if (thisevent.id=='upFloor') { - addFloorEvent.style.display='block'; - addFloorEvent.children[0].innerHTML='绑定上楼事件'; - } - else if (thisevent.id=='downFloor') { - addFloorEvent.style.display='block'; - addFloorEvent.children[0].innerHTML='绑定下楼事件'; - } - else if (['leftPortal','rightPortal','downPortal','upPortal'].indexOf(thisevent.id)>=0) { - addFloorEvent.style.display='block'; - addFloorEvent.children[0].innerHTML='绑定楼传事件'; - } - else addFloorEvent.style.display='none'; - - chooseThis.children[0].innerHTML='选中此点'+'('+editor.pos.x+','+editor.pos.y+')' - copyLoc.children[0].innerHTML='复制事件'+locStr+'到此处'; - moveLoc.children[0].innerHTML='交换事件'+locStr+'与此事件的位置'; - midMenu.style='top:'+(y+scrollTop)+'px;left:'+(x+scrollLeft)+'px;'; - } - editor.hideMidMenu=function(){ - if(editor.isMobile){ - setTimeout(function(){ - midMenu.style='display:none'; - },200) - } else { - midMenu.style='display:none'; - } - } - - var addFloorEvent = document.getElementById('addFloorEvent'); - addFloorEvent.onmousedown = function(e) { - editor.hideMidMenu(); - e.stopPropagation(); - var thisevent = editor.map[editor.pos.y][editor.pos.x]; - var loc = editor.pos.x+","+editor.pos.y; - if (thisevent.id=='upFloor') { - editor.currentFloorData.changeFloor[loc] = {"floorId": ":next", "stair": "downFloor"}; - } - else if (thisevent.id=='downFloor') { - editor.currentFloorData.changeFloor[loc] = {"floorId": ":before", "stair": "upFloor"}; - } - else if (thisevent.id=='leftPortal' || thisevent.id=='rightPortal') { - editor.currentFloorData.changeFloor[loc] = {"floorId": ":next", "stair": ":symmetry_x"} - } - else if (thisevent.id=='upPortal' || thisevent.id=='downPortal') { - editor.currentFloorData.changeFloor[loc] = {"floorId": ":next", "stair": ":symmetry_y"} - } - editor.file.saveFloorFile(function (err) { - if (err) { - printe(err); - throw(err) - } - editor.drawPosSelection(); - editor_mode.showMode('loc'); - printf('添加楼梯事件成功'); - }); - } - - var chooseThis = document.getElementById('chooseThis'); - chooseThis.onmousedown = function(e){ - editor.hideMidMenu(); - e.stopPropagation(); - selectBox.isSelected(false); - - editor_mode.onmode('nextChange'); - editor_mode.onmode('loc'); - //editor_mode.loc(); - //tip.whichShow(1); - if(editor.isMobile)editor.showdataarea(false); - } - - var chooseInRight = document.getElementById('chooseInRight'); - chooseInRight.onmousedown = function(e){ - editor.hideMidMenu(); - e.stopPropagation(); - var thisevent = editor[editor.layerMod][editor.pos.y][editor.pos.x]; - editor.setSelectBoxFromInfo(thisevent); - } - - var copyLoc = document.getElementById('copyLoc'); - copyLoc.onmousedown = function(e){ - editor.hideMidMenu(); - e.stopPropagation(); - editor.preMapData = null; - reDo = null; - editor_mode.onmode(''); - var now = editor.pos, last = editor.lastRightButtonPos[1]; - if (now.x == last.x && now.y == last.y) return; - editor.pasteToPos(editor.lastCopyedInfo[1]); - editor.updateMap(); - editor.file.saveFloorFile(function (err) { - if (err) { - printe(err); - throw(err) - } - ;printf('复制事件成功'); - editor.drawPosSelection(); - }); - } - - var moveLoc = document.getElementById('moveLoc'); - moveLoc.onmousedown = function(e){ - editor.hideMidMenu(); - e.stopPropagation(); - editor.preMapData = null; - reDo = null; - editor_mode.onmode(''); - editor.exchangePos(editor.pos, editor.lastRightButtonPos[1]); - } - - var clearEvent = document.getElementById('clearEvent'); - clearEvent.onmousedown = function (e) { - e.stopPropagation(); - reDo = null; - editor.clearPos(false); - } - - var clearLoc = document.getElementById('clearLoc'); - clearLoc.onmousedown = function(e){ - e.stopPropagation(); - reDo = null; - editor.clearPos(true); - } - - var brushMod=document.getElementById('brushMod'); - brushMod.onchange=function(){ - editor.brushMod=brushMod.value; - } - - var brushMod2=document.getElementById('brushMod2'); - if(brushMod2)brushMod2.onchange=function(){ - editor.brushMod=brushMod2.value; - } - - var brushMod3=document.getElementById('brushMod3'); - if(brushMod3) { - brushMod3.onchange=function(){ - // tip.showHelp(5) - tip.isSelectedBlock(false) - tip.msgs[11] = String('tileset贴图模式下可以按选中tileset素材,并在地图上拖动来一次绘制一个区域'); - tip.whichShow(12); - editor.brushMod=brushMod3.value; - } - } - - var bgc = document.getElementById('bg'), fgc = document.getElementById('fg'), - evc = document.getElementById('event'), ev2c = document.getElementById('event2'); - - var layerMod=document.getElementById('layerMod'); - layerMod.onchange=function(){ - editor.layerMod=layerMod.value; - [bgc,fgc,evc,ev2c].forEach(function (x) { - x.style.opacity = 1; - }); - - // 手机端.... - if (editor.isMobile) { - if (layerMod.value == 'bgmap') { - [fgc,evc,ev2c].forEach(function (x) { - x.style.opacity = 0.3; - }); - } - if (layerMod.value == 'fgmap') { - [bgc,evc,ev2c].forEach(function (x) { - x.style.opacity = 0.3; - }); - } - } - } - - var layerMod2=document.getElementById('layerMod2'); - if(layerMod2)layerMod2.onchange=function(){ - editor.layerMod=layerMod2.value; - [fgc,evc,ev2c].forEach(function (x) { - x.style.opacity = 0.3; - }); - bgc.style.opacity = 1; - } - - var layerMod3=document.getElementById('layerMod3'); - if(layerMod3)layerMod3.onchange=function(){ - editor.layerMod=layerMod3.value; - [bgc,evc,ev2c].forEach(function (x) { - x.style.opacity = 0.3; - }); - fgc.style.opacity = 1; - } - - var viewportButtons=document.getElementById('viewportButtons'); - var pressTimer = null; - for(var ii=0,node;node=viewportButtons.children[ii];ii++){ - (function(x,y){ - var move = function () { - editor.moveViewport(x, y); - } - node.onmousedown = function () { - clearTimeout(pressTimer); - pressTimer = setTimeout(function () { - pressTimer = -1; - var f = function () { - if (pressTimer != null) { - move(); - setTimeout(f, 150); - } - } - f(); - }, 500); - }; - node.onmouseup = function () { - if (pressTimer > 0) { - clearTimeout(pressTimer); - move(); - } - pressTimer = null; - } - })([-1,0,0,1][ii],[0,-1,1,0][ii]); - } -} - -editor.constructor.prototype.mobile_listen=function () { - if(!editor.isMobile)return; - - var mobileview=document.getElementById('mobileview'); - var editModeSelect=document.getElementById('editModeSelect'); - var mid=document.getElementById('mid'); - var right=document.getElementById('right'); - var mobileeditdata=document.getElementById('mobileeditdata'); - - - editor.showdataarea=function(callShowMode){ - mid.style='z-index:-1;opacity: 0;'; - right.style='z-index:-1;opacity: 0;'; - mobileeditdata.style=''; - if(callShowMode)editor.mode.showMode(editModeSelect.value); - editor.hideMidMenu(); - } - mobileview.children[0].onclick=function(){ - editor.showdataarea(true) - } - mobileview.children[1].onclick=function(){ - mid.style=''; - right.style='z-index:-1;opacity: 0;'; - mobileeditdata.style='z-index:-1;opacity: 0;'; - editor.lastClickId=''; - } - mobileview.children[3].onclick=function(){ - mid.style='z-index:-1;opacity: 0;'; - right.style=''; - mobileeditdata.style='z-index:-1;opacity: 0;'; - editor.lastClickId=''; - } - - - var gettrbyid=function(){ - if(!editor.lastClickId)return false; - thisTr = document.getElementById(editor.lastClickId); - input = thisTr.children[2].children[0].children[0]; - field = thisTr.children[0].getAttribute('title'); - cobj = JSON.parse(thisTr.children[1].getAttribute('cobj')); - return [thisTr,input,field,cobj]; - } - mobileeditdata.children[0].onclick=function(){ - var info = gettrbyid() - if(!info)return; - info[1].ondblclick() - } - mobileeditdata.children[1].onclick=function(){ - var info = gettrbyid() - if(!info)return; - printf(info[2]) - } - mobileeditdata.children[2].onclick=function(){ - var info = gettrbyid() - if(!info)return; - printf(info[0].children[1].getAttribute('title')) - } - - //===== - - document.body.ontouchstart=document.body.onmousedown; - document.body.onmousedown=null; - - - var eui=document.getElementById('eui'); - eui.ontouchstart=eui.onmousedown - eui.onmousedown=null - eui.ontouchmove=eui.onmousemove - eui.onmousemove=null - eui.ontouchend=eui.onmouseup - eui.onmouseup=null - - - var chooseThis = document.getElementById('chooseThis'); - chooseThis.ontouchstart=chooseThis.onmousedown - chooseThis.onmousedown=null - var chooseInRight = document.getElementById('chooseInRight'); - chooseInRight.ontouchstart=chooseInRight.onmousedown - chooseInRight.onmousedown=null - var copyLoc = document.getElementById('copyLoc'); - copyLoc.ontouchstart=copyLoc.onmousedown - copyLoc.onmousedown=null - var moveLoc = document.getElementById('moveLoc'); - moveLoc.ontouchstart=moveLoc.onmousedown - moveLoc.onmousedown=null - var clearLoc = document.getElementById('clearLoc'); - clearLoc.ontouchstart=clearLoc.onmousedown - clearLoc.onmousedown=null -} - -} \ No newline at end of file diff --git a/_server/editor_util.js b/_server/editor_util.js index 6f81a8c1..beb437db 100644 --- a/_server/editor_util.js +++ b/_server/editor_util.js @@ -161,10 +161,10 @@ editor_util_wrapper = function (editor) { return val != null && !(typeof val == 'number' && isNaN(val)); } - editor_util.prototype.checkCallback=function(callback){ + editor_util.prototype.checkCallback = function (callback) { if (!editor.util.isset(callback)) { editor.printe('未设置callback'); - throw('未设置callback') + throw ('未设置callback') } } diff --git a/_server/fs.js b/_server/fs.js index dddfbbec..7a74d647 100644 --- a/_server/fs.js +++ b/_server/fs.js @@ -132,7 +132,13 @@ var data = ''; data += 'name=' + path; postsomething(data, '/listFile', function (err, data) { - callback(err, JSON.parse(data)) + try { + data = JSON.parse(data); + } catch (e) { + err = "Invalid /listFile"; + data = null; + } + callback(err, data); }); return; } diff --git a/_server/img_md/view1.png b/_server/img_md/view1.png new file mode 100644 index 00000000..9cf0135c Binary files /dev/null and b/_server/img_md/view1.png differ diff --git a/_server/img_md/view2.png b/_server/img_md/view2.png new file mode 100644 index 00000000..8243840b Binary files /dev/null and b/_server/img_md/view2.png differ diff --git a/_server/img_md/view3.png b/_server/img_md/view3.png new file mode 100644 index 00000000..34daceac Binary files /dev/null and b/_server/img_md/view3.png differ diff --git a/_server/refactoring.md b/_server/refactoring.md index 8ea8c365..fbd0fff0 100644 --- a/_server/refactoring.md +++ b/_server/refactoring.md @@ -1,5 +1,7 @@ # 重构 +> 目前状态: 按功能分类已基本完成, 未完成file/game的重写 + 总体思路 + 按功能拆分文件 + 左侧页面模块化, 方便添加 @@ -12,16 +14,21 @@ editor_file之后是更改editor.map的储存方式, 现有的存对象的模式要在对象和数字间来回转换, 非常繁琐和奇怪 -再之后是把editor_unsorted_*.js整理清晰 - ## 文件结构 +(全部小写,必要时用下划线分割) + + [ ] editor_blockly 图块化事件编辑器 + [ ] editor_multi 多行文本编辑器 + [x] editor_table 处理表格的生成, 及其响应的事件, 从原editor\_mode中分离 + [ ] editor_file 调用fs.js编辑文件, 把原editor\_file模块化, 并且只负责文件写入 + [ ] editor_game 处理游戏数据, 导入为editor的数据, 编辑数据, 从原editor和editor_file中抽离. **只有此文件允许`\s(main|core)`形式的调用**(以及其初始化`editor_game_wrapper(editor, main, core);`) + [x] editor_util 生成guid/处理颜色 等函数, 从editor分离 ++ [ ] editor_listen 处理界面上的按钮/下拉框点击等用户的操作与功能函数的绑定, 维护editor.dom, unsorted_1/2中的绑定挪到此处, 其中的函数内容, 分类放在其他文件 ++ [ ] editor_mappanel 与地图区相关的功能, <-unsorted_1/2/3 ++ [ ] editor_datapanel 与数据区相关的功能, <-unsorted_1/2/3 ++ [ ] editor_materialpanel 与素材区相关的功能, <-unsorted_1/2/3 ++ [ ] editor_ui 维护printe/printf/tip, 以及之后可能的窗口化, ui事件中没有具体到前三个区中的函数 <-unsorted_1/2/3 + [ ] editor 执行初始化流程加组合各组件 + [ ] 原editor_mode 移除 + [x] 原vm 移除 @@ -72,9 +79,11 @@ editor: { + editor.widthX特别不直观 ++ ? 编辑器使用可拖拽和调大小的窗口做容器 + ## 功能改进 -+ [ ] 大地图 ++ [x] 大地图 在切换时, 每次都回到最左上->每个楼层记录一个位置 四个箭头支持长按 ? 滚动条 @@ -87,12 +96,12 @@ editor: { + [ ] ? 简洁的事件方块注册 `editor.registerEvent('log',[['test','Int','测试',0],['floorId','Idstring','楼层','MT0']])` -+ [ ] 一个显示所有快捷键的文本 ++ [x] 一个显示所有快捷键的文本 -+ [ ] 更多快捷键 ++ [x] 更多快捷键 【全塔属性】、【楼层属性】等常用的编辑栏切换 -+ [ ] ? 地图编辑优化 ++ [x] ? 地图编辑优化 常用的地图编辑快捷键/命令:复制ctrl+c、粘贴ctrl+v、(复制可绑定为现在的“选中xx位置事件” 粘贴为复制xx事件到此处),撤回ctrl+z、取消撤回ctrl+y 可以按住拖动图块与事件。 @@ -103,18 +112,20 @@ editor: { + [x] 修改系统的触发器(下拉菜单增加新项) 在编辑器修改`comment.js`:现场发readFile请求读文件,然后开脚本编辑器进行编辑 -+ [ ] ? 删除注册项/修改图块ID ++ [x] ? 删除注册项/修改图块ID + [ ] ? 怪物和道具也能像其他类型那样查看“图块信息”(而不只是具体的怪物属性) -+ [ ] 素材区自动换列 ++ [x] 素材区自动换列 怪物或道具太多时, 按照每100个进行拆分新开列来显示 -+ [ ] 多帧素材只显示第一帧 ++ [x] 多帧素材只显示第一帧 -+ [ ] `显示文章`以及`选项`等方块, 把`标题`和`图像`从字符串提取出填回相应的空 ++ [x] `显示文章`以及`选项`等方块, 把`标题`和`图像`从字符串提取出填回相应的空 -+ [ ] blockly中某些需要选点的填空, 增加按钮, 点击后从缩略图中点击位置 ++ [x] blockly中某些需要选点的填空, 增加按钮, 点击后从缩略图中点击位置 + ++ [ ] 插件编写增加判定,如果保存时框内不是以 "function\s*()" 开头(也就是用户直接写的脚本),则自动添加一个 function() { } 将代码包装起来。 ## 左侧页面模式 diff --git a/_server/table/comment.js b/_server/table/comment.js index abbf3b7d..6e549b88 100644 --- a/_server/table/comment.js +++ b/_server/table/comment.js @@ -258,11 +258,12 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { }, "_data": "该图块是否不可通行;true代表不可通行,false代表可通行,null代表使用系统缺省值" }, - "canBreak": { + "script": { "_leaf": true, - "_type": "checkbox", - "_bool": "bool", - "_data": "该图块是否可被破墙或地震" + "_type": "textarea", + "_string": true, + "_lint": true, + "_data": "触碰到该图块时自动执行的脚本内容;此脚本会在该点的触发器执行前执行" }, "cannotOut": { "_leaf": true, @@ -276,6 +277,12 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_range": "thiseval==null||(thiseval instanceof Array)", "_data": "该图块的不可入方向\n可以在这里定义不能朝哪个方向进入该图块,可以达到悬崖之类的效果\n例如 [\"down\"] 代表不能从该图块的上方点朝向下进入此图块\n此值对背景层、事件层、前景层上的图块均有效" }, + "canBreak": { + "_leaf": true, + "_type": "checkbox", + "_bool": "bool", + "_data": "该图块是否可被破墙或地震" + }, "animate": { "_leaf": true, "_type": "textarea", @@ -435,6 +442,24 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_event": "event", "_data": "该点的可能事件列表,可以双击进入事件编辑器。" }, + "autoEvent": { + "_type": "object", + "_leaf": false, + "_action": function (args) { + args.vobj=args.vobj||{}; + for(var ii=0;ii<2;ii++){ + args.vobj[ii]=args.vobj[ii]||null; + } + }, + "_data": function (key) { + return { + "_leaf": true, + "_type": "event", + "_event": "autoEvent", + "_data": "自动事件页" + } + } + }, "changeFloor": { "_leaf": true, "_type": "event", @@ -464,7 +489,7 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_type": "textarea", "_range": "thiseval==null||(thiseval instanceof Array)", "_data": "该点不可通行的方向 \n 可以在这里定义该点不能前往哪个方向,可以达到悬崖之类的效果\n例如 [\"up\", \"left\"] 代表该点不能往上和左走" - } + }, } } } @@ -496,6 +521,7 @@ var comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "afterBattle": {}, "afterGetItem": {}, "afterOpenDoor": {}, + "autoEvent": {}, "cannotMove": {} } } diff --git a/_server/table/functions.comment.js b/_server/table/functions.comment.js index 44396901..55dc8d1c 100644 --- a/_server/table/functions.comment.js +++ b/_server/table/functions.comment.js @@ -94,6 +94,12 @@ var functions_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_lint": true, "_data": "炸弹事件" }, + "afterPassNet": { + "_leaf": true, + "_type": "textarea", + "_lint": true, + "_data": "经过特殊地形后的事件" + }, "canUseQuickShop": { "_leaf": true, "_type": "textarea", diff --git a/_server/table/plugins.comment.js b/_server/table/plugins.comment.js index fc4f5144..3d436a06 100644 --- a/_server/table/plugins.comment.js +++ b/_server/table/plugins.comment.js @@ -20,6 +20,18 @@ var plugins_comment_c456ea59_6018_45ef_8bcc_211a24c627dc = { "_range": "typeof(thiseval)=='string' || thiseval==null", "_data": "绘制灯光效果" }, + "drawItemShop": { + "_leaf": true, + "_type": "textarea", + "_range": "typeof(thiseval)=='string' || thiseval==null", + "_data": "道具商店插件" + }, + "smoothCamera": { + "_leaf": true, + "_type": "textarea", + "_range": "typeof(thiseval)=='string' || thiseval==null", + "_data": "平滑移动镜头效果" + }, } if (obj[key]) return obj[key]; return { diff --git a/editor-mobile.html b/editor-mobile.html index b8d2e0eb..fe371abd 100644 --- a/editor-mobile.html +++ b/editor-mobile.html @@ -76,6 +76,7 @@ +

色相: @@ -101,7 +102,7 @@

-

地图选点     +

地图选点      

0,0

@@ -195,6 +196,7 @@ -->
- + + + + 开启中文名替换 @@ -236,6 +241,7 @@ 语法检查 +
@@ -336,7 +342,7 @@
-

地图选点     +

地图选点      

0,0

@@ -191,6 +192,7 @@ --> - - -
+ + + + + 开启中文名替换 @@ -232,6 +236,7 @@ 语法检查 +
@@ -357,7 +362,7 @@