From 3d315ed8f65dcff5425630d71357ba5846e36caa Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Mon, 15 Jun 2020 20:10:40 +0800 Subject: [PATCH] Multiline input --- _server/MotaAction.g4 | 88 +++++++++++++++------------- _server/MotaActionParser.js | 22 +++++-- _server/editor_blockly.js | 23 ++++++-- _server/thirdparty/caret-position.js | 3 + 4 files changed, 84 insertions(+), 52 deletions(-) diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index d38f21e1..bddd4771 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -126,13 +126,13 @@ return code; */; shopsub - : '商店 id' IdString '标题' EvalString? '图像' IdString? BGNL? Newline '文字' EvalString? BGNL? Newline '快捷名称' EvalString '未开启不显示' Bool '不可预览' Bool BGNL? Newline shopChoices+ BEND + : '商店 id' IdString '标题' EvalString? '图像' IdString? BGNL? Newline '文字' EvalString_Multi? BGNL? Newline '快捷名称' EvalString '未开启不显示' Bool '不可预览' Bool BGNL? Newline shopChoices+ BEND /* shopsub tooltip : 全局商店 helpUrl : /_docs/#/instruction -doubleclicktext : EvalString_1 +doubleclicktext : EvalString_Multi_0 allIds : ['IdString_1'] default : ["shop1","贪婪之神","moneyShop","勇敢的武士啊, 给我${20+2*flag:shop1}金币就可以:","金币商店",false,false] var title=''; @@ -145,8 +145,8 @@ if (EvalString_0==''){ } var code = { 'id': IdString_0, - 'text': title+EvalString_1, - 'textInList': EvalString_2, + 'text': title+EvalString_Multi_0, + 'textInList': EvalString_1, 'mustEnable': Bool_0, 'disablePreview': Bool_1, 'choices': 'choices_asdfefw' @@ -723,28 +723,28 @@ action ; text_0_s - : '显示文章' ':' EvalString Newline + : '显示文章' ':' EvalString_Multi Newline /* text_0_s tooltip : text:显示一段文字(剧情) helpUrl : /_docs/#/instruction -doubleclicktext : EvalString_0 -default : ["欢迎使用事件编辑器(双击方块进入多行编辑)"] -var code = '"'+EvalString_0+'",\n'; +doubleclicktext : EvalString_Multi_0 +default : ["欢迎使用事件编辑器(回车直接多行编辑)"] +var code = '"'+EvalString_Multi_0+'",\n'; return code; */; text_1_s - : '标题' EvalString? '图像' EvalString? '对话框效果' EvalString? ':' EvalString Newline + : '标题' EvalString? '图像' EvalString? '对话框效果' EvalString? BGNL? Newline EvalString_Multi Newline /* text_1_s tooltip : text:显示一段文字(剧情),选项较多请右键点击帮助 helpUrl : /_docs/#/instruction -doubleclicktext : EvalString_3 +doubleclicktext : EvalString_Multi_0 allIds : ['EvalString_1'] -default : ["小妖精","fairy","","欢迎使用事件编辑器(双击方块进入多行编辑)"] +default : ["小妖精","fairy","","欢迎使用事件编辑器(回车直接多行编辑)"] var title=''; if (EvalString_0==''){ if (EvalString_1=='' )title=''; @@ -757,20 +757,20 @@ if(EvalString_2 && !(/^(up|center|down|hero|this)(,(hero|null|\d+,\d+|\d+))?$/.t throw new Error('对话框效果的用法请右键点击帮助'); } EvalString_2 = EvalString_2 && ('\\b['+EvalString_2+']'); -var code = '"'+title+EvalString_2+EvalString_3+'",\n'; +var code = '"'+title+EvalString_2+EvalString_Multi_0+'",\n'; return code; */; text_2_s - : '标题' EvalString? '图像' EvalString? '对话框效果' EvalString? ':' EvalString BGNL? Newline textDrawingList* Newline + : '标题' EvalString? '图像' EvalString? '对话框效果' EvalString? BGNL? Newline EvalString_Multi BGNL? Newline textDrawingList* Newline /* text_2_s tooltip : text:显示一段文字(剧情),选项较多请右键点击帮助 helpUrl : /_docs/#/instruction -doubleclicktext : EvalString_3 +doubleclicktext : EvalString_Multi_0 allIds : ['EvalString_1'] -default : ["小妖精","fairy","","欢迎使用事件编辑器(双击方块进入多行编辑)",null] +default : ["小妖精","fairy","","欢迎使用事件编辑器(回车直接多行编辑)",null] var title=''; if (EvalString_0==''){ if (EvalString_1=='' )title=''; @@ -783,7 +783,7 @@ if(EvalString_2 && !(/^(up|center|down|hero|this)(,(hero|null|\d+,\d+|\d+))?$/.t throw new Error('对话框效果的用法请右键点击帮助'); } EvalString_2 = EvalString_2 && ('\\b['+EvalString_2+']'); -var code = '"'+title+EvalString_2+textDrawingList_0.replace(/\s/g, '')+EvalString_3+'",\n'; +var code = '"'+title+EvalString_2+textDrawingList_0.replace(/\s/g, '')+EvalString_Multi_0+'",\n'; return code; */; @@ -841,27 +841,27 @@ return code; */; comment_s - : '添加注释' ':' EvalString Newline + : '添加注释' ':' EvalString_Multi Newline /* comment_s tooltip : comment:添加一段会被游戏跳过的注释内容 helpUrl : /_docs/#/instruction -doubleclicktext : EvalString_0 +doubleclicktext : EvalString_Multi_0 default : ["可以在这里写添加任何注释内容"] colour : this.commentColor -var code = '{"type": "comment", "text": "'+EvalString_0+'"},\n'; +var code = '{"type": "comment", "text": "'+EvalString_Multi_0+'"},\n'; return code; */; autoText_s - : '自动剧情文本: 标题' EvalString? '图像' EvalString? '对话框效果' EvalString? '时间' Int BGNL? EvalString Newline + : '自动剧情文本: 标题' EvalString? '图像' EvalString? '对话框效果' EvalString? '时间' Int BGNL? EvalString_Multi Newline /* autoText_s tooltip : autoText:自动剧情文本,用户无法跳过自动剧情文本,大段剧情文本请添加“是否跳过剧情”的提示 helpUrl : /_docs/#/instruction -doubleclicktext : EvalString_2 +doubleclicktext : EvalString_Multi_0 allIds : ['EvalString_1'] default : ["小妖精","fairy","",3000,"用户无法跳过自动剧情文本,大段剧情文本请添加“是否跳过剧情”的提示"] var title=''; @@ -876,21 +876,21 @@ if(EvalString_2 && !(/^(up|center|down|hero|this)(,(hero|null|\d+,\d+|\d+))?$/.t throw new Error('对话框效果的用法请右键点击帮助'); } EvalString_2 = EvalString_2 && ('\\b['+EvalString_2+']'); -var code = '{"type": "autoText", "text": "'+title+EvalString_2+EvalString_3+'", "time": '+Int_0+'},\n'; +var code = '{"type": "autoText", "text": "'+title+EvalString_2+EvalString_Multi_0+'", "time": '+Int_0+'},\n'; return code; */; scrollText_s - : '滚动剧情文本:' '时间' Int '行距' Number '不等待执行完毕' Bool? BGNL? EvalString Newline + : '滚动剧情文本:' '时间' Int '行距' Number '不等待执行完毕' Bool? BGNL? EvalString_Multi Newline /* scrollText_s tooltip : scrollText:滚动剧情文本,将从下到上进行滚动显示。 helpUrl : /_docs/#/instruction -doubleclicktext : EvalString_0 +doubleclicktext : EvalString_Multi_0 default : [5000,1.4,false,"时间是总时间,可以使用setText事件来控制字体、颜色、大小、偏移量等"] Bool_0 = Bool_0?', "async": true':''; -var code = '{"type": "scrollText", "text": "'+EvalString_0+'"'+Bool_0+', "time" :'+Int_0+', "lineHeight": '+Number_0+'},\n'; +var code = '{"type": "scrollText", "text": "'+EvalString_Multi_0+'"'+Bool_0+', "time" :'+Int_0+', "lineHeight": '+Number_0+'},\n'; return code; */; @@ -1862,14 +1862,14 @@ return code; */; showTextImage_s - : '显示图片化文本' '文本内容' EvalString BGNL? + : '显示图片化文本' EvalString_Multi BGNL? '图片编号' Int '起点像素' 'x' PosString 'y' PosString '行距' Number '翻转' Reverse_List '不透明度' Number '时间' Int '不等待执行完毕' Bool Newline /* showTextImage_s tooltip : showTextImage:显示图片化文本 helpUrl : /_docs/#/instruction -doubleclicktext : EvalString_0 +doubleclicktext : EvalString_Multi_0 colour : this.printColor default : ["可以使用setText事件来控制字体、颜色、大小、偏移量等",1,"0","0",1.4,"null",1,0,false] if(Int_0<=0 || Int_0>50) throw new Error('图片编号在1~50之间'); @@ -1877,7 +1877,7 @@ if (Reverse_List_0 && Reverse_List_0 != 'null') { Reverse_List_0 = ', "reverse": "' + Reverse_List_0 + '"'; } else Reverse_List_0 = ''; var async = Bool_0?', "async": true':''; -var code = '{"type": "showTextImage", "code": '+Int_0+', "text": "'+EvalString_0+'", "loc": ['+PosString_0+','+PosString_1+'], "lineHeight": '+Number_0+Reverse_List_0+', "opacity": '+Number_1+', "time": '+Int_1+async+'},\n'; +var code = '{"type": "showTextImage", "code": '+Int_0+', "text": "'+EvalString_Multi_0+'", "loc": ['+PosString_0+','+PosString_1+'], "lineHeight": '+Number_0+Reverse_List_0+', "opacity": '+Number_1+', "time": '+Int_1+async+'},\n'; return code; */; @@ -2371,27 +2371,27 @@ return code; */; choices_s - : '选项' ':' EvalString? BGNL? '标题' EvalString? '图像' IdString? '超时毫秒数' Int BGNL? Newline choicesContext+ BEND Newline + : '选项' ':' EvalString_Multi? BGNL? '标题' EvalString? '图像' IdString? '超时毫秒数' Int BGNL? Newline choicesContext+ BEND Newline /* choices_s tooltip : choices: 给用户提供选项 helpUrl : /_docs/#/instruction -doubleclicktext : EvalString_0 +doubleclicktext : EvalString_Multi_0 default : ["","流浪者","trader",0] allIds : ['IdString_0'] var title=''; -if (EvalString_1==''){ +if (EvalString_0==''){ if (IdString_0=='')title=''; else title='\\t['+IdString_0+']'; } else { - if (IdString_0=='')title='\\t['+EvalString_1+']'; - else title='\\t['+EvalString_1+','+IdString_0+']'; + if (IdString_0=='')title='\\t['+EvalString_0+']'; + else title='\\t['+EvalString_0+','+IdString_0+']'; } -EvalString_0 = title+EvalString_0; -EvalString_0 = EvalString_0 ?(', "text": "'+EvalString_0+'"'):''; +EvalString_Multi_0 = title+EvalString_Multi_0; +EvalString_Multi_0 = EvalString_Multi_0 ?(', "text": "'+EvalString_Multi_0+'"'):''; Int_0 = Int_0 ? (', "timeout": '+Int_0) : ''; -var code = ['{"type": "choices"',EvalString_0,Int_0,', "choices": [\n', +var code = ['{"type": "choices"',EvalString_Multi_0,Int_0,', "choices": [\n', choicesContext_0, ']},\n'].join(''); return code; @@ -2415,16 +2415,16 @@ return code; */; confirm_s - : '显示确认框' ':' EvalString '超时毫秒数' Int BGNL? '确定的场合' ':' '(默认选中' Bool ')' BGNL? Newline action+ '取消的场合' ':' BGNL? Newline action+ BEND Newline + : '显示确认框' ':' EvalString_Multi '超时毫秒数' Int BGNL? '确定的场合' ':' '(默认选中' Bool ')' BGNL? Newline action+ '取消的场合' ':' BGNL? Newline action+ BEND Newline /* confirm_s tooltip : 弹出确认框 helpUrl : /_docs/#/instruction default : ["确认要xxx吗?",0,false] -doubleclicktext : EvalString_0 +doubleclicktext : EvalString_Multi_0 Bool_0 = Bool_0?', "default": true':'' Int_0 = Int_0 ? (', "timeout": '+Int_0) : ''; -var code = ['{"type": "confirm"'+Int_0+Bool_0+', "text": "',EvalString_0,'",\n', +var code = ['{"type": "confirm"'+Int_0+Bool_0+', "text": "',EvalString_Multi_0,'",\n', '"yes": [\n',action_0,'],\n', '"no": [\n',action_1,']\n', '},\n'].join(''); @@ -2723,12 +2723,12 @@ return code; */; drawTextContent_s - : '绘制多行文本' EvalString BGNL? '起点像素' 'x' PosString 'y' PosString '最大宽度' IntString? '颜色' ColorString? Colour BGNL? '对齐' TextAlign_List '字体大小' IntString? '行距' IntString? '粗体' Bool Newline + : '绘制多行文本' EvalString_Multi BGNL? '起点像素' 'x' PosString 'y' PosString '最大宽度' IntString? '颜色' ColorString? Colour BGNL? '对齐' TextAlign_List '字体大小' IntString? '行距' IntString? '粗体' Bool Newline /* drawTextContent_s tooltip : drawTextContent:绘制多行文本 helpUrl : /_docs/#/instruction -doubleclicktext : EvalString_0 +doubleclicktext : EvalString_Multi_0 colour : this.subColor default : ["绘制多行文本\\n可双击编辑","0","0","","",'rgba(255,255,255,1)',null,"","",false] TextAlign_List_0 = TextAlign_List_0==='null'?'': ', "align": "'+TextAlign_List_0+'"'; @@ -2737,7 +2737,7 @@ IntString_0 = IntString_0 ? (', "maxWidth": '+IntString_0) : ''; IntString_1 = IntString_1 ? (', "fontSize": '+IntString_1) : ''; IntString_2 = IntString_2 ? (', "lineHeight": '+IntString_2) : ''; ColorString_0 = ColorString_0 ? (', "color": ['+ColorString_0+']') : ''; -var code = '{"type": "drawTextContent", "text": "'+EvalString_0+'", "left": '+PosString_0+', "top": '+PosString_1+TextAlign_List_0+IntString_0+IntString_1+IntString_2+ColorString_0+Bool_0+'},\n'; +var code = '{"type": "drawTextContent", "text": "'+EvalString_Multi_0+'", "left": '+PosString_0+', "top": '+PosString_1+TextAlign_List_0+IntString_0+IntString_1+IntString_2+ColorString_0+Bool_0+'},\n'; return code; */; @@ -3420,6 +3420,10 @@ EvalString : Equote_double (ESC_double | ~["\\])* Equote_double ; +EvalString_Multi + : Equote_double (ESC_double | ~["\\])* Equote_double + ; + fragment ESC_double : '\\' (["\\/bfnrt] | UNICODE) ; fragment UNICODE : 'u' HEX HEX HEX HEX ; fragment HEX : [0-9a-fA-F] ; diff --git a/_server/MotaActionParser.js b/_server/MotaActionParser.js index 60f67b12..7e72a2a8 100644 --- a/_server/MotaActionParser.js +++ b/_server/MotaActionParser.js @@ -256,10 +256,10 @@ ActionParser.prototype.parseAction = function() { break; case "scrollText": this.next = MotaActionBlocks['scrollText_s'].xmlText([ - data.time, data.lineHeight||1.4, data.async||false, this.EvalString(data.text), this.next]); + data.time, data.lineHeight||1.4, data.async||false, this.EvalString_Multi(data.text), this.next]); break; case "comment": // 注释 - this.next = MotaActionBlocks['comment_s'].xmlText([this.EvalString(data.text),this.next],null,data.text); + this.next = MotaActionBlocks['comment_s'].xmlText([this.EvalString_Multi(data.text),this.next],null,data.text); break; case "setText": // 设置剧情文本的属性 data.title=this.Colour(data.title); @@ -482,7 +482,7 @@ ActionParser.prototype.parseAction = function() { case "showTextImage": // 显示图片化文本 data.loc=data.loc||['',''] this.next = MotaActionBlocks['showTextImage_s'].xmlText([ - this.EvalString(data.text),data.code,data.loc[0],data.loc[1],data.lineHeight||1.4,data.reverse,data.opacity,data.time||0,data.async||false,this.next]); + this.EvalString_Multi(data.text),data.code,data.loc[0],data.loc[1],data.lineHeight||1.4,data.reverse,data.opacity,data.time||0,data.async||false,this.next]); break; case "moveImage": // 移动图片 data.to=data.to||['',''] @@ -658,7 +658,7 @@ ActionParser.prototype.parseAction = function() { break; case "confirm": // 显示确认框 this.next = MotaActionBlocks['confirm_s'].xmlText([ - this.EvalString(data.text), data.timeout||0, data["default"], + this.EvalString_Multi(data.text), data.timeout||0, data["default"], this.insertActionList(data["yes"]), this.insertActionList(data["no"]), this.next]); @@ -836,7 +836,7 @@ ActionParser.prototype.parseAction = function() { case "drawTextContent": // 绘制多行文本 data.color = this.Colour(data.color); this.next = MotaActionBlocks['drawTextContent_s'].xmlText([ - this.EvalString(data.text), data.left, data.top, data.maxWidth, data.color, 'rgba('+data.color+')', + this.EvalString_Multi(data.text), data.left, data.top, data.maxWidth, data.color, 'rgba('+data.color+')', data.align, data.fontSize, data.lineHeight, data.bold, this.next ]); break; @@ -1005,8 +1005,12 @@ ActionParser.prototype.EvalString = function(EvalString) { return EvalString.split('\b').join('\\b').split('\t').join('\\t').split('\n').join('\\n'); } +ActionParser.prototype.EvalString_Multi = function(EvalString) { + return EvalString.split('\b').join('\\b').split('\t').join('\\t'); +} + ActionParser.prototype.getTitleAndPosition = function (string) { - string = this.EvalString(string); + string = this.EvalString_Multi(string); var title = '', icon = '', position = ''; string = string.replace(/\\t\[(([^\],]+),)?([^\],]+)\]/g, function (s0, s1, s2, s3) { if (s3) title = s3; @@ -1187,6 +1191,12 @@ MotaActionFunctions.EvalString_pre = function(EvalString){ return EvalString.replace(/([^\\])"/g,'$1\\"').replace(/^"/g,'\\"').replace(/""/g,'"\\"'); } +MotaActionFunctions.EvalString_Multi_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,'"\\"').replace(/\n/g, '\\n'); +} + MotaActionFunctions.JsonEvalString_pre = function (JsonEvalString) { if (JsonEvalString == '') return ''; JsonEvalString = MotaActionFunctions.replaceFromName(JsonEvalString); diff --git a/_server/editor_blockly.js b/_server/editor_blockly.js index 3a678b7a..7dac543c 100644 --- a/_server/editor_blockly.js +++ b/_server/editor_blockly.js @@ -343,9 +343,10 @@ editor_blockly = function () { var value = b.getFieldValue(f); //多行编辑 editor_multi.multiLineEdit(value, b, f, {'lint': f === 'RawEvalString_0'}, function (newvalue, b, f) { - if (MotaActionBlocks[b.type].doubleclicktext !== 'RawEvalString_0') { + if (!f.startsWith('EvalString_Multi')) { + newvalue = newvalue.split('\n').join('\\n'); } - b.setFieldValue(newvalue.split('\n').join('\\n'), f); + b.setFieldValue(newvalue, f); }); } @@ -787,8 +788,10 @@ editor_blockly = function () { var list = editor_blockly.getAutoCompletions(value, pb.type, self.name); awesomplete.list = list; - awesomplete.ul.style.marginLeft = getCaretCoordinates(htmlInput, htmlInput.selectionStart).left - - htmlInput.scrollLeft - 20 + "px"; + var caretPosition = getCaretCoordinates(htmlInput, htmlInput.selectionStart); + awesomplete.ul.style.marginLeft = caretPosition.left - htmlInput.scrollLeft - 20 + "px"; + var totalHeight = parseFloat(Blockly.WidgetDiv.DIV.style.height.replace('px', '')); + awesomplete.ul.style.marginTop = caretPosition.top + caretPosition.height - totalHeight + 10 + 'px'; awesomplete.evaluate(); } @@ -871,6 +874,18 @@ Blockly.FieldTextInput.prototype.onHtmlInputKeyDown_ = function(e) { } }; +Blockly.FieldMultilineInput.prototype.showInlineEditor_ = function(quietInput) { + Blockly.FieldMultilineInput.superClass_.showInlineEditor_.call(this, quietInput); + // force to resize the input + this.htmlInput_.style.height = Blockly.WidgetDiv.DIV.style.height; +}; + +Blockly.FieldMultilineInput.prototype.onHtmlInputChange_ = function(e) { + Blockly.FieldMultilineInput.superClass_.onHtmlInputChange_.call(this, e); + // force to resize the input + this.htmlInput_.style.height = Blockly.WidgetDiv.DIV.style.height; +}; + Blockly.copy_ = function(toCopy) { if (toCopy.isComment) { var xml = toCopy.toXmlWithXY(); diff --git a/_server/thirdparty/caret-position.js b/_server/thirdparty/caret-position.js index a46ddb78..8294e99f 100644 --- a/_server/thirdparty/caret-position.js +++ b/_server/thirdparty/caret-position.js @@ -73,6 +73,7 @@ // Default textarea styles style.whiteSpace = 'nowrap'; + style.zIndex = 2000; if (!isInput) style.wordWrap = 'break-word'; // only for textarea-s @@ -107,6 +108,8 @@ style[prop] = computed[prop]; } }); + if (!isInput) + style.whiteSpace = 'pre'; if (isFirefox) { // Firefox lies about the overflow property for textareas: https://bugzilla.mozilla.org/show_bug.cgi?id=984275