diff --git a/_docs/event.md b/_docs/event.md index 7cd66565..64a598d1 100644 --- a/_docs/event.md +++ b/_docs/event.md @@ -1840,6 +1840,7 @@ UI绘制事件。 - `alpha`:不透明度,必须是0到1之间的浮点数 - `align`:对齐方式,只能是`left`, `center`, `right`,分别代表左对齐,居中和右对齐 - `baseline`:基准线,只能是`top`, `middle`, `alphabetic`, `bottom`,分别代表顶部,居中,标准值和底部。 +- `z`:画布的z值,必须是正整数。初始创建时画布的z值是135。请注意,闪烁光标所在画布的z值永远比该画布大1。 ### fillText:绘制文本 diff --git a/_docs/personalization.md b/_docs/personalization.md index 72de08cd..5b71c8c3 100644 --- a/_docs/personalization.md +++ b/_docs/personalization.md @@ -22,6 +22,7 @@ HTML5魔塔是使用画布(canvas)来绘制,存在若干个图层,它们 - paint**[D]**:绘图层;主要用来进行绘图模式。(z-index: 95) - curtain:色调层;用来控制当前楼层的画面色调 (z-index: 125) - image1\~50**[D]**:图片层;用来绘制图片等操作。(z-index: 100+code, 101~150) +- uievent**[D]**:自定义UI绘制层;用来进行自定义UI绘制等操作。(z-index:135,可以通过事件设置该值) - ui:UI层;用来绘制一切UI窗口,如剧情文本、怪物手册、楼传器、系统菜单等等 (z-index: 140) - data:数据层;用来绘制一些顶层的或更新比较快的数据,如左上角的提示,战斗界面中数据的变化等等。 (z-index: 170) @@ -29,6 +30,8 @@ HTML5魔塔是使用画布(canvas)来绘制,存在若干个图层,它们 而,色调层的z-index是25,ui层的z-index是140;因此,图片编号在1~24的将被色调层遮挡,25~40的将被ui层遮挡,41~50的将遮挡UI层。 +uievent层为自定义UI绘制所在的层,其z值初始是135,可以通过事件设置;自定义绘制的闪烁光标所在层的z值永远比该值大1。 + ### 动态创建canvas 从V2.5.3开始,可以在H5样板中任意动态创建canvas并进行使用。 diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index 2d0a5276..3627e6c1 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -109,7 +109,7 @@ return code; */; shopsub - : '商店 id' IdString '标题' EvalString '图标' IdString BGNL? Newline '快捷商店栏中名称' EvalString '共用times' Bool BGNL? Newline '未开启状态则不显示在列表中' Bool BGNL? NewLine '使用' ShopUse_List '消耗' EvalString BGNL? Newline '显示文字' EvalString BGNL? Newline shopChoices+ BEND + : '商店 id' IdString '标题' EvalString '图标' IdString BGNL? Newline '快捷商店栏中名称' EvalString '共用times' Bool BGNL? Newline '未开启状态则不显示在列表中' Bool BGNL? Newline '使用' ShopUse_List '消耗' EvalString BGNL? Newline '显示文字' EvalString BGNL? Newline shopChoices+ BEND /* shopsub @@ -224,7 +224,7 @@ changeFloor_m /* changeFloor_m tooltip : 楼梯, 传送门, 如果目标楼层有多个楼梯, 写upFloor或downFloor可能会导致到达的楼梯不确定, 这时候请使用loc方式来指定具体的点位置 helpUrl : https://h5mota.com/games/template/_docs/#/element?id=%e8%b7%af%e9%9a%9c%ef%bc%8c%e6%a5%bc%e6%a2%af%ef%bc%8c%e4%bc%a0%e9%80%81%e9%97%a8 -default : [null,"MT1",null,0,0,null,500,null] +default : [null,"MTx",null,0,0,null,500,null] var toFloorId = IdString_0; if (Floor_List_0!='floorId') toFloorId = Floor_List_0; var loc = ', "loc": ['+Number_0+', '+Number_1+']'; @@ -702,7 +702,7 @@ return code; */; insert_2_s - : '插入事件' 'x' PosString ',' 'y' PosString Event_List? '楼层' IdString? '参数列表' EvalString? ENewline + : '插入事件' 'x' PosString ',' 'y' PosString Event_List? '楼层' IdString? '参数列表' EvalString? Newline /* insert_2_s @@ -1068,7 +1068,7 @@ changeFloor_s /* changeFloor_s tooltip : changeFloor: 楼层切换,动画时间可不填 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=changefloor%EF%BC%9A%E6%A5%BC%E5%B1%82%E5%88%87%E6%8D%A2 -default : ["MT1","0","0",null,500] +default : ["MTx","0","0",null,500] colour : this.dataColor DirectionEx_List_0 = DirectionEx_List_0 && (', "direction": "'+DirectionEx_List_0+'"'); Int_0 = (Int_0!=='') ?(', "time": '+Int_0):''; @@ -1917,13 +1917,13 @@ return code; setAttribute_s - : '设置画布属性' '字体' EvalString? '填充样式' EvalString? Colour '边框样式' EvalString? Colour BGNL? '线宽度' EvalString? '不透明度' EvalString? '对齐' TextAlign_List '基准线' TextBaseline_List Newline + : '设置画布属性' '字体' EvalString? '填充样式' EvalString? Colour '边框样式' EvalString? Colour BGNL? '线宽度' EvalString? '不透明度' EvalString? '对齐' TextAlign_List '基准线' TextBaseline_List 'z值' EvalString? Newline /* setAttribute_s tooltip : setAttribute:设置画布属性 helpUrl : https://h5mota.com/games/template/_docs/#/event?id=setAttribute%ef%bc%9a%e8%ae%be%e7%bd%ae%e7%94%bb%e5%b8%83%e5%b1%9e%e6%80%a7 colour : this.subColor -default : ["","",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',"","",null,null] +default : ["","",'rgba(255,255,255,1)',"",'rgba(255,255,255,1)',"","",null,null,""] TextAlign_List_0 = TextAlign_List_0==='null'?'': ', "align": "'+TextAlign_List_0+'"'; TextBaseline_List_0 = TextBaseline_List_0==='null'?'': ', "baseline": "'+TextBaseline_List_0+'"'; var colorRe = MotaActionFunctions.pattern.colorRe; @@ -1949,7 +1949,11 @@ if (EvalString_4) { if (isNaN(f) || f<0 || f>1) throw new Error('不透明度必须是0到1的浮点数或不填'); EvalString_4 = ', "alpha": '+EvalString_4; } -var code = '{"type": "setAttribute"'+EvalString_0+EvalString_1+EvalString_2+EvalString_3+EvalString_4+TextAlign_List_0+TextBaseline_List_0+'},\n'; +if (EvalString_5) { + if (!/^\d+$/.test(EvalString_5))throw new Error('z值必须是整数或不填'); + EvalString_5 = ', "z": '+EvalString_5; +} +var code = '{"type": "setAttribute"'+EvalString_0+EvalString_1+EvalString_2+EvalString_3+EvalString_4+TextAlign_List_0+TextBaseline_List_0+EvalString_5+'},\n'; return code; */; @@ -2509,8 +2513,8 @@ Bool: 'TRUE' Int : '0' | [1-9][0-9]* ; // no leading zeros Letter_List - : 'A'|'B'|'C'|'D'|'E'|'F' - /*Letter_List ['A','B','C','D','E','F']*/; + : 'A'|'B'|'C'|'D'|'E'|'F'|'G'|'H'|'I'|'J'|'K'|'L'|'M'|'N'|'O'|'P'|'Q'|'R'|'S'|'T'|'U'|'V'|'W'|'X'|'Y'|'Z' + /*Letter_List ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']*/; Number @@ -2739,12 +2743,19 @@ ActionParser.prototype.parseAction = function() { this.next = data.next; return; case "text": // 文字/对话 - this.next = MotaActionBlocks['text_0_s'].xmlText([ - this.EvalString(data.text),this.next]); + var info = this.getTitleAndPosition(data.text); + if (info[0] || info[1] || info[2]) { + this.next = MotaActionBlocks['text_1_s'].xmlText([ + info[0], info[1], info[2], info[3], this.next]); + } + else { + this.next = MotaActionBlocks['text_0_s'].xmlText([info[3],this.next]); + } break; case "autoText": // 自动剧情文本 + var info = this.getTitleAndPosition(data.text); this.next = MotaActionBlocks['autoText_s'].xmlText([ - '','','',data.time,this.EvalString(data.text),this.next]); + info[0],info[1],info[2],data.time,info[3],this.next]); break; case "scrollText": this.next = MotaActionBlocks['scrollText_s'].xmlText([ @@ -3119,8 +3130,10 @@ ActionParser.prototype.parseAction = function() { text_choices=MotaActionBlocks['choicesContext'].xmlText([ choice.text,choice.icon,choice.color,'rgba('+choice.color+')',this.insertActionList(choice.action),text_choices]); } + if (!this.isset(data.text)) data.text = ''; + var info = this.getTitleAndPosition(data.text); this.next = MotaActionBlocks['choices_s'].xmlText([ - this.isset(data.text)?this.EvalString(data.text):null,'','',text_choices,this.next]); + info[3],info[0],info[1],text_choices,this.next]); break; case "while": // 前置条件循环处理 this.next = MotaActionBlocks['while_s'].xmlText([ @@ -3234,7 +3247,7 @@ ActionParser.prototype.parseAction = function() { data.strokeStyle=this.Colour(data.strokeStyle); this.next = MotaActionBlocks['setAttribute_s'].xmlText([ data.font,data.fillStyle,'rgba('+data.fillStyle+')',data.strokeStyle,'rgba('+data.strokeStyle+')', - data.lineWidth,data.alpha,data.align,data.baseline,this.next]); + data.lineWidth,data.alpha,data.align,data.baseline,data.z,this.next]); break; case "fillText": // 绘制一行文本 data.style = this.Colour(data.style); @@ -3387,12 +3400,26 @@ ActionParser.prototype.EvalString = function(EvalString) { return EvalString.split('\b').join('\\b').split('\t').join('\\t').split('\n').join('\\n'); } +ActionParser.prototype.getTitleAndPosition = function (string) { + string = this.EvalString(string); + var title = '', icon = '', position = ''; + string = string.replace(/\\t\[(([^\],]+),)?([^\],]+)\]/g, function (s0, s1, s2, s3) { + if (s3) title = s3; + if (s2) { icon = s3; title = s2; } + if (icon.endsWith('.png')) { title += "," + icon; icon = ''; } + return ""; + }).replace(/\\b\[(.*?)\]/g, function (s0, s1) { + position = s1; return ""; + }); + return [title, icon, position, string]; +} + ActionParser.prototype.Colour = function(color) { return color?JSON.stringify(color).slice(1,-1):null; } ActionParser.prototype.tryToUseEvFlag_e = function(defaultType, args, isShadow, comment) { - var match=/^switch:([A-F])$/.exec(args[0]) + var match=/^switch:([A-Z])$/.exec(args[0]) if(match){ args[0]=match[1] return MotaActionBlocks['evFlag_e'].xmlText(args, isShadow, comment); @@ -3468,10 +3495,11 @@ MotaActionFunctions.StepString_pre = function(StepString){ } MotaActionFunctions.pattern=MotaActionFunctions.pattern||{}; -MotaActionFunctions.pattern.id=/^flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)$/; +MotaActionFunctions.pattern.id=/^(flag|global):([a-zA-Z0-9_\u4E00-\u9FCC]+)$/; MotaActionFunctions.pattern.id2=/^flag:([a-zA-Z0-9_\u4E00-\u9FCC]+),flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)$/; MotaActionFunctions.pattern.idWithoutFlag=/^[0-9a-zA-Z_][0-9a-zA-Z_\-:]*$/; MotaActionFunctions.pattern.colorRe=/^(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(,0(\.\d+)?|,1)?$/; MotaActionFunctions.pattern.fontRe=/^(italic )?(bold )?(\d+)px ([a-zA-Z0-9_\u4E00-\u9FCC]+)$/; + */ \ No newline at end of file diff --git a/_server/css/editor.css b/_server/css/editor.css index e053cafd..c12e3f07 100644 --- a/_server/css/editor.css +++ b/_server/css/editor.css @@ -262,10 +262,6 @@ body { position: absolute; } -.egameCanvas { - position: absolute; -} - .gameCanvas { position: absolute; } @@ -287,6 +283,13 @@ body { 0 0 0 3px #000; } +#iconExpandBtn { + position: absolute; + left: 10px; + bottom: 30px; + display: none; +} + .warnText { color: #D50000; font-weight: 700; diff --git a/_server/css/editor_mobile.css b/_server/css/editor_mobile.css index ef6d2f72..c37142e1 100644 --- a/_server/css/editor_mobile.css +++ b/_server/css/editor_mobile.css @@ -247,10 +247,6 @@ body { position: absolute; } -.egameCanvas { - position: absolute; -} - .gameCanvas { position: absolute; } @@ -272,6 +268,13 @@ body { 0 0 0 3px #000; } +#iconExpandBtn { + position: absolute; + left: 10px; + bottom: 30px; + display: none; +} + .warnText { color: #D50000; font-weight: 700; @@ -433,7 +436,7 @@ div.row .rowtd .rowtext{ font: normal 2.5vw Arial, sans-serif; list-style: none; margin: 0; - padding: 4px 7em 4px 28px; + padding: 4px 7em 4px 4px; white-space: nowrap; /* padding-left: 12px; */ diff --git a/_server/editor.js b/_server/editor.js index aa5a21ec..683200a2 100644 --- a/_server/editor.js +++ b/_server/editor.js @@ -144,14 +144,15 @@ editor.prototype.changeFloor = function (floorId, callback) { } editor.preMapData = null; core.changeFloor(floorId, null, {"x": 0, "y": 0, "direction": "up"}, null, function () { - core.bigmap.offsetX=0; - core.bigmap.offsetY=0; - editor.moveViewport(0,0); - editor.game.fetchMapFromCore(); editor.updateMap(); editor_mode.floor(); editor.drawEventBlock(); + + editor.viewportLoc = editor.viewportLoc || {}; + var loc = editor.viewportLoc[floorId] || [], x = loc[0] || 0, y = loc[1] || 0; + editor.setViewport(x, y); + if (callback) callback(); }); } @@ -256,14 +257,19 @@ editor.prototype.updateMap = function () { } -editor.prototype.moveViewport=function(x,y){ - core.bigmap.offsetX = core.clamp(core.bigmap.offsetX+32*x, 0, 32*core.bigmap.width-core.__PIXELS__); - core.bigmap.offsetY = core.clamp(core.bigmap.offsetY+32*y, 0, 32*core.bigmap.height-core.__PIXELS__); +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.currentFloorId] = [core.bigmap.offsetX, core.bigmap.offsetY]; core.control.updateViewport(); editor.buildMark(); editor.drawPosSelection(); } +editor.prototype.moveViewport=function(x,y){ + editor.setViewport(core.bigmap.offsetX+32*x, core.bigmap.offsetY+32*y); +} + /////////// 界面交互相关 /////////// editor.prototype.drawInitData = function (icons) { @@ -272,6 +278,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; // var imgNames = Object.keys(images); //还是固定顺序吧; var imgNames = ["terrains", "animates", "enemys", "enemy48", "items", "npcs", "npc48", "autotile"]; @@ -282,20 +291,21 @@ editor.prototype.drawInitData = function (icons) { for (var im in autotiles) { tempy += autotiles[im].height; } - editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + 3 * 32) / 32, tempy]; - sumWidth += 3 * 32; + var tempx = editor.folded ? 32 : 3 * 32; + editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + tempx) / 32, tempy]; + sumWidth += tempx; maxHeight = Math.max(maxHeight, tempy); continue; } - if (img == 'terrains') { - editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + images[img].width) / 32, images[img].height + 32*2] - sumWidth += images[img].width; - maxHeight = Math.max(maxHeight, images[img].height + 32*2); - continue; + var width = images[img].width, height = images[img].height, mh = height; + if (editor.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; } - editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + images[img].width) / 32, images[img].height]; - sumWidth += images[img].width; - maxHeight = Math.max(maxHeight, images[img].height); + editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + width) / 32, height]; + sumWidth += width; + maxHeight = Math.max(maxHeight, mh + 64); } var tilesets = images.tilesets; for (var ii in core.tilesets) { @@ -312,82 +322,75 @@ editor.prototype.drawInitData = function (icons) { if (fullWidth > edata.width) edata.style.width = (edata.width = fullWidth) / ratio + 'px'; edata.style.height = (edata.height = fullHeight) / ratio + 'px'; */ + var iconImages = document.getElementById('iconImages'); iconImages.style.width = (iconImages.width = fullWidth) / ratio + 'px'; iconImages.style.height = (iconImages.height = fullHeight) / ratio + 'px'; - var dc = {drawImage:function(){ - var image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight; - var a=Array.prototype.slice.call(arguments) - if(arguments.length==3){ - // [image, dx, dy]=arguments - // [sx, sy, sWidth, sHeight, dWidth, dHeight]=[0,0,image.width,image.height,image.width,image.height] - image=a[0] - a=[a[0],0,0,image.width,image.height,a[1],a[2],image.width,image.height] - } - if(arguments.length==5){ - // [image, dx, dy, dWidth, dHeight]=arguments - // [sx, sy, sWidth, sHeight]=[0,0,image.width,image.height] - image=a[0] - a=[a[0],0,0,image.width,image.height,a[1],a[2],a[3],a[4]] - } - if(arguments.length==9){ - // [image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight]=arguments - } - image=a[0]; - sx=a[1]; - sy=a[2]; - sWidth=a[3]; - sHeight=a[4]; - dx=a[5]; - dy=a[6]; - dWidth=a[7]; - dHeight=a[8]; - //放弃对 dWidth, dHeight 的支持, 始终画一样大的 - var dimg=new Image() - dimg.src = image.src; - dimg.style.clip=['rect(',sy,'px,',sx+sWidth,'px,',sy+sHeight,'px,',sx,'px)'].join('') - dimg.style.top=dy-sy+'px' - dimg.style.left=dx-sx+'px' - dimg.width=image.width/ratio - dimg.height=image.height/ratio - iconImages.appendChild(dimg) - }} - // var dc = edata.getContext('2d'); - var nowx = 0; - var nowy = 0; + var drawImage = function (image, x, y) { + image.style.left = x + 'px'; + image.style.top = y + 'px'; + iconImages.appendChild(image); + } + + var nowx = 0, nowy = 0; for (var ii = 0; ii < imgNames.length; ii++) { var img = imgNames[ii]; if (img == 'terrains') { - (function(image,dc,nowx){ + (function(image,nowx){ if (image.complete) { - dc.drawImage(image, nowx, 32); + drawImage(image, nowx, 32); core.material.images.airwall = image; delete(editor.airwallImg); } else image.onload = function () { - dc.drawImage(image, nowx, 32); + drawImage(image, nowx, 32); core.material.images.airwall = image; delete(editor.airwallImg); editor.updateMap(); } - })(editor.airwallImg,dc,nowx); - dc.drawImage(images[img], nowx, 32*2); - nowx += images[img].width; + })(editor.airwallImg,nowx); + if (editor.folded) { + // --- 单列 & 折行 + var subimgs = core.splitImage(images[img], 32, editor.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); + nowx += 32; + } + } + else { + drawImage(images[img], nowx, 32*2); + nowx += images[img].width; + } continue; } if (img == 'autotile') { var autotiles = images[img]; + var tempx = editor.folded ? 32 : 96; for (var im in autotiles) { - dc.drawImage(autotiles[im], 0, 0, 96, 128, nowx, nowy, 96, 128); + var subimgs = core.splitImage(autotiles[im], tempx, autotiles[im].height); + drawImage(subimgs[0], nowx, nowy); nowy += autotiles[im].height; } - nowx += 3 * 32; + nowx += tempx; continue; } - dc.drawImage(images[img], nowx, 0) - nowx += images[img].width; + if (editor.folded) { + // --- 单列 & 折行 + var per_height = img.endsWith('48') ? 48 : 32; + var subimgs = core.splitImage(images[img], 32, editor.foldPerCol * per_height); + var frames = images[img].width / 32; + for (var i = 0; i < subimgs.length; i+=frames) { + drawImage(subimgs[i], nowx, 0); + nowx += 32; + } + } + else { + drawImage(images[img], nowx, 0); + nowx += images[img].width; + } } for (var ii in core.tilesets) { var img = core.tilesets[ii]; - dc.drawImage(tilesets[img], nowx, 0) + drawImage(tilesets[img], nowx, 0); nowx += tilesets[img].width; } //editor.mapInit(); @@ -461,8 +464,12 @@ editor.prototype.setSelectBoxFromInfo=function(thisevent){ pos.x=editor.widthsX[thisevent.images][1]; pos.y=thisevent.y; if(thisevent.x)pos.x+=thisevent.x; - if(thisevent.images=='terrains')pos.y+=2; 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(pos.x == 0) pos.y+=2; } var dataSelection = document.getElementById('dataSelection'); dataSelection.style.left = pos.x * 32 + 'px'; @@ -484,4 +491,69 @@ 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.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 = new editor(); \ No newline at end of file diff --git a/_server/editor_blockly.js b/_server/editor_blockly.js index b236153f..83e56a95 100644 --- a/_server/editor_blockly.js +++ b/_server/editor_blockly.js @@ -745,7 +745,7 @@ function omitedcheckUpdateFunction(event) { "closeDoor_s": ["PosString_0", "PosString_1"], "show_s": ["EvalString_0", "EvalString_1", "IdString_0"], "hide_s": ["EvalString_0", "EvalString_1", "IdString_0"], - "setBlock_s": ["PosString_0", "PosString_1"], + "setBlock_s": ["PosString_0", "PosString_1", "IdString_0"], "move_s": ["PosString_0", "PosString_1"], "jump_s": ["PosString_2", "PosString_3"], // 跳跃暂时只考虑终点 "showBgFgMap_s": ["EvalString_0", "EvalString_1", "IdString_0"], @@ -775,6 +775,10 @@ function omitedcheckUpdateFunction(event) { } block.setFieldValue(xv+"", arr[0]); block.setFieldValue(yv+"", arr[1]); + if (block.type == 'changeFloor_m') { + block.setFieldValue("floorId", "Floor_List_0"); + block.setFieldValue("loc", "Stair_List_0"); + } }); } diff --git a/_server/editor_file_unsorted.js b/_server/editor_file_unsorted.js index c6206fe9..eec1667a 100644 --- a/_server/editor_file_unsorted.js +++ b/_server/editor_file_unsorted.js @@ -58,8 +58,8 @@ editor_file = function (editor, callback) { title = "主塔 "+name+" 层"; } - var width = parseInt(document.getElementById('newMapsWidth').value); - var height = parseInt(document.getElementById('newMapsHeight').value); + var width = parseInt(document.getElementById('newMapWidth').value); + var height = parseInt(document.getElementById('newMapHeight').value); var row = [], map = []; for (var i=0;i0) { - var toId = editor.core.floorIds[index-1]; + var nextIndex = index + (e.keyCode==33?1:-1); + if (nextIndex>=0 && nextIndex=((core.__SIZE__==13?630:655) - scrollBarHeight)) return; + if (!editor.isMobile && e.clientY>=iconLib.offsetHeight - scrollBarHeight) return; var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft; var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; var loc = { @@ -433,11 +542,11 @@ editor.constructor.prototype.listen=function () { 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.indexOf('48') === -1 ? 32 : 48; + var ysize = spriter.endsWith('48') ? 48 : 32; loc.ysize = ysize; pos.images = editor.widthsX[spriter][0]; pos.y = ~~(loc.y / loc.ysize); - if(core.tilesets.indexOf(pos.images)==-1)pos.x = editor.widthsX[spriter][1]; + 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); @@ -451,8 +560,15 @@ editor.constructor.prototype.listen=function () { } } } - } else if ((pos.y + 1) * ysize > editor.widthsX[spriter][3]) - pos.y = ~~(editor.widthsX[spriter][3] / ysize) - 1; + } + 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) @@ -466,10 +582,16 @@ editor.constructor.prototype.listen=function () { } else if(pos.x == 0 && pos.y == 1){ editor.info = editor.ids[editor.indexs[17]]; } else { - if (Object.prototype.hasOwnProperty.call(autotiles, pos.images)) editor.info = {'images': pos.images, 'y': 0}; - else if (pos.images == 'terrains') editor.info = {'images': pos.images, 'y': pos.y - 2}; + 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 editor.info = {'images': pos.images, 'y': pos.y}; + 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 @@ -496,10 +618,13 @@ editor.constructor.prototype.listen=function () { 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; @@ -585,8 +710,6 @@ editor.constructor.prototype.listen=function () { editor.setSelectBoxFromInfo(thisevent); } - var fields = Object.keys(editor.file.comment._data.floors._data.loc._data); - var copyLoc = document.getElementById('copyLoc'); copyLoc.onmousedown = function(e){ editor.hideMidMenu(); @@ -594,22 +717,10 @@ editor.constructor.prototype.listen=function () { editor.preMapData = null; reDo = null; editor_mode.onmode(''); - var now = editor.pos; - var last = editor.lastRightButtonPos[1]; - var lastevent = editor.map[last.y][last.x]; - var lastinfo = 0; - if(lastevent==0){ - lastinfo = 0; - } else { - var ids=editor.indexs[lastevent.idnum]; - ids=ids[0]?ids[0]:ids; - lastinfo=editor.ids[ids]; - } - editor.map[now.y][now.x]=lastinfo; + 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(); - fields.forEach(function(v){ - editor.currentFloorData[v][now.x+','+now.y]=editor.currentFloorData[v][last.x+','+last.y] - }) editor.file.saveFloorFile(function (err) { if (err) { printe(err); @@ -626,36 +737,12 @@ editor.constructor.prototype.listen=function () { e.stopPropagation(); editor.preMapData = null; reDo = null; - var thisevent = editor.map[editor.pos.y][editor.pos.x]; - if(thisevent==0){ - editor.info = 0; - } else { - var ids=editor.indexs[thisevent.idnum]; - ids=ids[0]?ids[0]:ids; - editor.info=editor.ids[ids]; - } editor_mode.onmode(''); - var now = editor.pos; - var last = editor.lastRightButtonPos[1]; - - var lastevent = editor.map[last.y][last.x]; - var lastinfo = 0; - if(lastevent==0){ - lastinfo = 0; - } else { - var ids=editor.indexs[lastevent.idnum]; - ids=ids[0]?ids[0]:ids; - lastinfo=editor.ids[ids]; - } - editor.map[last.y][last.x]=editor.info; - editor.map[now.y][now.x]=lastinfo; + var now = editor.pos, last = editor.lastRightButtonPos[1]; + if (now.x == last.x && now.y == last.y) return; + editor.pasteToPos(editor.lastCopyedInfo[1], now); + editor.pasteToPos(editor.lastCopyedInfo[0], last); editor.updateMap(); - - fields.forEach(function(v){ - var temp_atsfcytaf=editor.currentFloorData[v][now.x+','+now.y]; - editor.currentFloorData[v][now.x+','+now.y]=editor.currentFloorData[v][last.x+','+last.y]; - editor.currentFloorData[v][last.x+','+last.y]=temp_atsfcytaf; - }) editor.file.saveFloorFile(function (err) { if (err) { printe(err); @@ -666,39 +753,18 @@ editor.constructor.prototype.listen=function () { }); } - var _clearPoint = function (clearPoint) { - editor.hideMidMenu(); - editor.preMapData = null; - reDo = null; - editor.info = 0; - editor_mode.onmode(''); - var now = editor.pos; - if (clearPoint) - editor.map[now.y][now.x]=editor.info; - editor.updateMap(); - fields.forEach(function(v){ - delete editor.currentFloorData[v][now.x+','+now.y]; - }) - editor.file.saveFloorFile(function (err) { - if (err) { - printe(err); - throw(err) - } - ;printf(clearPoint?'清空该点和事件成功':'只清空该点事件成功'); - editor.drawPosSelection(); - }); - } - var clearEvent = document.getElementById('clearEvent'); clearEvent.onmousedown = function (e) { e.stopPropagation(); - _clearPoint(false); + reDo = null; + editor.clearPos(false); } var clearLoc = document.getElementById('clearLoc'); clearLoc.onmousedown = function(e){ e.stopPropagation(); - _clearPoint(true); + reDo = null; + editor.clearPos(true); } var brushMod=document.getElementById('brushMod'); @@ -712,8 +778,11 @@ editor.constructor.prototype.listen=function () { } var brushMod3=document.getElementById('brushMod3'); - if(brushMod3)brushMod3.onchange=function(){ - editor.brushMod=brushMod3.value; + if(brushMod3) { + brushMod3.onchange=function(){ + tip.showHelp(5) + editor.brushMod=brushMod3.value; + } } var bgc = document.getElementById('bg'), fgc = document.getElementById('fg'), @@ -760,10 +829,31 @@ editor.constructor.prototype.listen=function () { } var viewportButtons=document.getElementById('viewportButtons'); + var pressTimer = null; for(var ii=0,node;node=viewportButtons.children[ii];ii++){ (function(x,y){ - node.onclick=function(){ - editor.moveViewport(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]); } diff --git a/_server/editor_unsorted_2.js b/_server/editor_unsorted_2.js index 17b8092e..042b617b 100644 --- a/_server/editor_unsorted_2.js +++ b/_server/editor_unsorted_2.js @@ -568,11 +568,14 @@ editor_unsorted_2_wrapper=function(editor_mode){ }); } + 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.onmode('nextChange'); - editor_mode.onmode(editModeSelect.value); - if(editor.isMobile)editor.showdataarea(false); + editor_mode.change(editModeSelect.value); } editor_mode.checkUnique = function (thiseval) { diff --git a/_server/editor_unsorted_3.js b/_server/editor_unsorted_3.js index 5be3711f..11e40ea2 100644 --- a/_server/editor_unsorted_3.js +++ b/_server/editor_unsorted_3.js @@ -206,13 +206,20 @@ printf = function (str_, type) { printe = function (str_) { printf(str_, 'error') } -tip_in_showMode = [ - '涉及图片的更改需要F5刷新浏览器来生效', - '文本域可以通过双击,在文本编辑器或事件编辑器中编辑', - '事件编辑器中的显示文本和自定义脚本的方块也可以双击', - "画出的地图要点击\"保存地图\"才会写入到文件中", -]; tip=document.getElementById('tip') +tip.showHelp = function(value) { + var tips = [ + '表格的文本域可以双击进行编辑', + '双击地图可以选中素材,右键可以弹出菜单', + '双击事件编辑器的图块可以进行长文本编辑/脚本编辑/地图选点/UI绘制预览等操作', + 'ESC或点击空白处可以自动保存当前修改', + 'H键可以打开操作帮助哦', + 'tileset贴图模式下可以按选中tileset素材,并在地图上拖动来一次绘制一个区域', + '可以拖动地图上的图块和事件,或按Ctrl+C, Ctrl+X和Ctrl+V进行复制,剪切和粘贴' + ]; + if (value == null) value = Math.floor(Math.random() * tips.length); + printf('tips: ' + tips[value]) +} tip._infos= {} tip.infos=function(value){ if(value!=null){ @@ -511,23 +518,40 @@ uievent.move = function (dx, dy) { 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); -} +}; -uievent.elements.selectPointButtons.children[0].onclick = function () { - uievent.move(-1, 0); -} +(function() { -uievent.elements.selectPointButtons.children[1].onclick = function () { - uievent.move(0, -1); -} - -uievent.elements.selectPointButtons.children[2].onclick = function () { - uievent.move(0, 1); -} - -uievent.elements.selectPointButtons.children[3].onclick = function () { - uievent.move(1, 0); -} + 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; diff --git a/editor-mobile.html b/editor-mobile.html index d76491b1..b398d1ec 100644 --- a/editor-mobile.html +++ b/editor-mobile.html @@ -297,7 +297,7 @@ - + @@ -308,6 +308,7 @@ +
diff --git a/editor.html b/editor.html index 0a0f0d96..43200cfe 100644 --- a/editor.html +++ b/editor.html @@ -293,7 +293,7 @@ - +
@@ -352,6 +352,7 @@
+