上传文件至 _server
This commit is contained in:
parent
cd2e6ba069
commit
50bc71e2b9
4242
_server/MotaAction.g4
Normal file
4242
_server/MotaAction.g4
Normal file
File diff suppressed because it is too large
Load Diff
1737
_server/MotaActionParser.js
Normal file
1737
_server/MotaActionParser.js
Normal file
File diff suppressed because it is too large
Load Diff
273
_server/README.md
Normal file
273
_server/README.md
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
# editor
|
||||||
|
|
||||||
|
直接使用游戏运行时(之后简称core)的代码来绘制游戏画面, 借助fs.js来实现浏览器编辑文件. 通过表格编辑数据, blockly图块编辑事件, code mirror编辑文本的可视化魔塔编辑器.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
左侧数据区, 中间地图区, 右侧素材区
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
事件编辑器
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
脚本编辑器
|
||||||
|
|
||||||
|
> 此文件是editor的结构说明, 不是使用文档
|
||||||
|
|
||||||
|
## 组成
|
||||||
|
|
||||||
|
本目录下所有文件,以及`../editor.html`,`../editor-mobile.html`和`../启动服务.exe`,`../server.py`是地图编辑器的所有组件.
|
||||||
|
|
||||||
|
### 父目录
|
||||||
|
+ 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
|
||||||
|
|
||||||
|
游戏运行时中部分代码根据`main.mod=='editor'`进行了调整
|
||||||
|
|
||||||
|
+ 通过`main.init('editor')`加载数据
|
||||||
|
|
||||||
|
+ `editor`模式关闭了部分动画
|
||||||
|
|
||||||
|
+ `core.drawMap`中`editor`模式下不再画图,而是生成画图的函数提+ 供给`editor`
|
||||||
|
|
||||||
|
+ `editor`模式下`GlobalAnimate`可以独立的选择是否播放
|
||||||
|
|
||||||
|
+ `core.playBgm`和`core.playSound`中非`play`模式不再播放声音
|
||||||
|
|
||||||
|
+ `core.show`和`core.hide`中非`play`模式不再进行动画而是立刻+ 完成并执行回调
|
||||||
|
|
||||||
|
+ `editor`模式不执行`core.resize`
|
||||||
|
|
||||||
|
|
||||||
|
### fs.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)
|
||||||
|
//读文本文件
|
||||||
|
//callback:function(err, data)
|
||||||
|
//data:字符串
|
||||||
|
fs.readFile('file.in','base64',callback)
|
||||||
|
//读二进制文件
|
||||||
|
//callback:function(err, data)
|
||||||
|
//data:base64字符串
|
||||||
|
|
||||||
|
fs.writeFile('file.out', data ,'utf-8', callback)
|
||||||
|
//写文本文件
|
||||||
|
//callback:function(err)
|
||||||
|
//data:字符串
|
||||||
|
fs.writeFile('file.out', data ,'base64', callback)
|
||||||
|
//写二进制文件
|
||||||
|
//callback:function(err)
|
||||||
|
//data:base64字符串
|
||||||
|
|
||||||
|
fs.readdir(path, callback)
|
||||||
|
//callback:function(err, data)
|
||||||
|
//path:支持"/"做分隔符
|
||||||
|
//data:[filename1,filename2,..] filename是字符串,只包含文件不包含目录
|
||||||
|
|
||||||
|
//所有参数不允许缺省
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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, 以及部分和入口页面生成有关的函数
|
1
_server/config.json
Normal file
1
_server/config.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"viewportLoc":[0,0],"lastUsed":[{"idnum":46,"id":"fly","images":"items","y":12,"recent":1732768196310,"frequent":2},{"idnum":89,"id":"portal","images":"animates","y":17,"recent":1732590284009,"frequent":4},{"idnum":92,"id":"leftPortal","images":"animates","y":24,"recent":1732590243601,"frequent":4},{"idnum":94,"id":"rightPortal","images":"animates","y":25,"recent":1732590229450,"frequent":6},{"idnum":206,"id":"bigBat","images":"enemys","y":5,"recent":1732518600961,"frequent":1},{"idnum":211,"id":"skeletonCaptain","images":"enemys","y":10,"recent":1732518593961,"frequent":3},{"idnum":205,"id":"bat","images":"enemys","y":4,"recent":1732518591433,"frequent":1},{"idnum":88,"id":"downFloor","images":"terrains","y":5,"recent":1732510497803,"frequent":1},{"idnum":87,"id":"upFloor","images":"terrains","y":6,"recent":1732510482564,"frequent":3},{"idnum":93,"id":"downPortal","images":"animates","y":23,"recent":1732510408539,"frequent":3},{"idnum":91,"id":"upPortal","images":"animates","y":26,"recent":1732510340731,"frequent":3},{"idnum":257,"id":"dragon","images":"enemys","y":56,"recent":1732431861421,"frequent":4},{"idnum":130,"id":"expShop","images":"npcs","y":9,"recent":1732092503297,"frequent":1},{"idnum":27,"id":"redGem","images":"items","y":16,"recent":1732092498097,"frequent":1},{"idnum":246,"id":"blueKing","images":"enemys","y":45,"recent":1731057412587,"frequent":9},{"idnum":43,"id":"sword5","images":"items","y":54,"recent":1730963163489,"frequent":1},{"idnum":36,"id":"shield1","images":"items","y":55,"recent":1730963160769,"frequent":1},{"idnum":1,"id":"yellowWall","images":"animates","y":10,"recent":1673440212744,"frequent":2},{"idnum":45,"id":"book","images":"items","y":9,"recent":1732787462314,"frequent":1}],"editor_multi.fontSize":14,"editorLastFloorId":"MT7"}
|
1054
_server/editor.js
Normal file
1054
_server/editor.js
Normal file
File diff suppressed because it is too large
Load Diff
1213
_server/editor_blockly.js
Normal file
1213
_server/editor_blockly.js
Normal file
File diff suppressed because it is too large
Load Diff
705
_server/editor_blocklyconfig.js
Normal file
705
_server/editor_blocklyconfig.js
Normal file
@ -0,0 +1,705 @@
|
|||||||
|
editor_blocklyconfig=(function(){
|
||||||
|
// start mark sfergsvae
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
var getCategory = function(name,custom){
|
||||||
|
for(var node of document.getElementById('toolbox').children) {
|
||||||
|
if(node.getAttribute('name')==name) return node;
|
||||||
|
}
|
||||||
|
var node = document.createElement('category');
|
||||||
|
node.setAttribute('name',name);
|
||||||
|
if(custom)node.setAttribute('custom',custom);
|
||||||
|
document.getElementById('toolbox').appendChild(node);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
var toolboxObj = {
|
||||||
|
'入口方块':[
|
||||||
|
'<label text="入口方块会根据当前类型在此数组中筛选,具体控制在editor_blockly.entranceCategoryCallback中"></label>',
|
||||||
|
MotaActionFunctions.actionParser.parse([
|
||||||
|
"欢迎使用事件编辑器",
|
||||||
|
"本事件触发一次后会消失",
|
||||||
|
{"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": "shop1",
|
||||||
|
"text": "\t[贪婪之神,moneyShop]勇敢的武士啊, 给我${20+2*flag:shop1}金币就可以:",
|
||||||
|
"textInList": "1F金币商店",
|
||||||
|
"choices": [
|
||||||
|
{"text": "生命+800", "need": "status:money>=20+2*flag:shop1", "action": [
|
||||||
|
{"type": "comment", "text": "新版商店中需要手动扣减金币和增加访问次数"},
|
||||||
|
{"type": "setValue", "name": "status:money", "operator": "-=", "value": "20+2*flag:shop1"},
|
||||||
|
{"type": "setValue", "name": "flag:shop1", "operator": "+=", "value": "1"},
|
||||||
|
{"type": "setValue", "name": "status:hp", "operator": "+=", "value": "800"}
|
||||||
|
]}
|
||||||
|
]
|
||||||
|
},{
|
||||||
|
"id": "itemShop",
|
||||||
|
"item": true,
|
||||||
|
"textInList": "道具商店",
|
||||||
|
"choices": [
|
||||||
|
{"id": "yellowKey", "number": 10, "money": 10}
|
||||||
|
]
|
||||||
|
},{
|
||||||
|
"id": "keyShop1",
|
||||||
|
"textInList": "回收钥匙商店",
|
||||||
|
"commonEvent": "回收钥匙商店",
|
||||||
|
"args": ""
|
||||||
|
}],'shop'),
|
||||||
|
MotaActionBlocks['common_m'].xmlText(),
|
||||||
|
MotaActionBlocks['beforeBattle_m'].xmlText(),
|
||||||
|
MotaActionBlocks['afterBattle_m'].xmlText(),
|
||||||
|
MotaActionBlocks['afterGetItem_m'].xmlText(),
|
||||||
|
MotaActionBlocks['afterOpenDoor_m'].xmlText(),
|
||||||
|
MotaActionBlocks['firstArrive_m'].xmlText(),
|
||||||
|
MotaActionBlocks['eachArrive_m'].xmlText(),
|
||||||
|
MotaActionBlocks['level_m'].xmlText(),
|
||||||
|
MotaActionFunctions.actionParser.parse([
|
||||||
|
['MTx', '']
|
||||||
|
], 'floorPartition'),
|
||||||
|
MotaActionBlocks['commonEvent_m'].xmlText(),
|
||||||
|
MotaActionBlocks['item_m'].xmlText(),
|
||||||
|
MotaActionFunctions.actionParser.parse([
|
||||||
|
{"title":"简单", "name": "Easy", "hard": 1, "action": [
|
||||||
|
{"type": "comment", "text": "在这里写该难度需执行的事件"}
|
||||||
|
]}
|
||||||
|
], 'levelChoose'),
|
||||||
|
MotaActionFunctions.actionParser.parse({
|
||||||
|
"type": 0, "value": {"atk": 10}, "percentage": {"speed": 10},
|
||||||
|
}, 'equip'),
|
||||||
|
MotaActionFunctions.actionParser.parse([{
|
||||||
|
"name": "bg.jpg", "x": 0, "y": 0, "canvas": "bg"
|
||||||
|
}], 'floorImage'),
|
||||||
|
MotaActionFunctions.actionParser.parse({
|
||||||
|
"time": 160, "openSound": "door.mp3", "closeSound": "door.mp3", "keys": {"yellowKey": 1, "orangeKey": 1}
|
||||||
|
}, 'doorInfo'),
|
||||||
|
MotaActionBlocks['faceIds_m'].xmlText(),
|
||||||
|
MotaActionBlocks['mainStyle_m'].xmlText(),
|
||||||
|
MotaActionFunctions.actionParser.parse({
|
||||||
|
"背景音乐": "bgm.mp3", "确定": "confirm.mp3", "攻击": "attack.mp3", "背景图": "bg.jpg", "领域": "zone", "文件名": "file.jpg"
|
||||||
|
}, 'nameMap'),
|
||||||
|
MotaActionFunctions.actionParser.parse([
|
||||||
|
{"name": "hero.png", "width": 32, "height": 32, "prefix": "hero_"},
|
||||||
|
], 'splitImages'),
|
||||||
|
],
|
||||||
|
'显示文字':[
|
||||||
|
MotaActionBlocks['text_0_s'].xmlText(),
|
||||||
|
MotaActionBlocks['text_1_s'].xmlText(),
|
||||||
|
MotaActionFunctions.actionParser.parseList("\t[小妖精,fairy]\f[fairy.png,0,0]欢迎使用事件编辑器(双击方块可直接预览)"),
|
||||||
|
MotaActionBlocks['moveTextBox_s'].xmlText(),
|
||||||
|
MotaActionBlocks['clearTextBox_s'].xmlText(),
|
||||||
|
MotaActionBlocks['comment_s'].xmlText(),
|
||||||
|
MotaActionBlocks['autoText_s'].xmlText(),
|
||||||
|
MotaActionBlocks['scrollText_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setText_s'].xmlText(),
|
||||||
|
MotaActionBlocks['tip_s'].xmlText(),
|
||||||
|
MotaActionBlocks['confirm_s'].xmlText(),
|
||||||
|
MotaActionBlocks['choices_s'].xmlText([
|
||||||
|
'选择剑或者盾','流浪者','man',0,'',MotaActionBlocks['choicesContext'].xmlText([
|
||||||
|
'剑','','',null,'','',MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]),
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
MotaActionBlocks['win_s'].xmlText(),
|
||||||
|
MotaActionBlocks['lose_s'].xmlText(),
|
||||||
|
MotaActionBlocks['restart_s'].xmlText(),
|
||||||
|
],
|
||||||
|
'数据相关':[
|
||||||
|
MotaActionBlocks['setValue_s'].xmlText([
|
||||||
|
MotaActionBlocks['idIdList_e'].xmlText(['status','生命']), '=', '', false
|
||||||
|
]),
|
||||||
|
MotaActionBlocks['setEnemy_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setEnemyOnPoint_s'].xmlText(),
|
||||||
|
MotaActionBlocks['resetEnemyOnPoint_s'].xmlText(),
|
||||||
|
MotaActionBlocks['moveEnemyOnPoint_s'].xmlText(),
|
||||||
|
MotaActionBlocks['moveEnemyOnPoint_1_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setEquip_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setFloor_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setGlobalAttribute_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setGlobalValue_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setGlobalFlag_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setNameMap_s'].xmlText(),
|
||||||
|
MotaActionBlocks['input_s'].xmlText(),
|
||||||
|
MotaActionBlocks['input2_s'].xmlText(),
|
||||||
|
MotaActionBlocks['update_s'].xmlText(),
|
||||||
|
MotaActionBlocks['moveAction_s'].xmlText(),
|
||||||
|
MotaActionBlocks['changeFloor_s'].xmlText(),
|
||||||
|
MotaActionBlocks['changePos_s'].xmlText(),
|
||||||
|
MotaActionBlocks['battle_s'].xmlText(),
|
||||||
|
MotaActionBlocks['useItem_s'].xmlText(),
|
||||||
|
MotaActionBlocks['loadEquip_s'].xmlText(),
|
||||||
|
MotaActionBlocks['unloadEquip_s'].xmlText(),
|
||||||
|
MotaActionBlocks['openShop_s'].xmlText(),
|
||||||
|
MotaActionBlocks['disableShop_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setHeroIcon_s'].xmlText(),
|
||||||
|
MotaActionBlocks['follow_s'].xmlText(),
|
||||||
|
MotaActionBlocks['unfollow_s'].xmlText(),
|
||||||
|
],
|
||||||
|
'地图处理':[
|
||||||
|
MotaActionBlocks['battle_1_s'].xmlText(),
|
||||||
|
MotaActionBlocks['openDoor_s'].xmlText(),
|
||||||
|
MotaActionBlocks['closeDoor_s'].xmlText(),
|
||||||
|
MotaActionBlocks['show_s'].xmlText(),
|
||||||
|
MotaActionBlocks['hide_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setBlock_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setBlockOpacity_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setBlockFilter_s'].xmlText(),
|
||||||
|
MotaActionBlocks['turnBlock_s'].xmlText(),
|
||||||
|
MotaActionBlocks['moveHero_s'].xmlText(),
|
||||||
|
MotaActionBlocks['move_s'].xmlText(),
|
||||||
|
MotaActionBlocks['jumpHero_s'].xmlText(),
|
||||||
|
MotaActionBlocks['jumpHero_1_s'].xmlText(),
|
||||||
|
MotaActionBlocks['jump_s'].xmlText(),
|
||||||
|
MotaActionBlocks['jump_1_s'].xmlText(),
|
||||||
|
MotaActionBlocks['showBgFgMap_s'].xmlText(),
|
||||||
|
MotaActionBlocks['hideBgFgMap_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setBgFgBlock_s'].xmlText(),
|
||||||
|
MotaActionBlocks['showFloorImg_s'].xmlText(),
|
||||||
|
MotaActionBlocks['hideFloorImg_s'].xmlText(),
|
||||||
|
],
|
||||||
|
'事件控制':[
|
||||||
|
MotaActionBlocks['if_1_s'].xmlText(),
|
||||||
|
MotaActionBlocks['if_s'].xmlText(),
|
||||||
|
MotaActionFunctions.actionParser.parseList({"type": "switch", "condition": "判别值", "caseList": [
|
||||||
|
{"action": [{"type": "comment", "text": "当判别值是值的场合执行此事件"}]},
|
||||||
|
{"case": "default", "action": [{"type": "comment", "text": "当没有符合的值的场合执行default事件"}]},
|
||||||
|
]}),
|
||||||
|
MotaActionFunctions.actionParser.parseList({"type": "for", "name": "temp:A", "from": "0", "to": "12", "step": "1", "data": []}),
|
||||||
|
MotaActionFunctions.actionParser.parseList({"type": "forEach", "name": "temp:A", "list": ["status:atk","status:def"], "data": []}),
|
||||||
|
MotaActionBlocks['while_s'].xmlText(),
|
||||||
|
MotaActionBlocks['dowhile_s'].xmlText(),
|
||||||
|
MotaActionBlocks['break_s'].xmlText(),
|
||||||
|
MotaActionBlocks['continue_s'].xmlText(),
|
||||||
|
MotaActionBlocks['exit_s'].xmlText(),
|
||||||
|
MotaActionBlocks['trigger_s'].xmlText(),
|
||||||
|
MotaActionBlocks['insert_1_s'].xmlText(),
|
||||||
|
MotaActionBlocks['insert_2_s'].xmlText(),
|
||||||
|
],
|
||||||
|
'特效表现':[
|
||||||
|
MotaActionBlocks['sleep_s'].xmlText(),
|
||||||
|
MotaActionFunctions.actionParser.parseList({"type": "wait", "timeout": 0, "data": [
|
||||||
|
{"case": "keyboard", "keycode": "13,32", "action": [{"type": "comment", "text": "当按下回车(keycode=13)或空格(keycode=32)时执行此事件\n超时剩余时间会写入flag:timeout"}]},
|
||||||
|
{"case": "mouse", "px": [0,32], "py": [0,32], "action": [{"type": "comment", "text": "当点击地图左上角时执行此事件\n超时剩余时间会写入flag:timeout"}]},
|
||||||
|
{"case": "condition", "condition": "flag:type==0\n&&flag:keycode==13", "action": [{"type": "comment", "text": "当满足自定义条件时会执行此事件\n超时剩余时间会写入flag:timeout"}]},
|
||||||
|
{"case": "timeout", "action": [{"type": "comment", "text": "当超时未操作时执行此事件"}]},
|
||||||
|
]}),
|
||||||
|
MotaActionBlocks['waitAsync_s'].xmlText(),
|
||||||
|
MotaActionBlocks['stopAsync_s'].xmlText(),
|
||||||
|
MotaActionBlocks['vibrate_s'].xmlText(),
|
||||||
|
MotaActionBlocks['animate_s'].xmlText(),
|
||||||
|
MotaActionBlocks['animate_1_s'].xmlText(),
|
||||||
|
MotaActionBlocks['stopAnimate_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setViewport_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setViewport_1_s'].xmlText(),
|
||||||
|
MotaActionBlocks['lockViewport_s'].xmlText(),
|
||||||
|
MotaActionBlocks['showStatusBar_s'].xmlText(),
|
||||||
|
MotaActionBlocks['hideStatusBar_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setHeroOpacity_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setCurtain_0_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setCurtain_1_s'].xmlText(),
|
||||||
|
MotaActionBlocks['screenFlash_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setWeather_s'].xmlText(),
|
||||||
|
MotaActionBlocks['callBook_s'].xmlText(),
|
||||||
|
MotaActionBlocks['callSave_s'].xmlText(),
|
||||||
|
MotaActionBlocks['autoSave_s'].xmlText(),
|
||||||
|
MotaActionBlocks['forbidSave_s'].xmlText(),
|
||||||
|
MotaActionBlocks['callLoad_s'].xmlText(),
|
||||||
|
],
|
||||||
|
'音像处理':[
|
||||||
|
MotaActionBlocks['showImage_s'].xmlText(),
|
||||||
|
MotaActionBlocks['showImage_1_s'].xmlText(),
|
||||||
|
MotaActionBlocks['hideImage_s'].xmlText(),
|
||||||
|
MotaActionBlocks['showTextImage_s'].xmlText(),
|
||||||
|
MotaActionBlocks['moveImage_s'].xmlText(),
|
||||||
|
MotaActionBlocks['rotateImage_s'].xmlText(),
|
||||||
|
MotaActionBlocks['scaleImage_s'].xmlText(),
|
||||||
|
MotaActionBlocks['showGif_s'].xmlText(),
|
||||||
|
MotaActionBlocks['playBgm_s'].xmlText(),
|
||||||
|
MotaActionBlocks['pauseBgm_s'].xmlText(),
|
||||||
|
MotaActionBlocks['resumeBgm_s'].xmlText(),
|
||||||
|
MotaActionBlocks['loadBgm_s'].xmlText(),
|
||||||
|
MotaActionBlocks['freeBgm_s'].xmlText(),
|
||||||
|
MotaActionBlocks['playSound_s'].xmlText(),
|
||||||
|
MotaActionBlocks['playSound_1_s'].xmlText(),
|
||||||
|
MotaActionBlocks['stopSound_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setVolume_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setBgmSpeed_s'].xmlText(),
|
||||||
|
],
|
||||||
|
'UI绘制':[
|
||||||
|
MotaActionBlocks['previewUI_s'].xmlText(),
|
||||||
|
MotaActionBlocks['clearMap_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setAttribute_s'].xmlText(),
|
||||||
|
MotaActionBlocks['setFilter_s'].xmlText(),
|
||||||
|
MotaActionBlocks['fillText_s'].xmlText(),
|
||||||
|
MotaActionBlocks['fillBoldText_s'].xmlText(),
|
||||||
|
MotaActionBlocks['drawTextContent_s'].xmlText(),
|
||||||
|
MotaActionBlocks['fillRect_s'].xmlText(),
|
||||||
|
MotaActionBlocks['strokeRect_s'].xmlText(),
|
||||||
|
MotaActionBlocks['drawLine_s'].xmlText(),
|
||||||
|
MotaActionBlocks['drawArrow_s'].xmlText(),
|
||||||
|
MotaActionBlocks['fillPolygon_s'].xmlText(),
|
||||||
|
MotaActionBlocks['strokePolygon_s'].xmlText(),
|
||||||
|
MotaActionBlocks['fillEllipse_s'].xmlText(),
|
||||||
|
MotaActionBlocks['strokeEllipse_s'].xmlText(),
|
||||||
|
MotaActionBlocks['fillArc_s'].xmlText(),
|
||||||
|
MotaActionBlocks['strokeArc_s'].xmlText(),
|
||||||
|
MotaActionBlocks['drawImage_s'].xmlText(),
|
||||||
|
MotaActionBlocks['drawImage_1_s'].xmlText(),
|
||||||
|
MotaActionBlocks['drawIcon_s'].xmlText(),
|
||||||
|
MotaActionBlocks['drawBackground_s'].xmlText(),
|
||||||
|
MotaActionBlocks['drawSelector_s'].xmlText(),
|
||||||
|
MotaActionBlocks['drawSelector_1_s'].xmlText(),
|
||||||
|
],
|
||||||
|
'原生脚本':[
|
||||||
|
MotaActionBlocks['function_s'].xmlText(),
|
||||||
|
MotaActionBlocks['unknown_s'].xmlText(),
|
||||||
|
],
|
||||||
|
'值块':[
|
||||||
|
MotaActionBlocks['setValue_s'].xmlText([
|
||||||
|
MotaActionBlocks['idIdList_e'].xmlText(['status','生命']), '=', '', false
|
||||||
|
]),
|
||||||
|
MotaActionBlocks['expression_arithmetic_0'].xmlText(),
|
||||||
|
MotaActionBlocks['idFlag_e'].xmlText(),
|
||||||
|
MotaActionBlocks['idTemp_e'].xmlText(),
|
||||||
|
MotaActionBlocks['negate_e'].xmlText(),
|
||||||
|
MotaActionBlocks['unaryOperation_e'].xmlText(),
|
||||||
|
MotaActionBlocks['bool_e'].xmlText(),
|
||||||
|
MotaActionBlocks['idString_e'].xmlText(),
|
||||||
|
MotaActionBlocks['idIdList_e'].xmlText(),
|
||||||
|
MotaActionBlocks['idFixedList_e'].xmlText(),
|
||||||
|
MotaActionBlocks['enemyattr_e'].xmlText(),
|
||||||
|
MotaActionBlocks['blockId_e'].xmlText(),
|
||||||
|
MotaActionBlocks['blockNumber_e'].xmlText(),
|
||||||
|
MotaActionBlocks['blockCls_e'].xmlText(),
|
||||||
|
MotaActionBlocks['hasEquip_e'].xmlText(),
|
||||||
|
MotaActionBlocks['equip_e'].xmlText(),
|
||||||
|
MotaActionBlocks['nextXY_e'].xmlText(),
|
||||||
|
MotaActionBlocks['isReplaying_e'].xmlText(),
|
||||||
|
MotaActionBlocks['hasVisitedFloor_e'].xmlText(),
|
||||||
|
MotaActionBlocks['isShopVisited_e'].xmlText(),
|
||||||
|
MotaActionBlocks['canBattle_e'].xmlText(),
|
||||||
|
MotaActionBlocks['damage_e'].xmlText(),
|
||||||
|
MotaActionBlocks['damage_1_e'].xmlText(),
|
||||||
|
MotaActionBlocks['rand_e'].xmlText(),
|
||||||
|
MotaActionBlocks['evalString_e'].xmlText(),
|
||||||
|
],
|
||||||
|
'常见事件模板':[
|
||||||
|
'<label text="检测音乐如果没有开启则系统提示开启"></label>',
|
||||||
|
MotaActionFunctions.actionParser.parseList({"type": "if", "condition": "!core.musicStatus.bgmStatus",
|
||||||
|
"true": [
|
||||||
|
"\t[系统提示]你当前音乐处于关闭状态,本塔开音乐游戏效果更佳"
|
||||||
|
],
|
||||||
|
"false": []
|
||||||
|
}),
|
||||||
|
'<label text="仿新新魔塔一次性商人"></label>',
|
||||||
|
MotaActionFunctions.actionParser.parse([
|
||||||
|
{
|
||||||
|
"type": "if",
|
||||||
|
"condition": "switch:A",
|
||||||
|
"true": [
|
||||||
|
"\t[行商,trader]\b[this]这是购买我的道具后我给玩家的提示。",
|
||||||
|
{
|
||||||
|
"type": "comment",
|
||||||
|
"text": "下一条指令可视情况使用或不使用"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "hide",
|
||||||
|
"remove": true,
|
||||||
|
"time": 250
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"false": [
|
||||||
|
{
|
||||||
|
"type": "confirm",
|
||||||
|
"text": "我有3把黄钥匙,\n你出50金币就卖给你。",
|
||||||
|
"yes": [
|
||||||
|
{
|
||||||
|
"type": "if",
|
||||||
|
"condition": "status:money>=50",
|
||||||
|
"true": [
|
||||||
|
{
|
||||||
|
"type": "setValue",
|
||||||
|
"name": "status:money",
|
||||||
|
"operator": "-=",
|
||||||
|
"value": "50"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "setValue",
|
||||||
|
"name": "item:yellowKey",
|
||||||
|
"operator": "+=",
|
||||||
|
"value": "3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "playSound",
|
||||||
|
"name": "确定",
|
||||||
|
"stop": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "setValue",
|
||||||
|
"name": "switch:A",
|
||||||
|
"value": "true"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"false": [
|
||||||
|
{
|
||||||
|
"type": "playSound",
|
||||||
|
"name": "操作失败"
|
||||||
|
},
|
||||||
|
"\t[行商,trader]\b[this]你的金币不足!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"no": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
], 'event'),
|
||||||
|
'<label text="全地图选中一个点"></label>',
|
||||||
|
MotaActionFunctions.actionParser.parse([
|
||||||
|
{
|
||||||
|
"type": "comment",
|
||||||
|
"text": "全地图选中一个点,需要用鼠标或触屏操作"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "setValue",
|
||||||
|
"name": "temp:X",
|
||||||
|
"value": "status:x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "setValue",
|
||||||
|
"name": "temp:Y",
|
||||||
|
"value": "status:y"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "tip",
|
||||||
|
"text": "再次点击闪烁位置确认"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "while",
|
||||||
|
"condition": "true",
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"type": "drawSelector",
|
||||||
|
"image": "winskin.png",
|
||||||
|
"code": 1,
|
||||||
|
"x": "32*temp:X",
|
||||||
|
"y": "32*temp:Y",
|
||||||
|
"width": 32,
|
||||||
|
"height": 32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "wait"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "if",
|
||||||
|
"condition": "(flag:type === 1)",
|
||||||
|
"true": [
|
||||||
|
{
|
||||||
|
"type": "if",
|
||||||
|
"condition": "((temp:X===flag:x)&&(temp:Y===flag:y))",
|
||||||
|
"true": [
|
||||||
|
{
|
||||||
|
"type": "break",
|
||||||
|
"n": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "setValue",
|
||||||
|
"name": "temp:X",
|
||||||
|
"value": "flag:x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "setValue",
|
||||||
|
"name": "temp:Y",
|
||||||
|
"value": "flag:y"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "drawSelector",
|
||||||
|
"code": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "comment",
|
||||||
|
"text": "流程进行到这里可以对[X,Y]点进行处理,比如"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "closeDoor",
|
||||||
|
"id": "yellowDoor",
|
||||||
|
"loc": [
|
||||||
|
"temp:X",
|
||||||
|
"temp:Y"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],'event'),
|
||||||
|
'<label text="多阶段Boss战斗"></label>',
|
||||||
|
MotaActionFunctions.actionParser.parse([
|
||||||
|
{
|
||||||
|
"type": "comment",
|
||||||
|
"text": "多阶段boss,请直接作为战后事件使用"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "setValue",
|
||||||
|
"name": "switch:A",
|
||||||
|
"operator": "+=",
|
||||||
|
"value": "1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "switch",
|
||||||
|
"condition": "switch:A",
|
||||||
|
"caseList": [
|
||||||
|
{
|
||||||
|
"case": "1",
|
||||||
|
"action": [
|
||||||
|
{
|
||||||
|
"type": "setBlock",
|
||||||
|
"number": "redSlime"
|
||||||
|
},
|
||||||
|
"\t[2阶段boss,redSlime]\b[this]你以为你已经打败我了吗?没听说过史莱姆有九条命吗?"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"case": "2",
|
||||||
|
"action": [
|
||||||
|
{
|
||||||
|
"type": "setBlock",
|
||||||
|
"number": "blackSlime"
|
||||||
|
},
|
||||||
|
"\t[3阶段boss,blackSlime]\b[this]不能消灭我的,只会让我更强大!"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"case": "3",
|
||||||
|
"action": [
|
||||||
|
{
|
||||||
|
"type": "setBlock",
|
||||||
|
"number": "slimelord"
|
||||||
|
},
|
||||||
|
"\t[4阶段boss,slimelord]\b[this]我还能打!"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"case": "4",
|
||||||
|
"action": [
|
||||||
|
"\t[4阶段boss,slimelord]我一定会回来的!"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],'afterBattle'),
|
||||||
|
],
|
||||||
|
'最近使用事件':[
|
||||||
|
'<label text="此处只是占位符,实际定义在editor_blockly.searchBlockCategoryCallback中"></label>',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
var toolboxgap = '<sep gap="5"></sep>'
|
||||||
|
//xml_text = MotaActionFunctions.actionParser.parse(obj,type||'event')
|
||||||
|
//MotaActionBlocks['idString_e'].xmlText()
|
||||||
|
|
||||||
|
for (var name in toolboxObj){
|
||||||
|
var custom = null;
|
||||||
|
if(name=='最近使用事件')custom='searchBlockCategory';
|
||||||
|
if(name=='入口方块')custom='entranceCategory';
|
||||||
|
getCategory(name,custom).innerHTML = toolboxObj[name].join(toolboxgap);
|
||||||
|
}
|
||||||
|
|
||||||
|
var blocklyArea = document.getElementById('blocklyArea');
|
||||||
|
var blocklyDiv = document.getElementById('blocklyDiv');
|
||||||
|
var workspace = Blockly.inject(blocklyDiv,{
|
||||||
|
media: '_server/blockly/media/',
|
||||||
|
toolbox: document.getElementById('toolbox'),
|
||||||
|
zoom:{
|
||||||
|
controls: true,
|
||||||
|
wheel: false,//滚轮改为上下(shift:左右)翻滚
|
||||||
|
startScale: 1.0,
|
||||||
|
maxScale: 3,
|
||||||
|
minScale: 0.3,
|
||||||
|
scaleSpeed: 1.08
|
||||||
|
},
|
||||||
|
trashcan: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
editor_blockly.isCommonEntry = function () {
|
||||||
|
var commonEntries = ['beforeBattle', 'afterBattle', 'afterOpenDoor', 'firstArrive', 'eachArrive', 'commonEvent', 'item'];
|
||||||
|
return commonEntries.indexOf(editor_blockly.entryType) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_blockly.entranceCategoryCallback = function(workspace) {
|
||||||
|
var list=toolboxObj['入口方块']
|
||||||
|
var xmlList = [];
|
||||||
|
var eventType = (editor_blockly.isCommonEntry() ? 'common' : editor_blockly.entryType)+'_m';
|
||||||
|
for(var ii=0,blockText;blockText=list[ii];ii++){
|
||||||
|
if(new RegExp('<block type="'+eventType+'">').exec(blockText)){
|
||||||
|
var block = Blockly.Xml.textToDom('<xml>'+blockText+'</xml>').firstChild;
|
||||||
|
block.setAttribute("gap", 5);
|
||||||
|
xmlList.push(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return xmlList;
|
||||||
|
}
|
||||||
|
|
||||||
|
workspace.registerToolboxCategoryCallback(
|
||||||
|
'entranceCategory', editor_blockly.entranceCategoryCallback);
|
||||||
|
|
||||||
|
editor_blockly.searchBlockCategoryCallback = function(workspace) {
|
||||||
|
var xmlList = [];
|
||||||
|
var labels = editor_blockly.searchBlock();
|
||||||
|
for (var i = 0; i < labels.length; i++) {
|
||||||
|
var blockText = '<xml>' +
|
||||||
|
MotaActionBlocks[labels[i]].xmlText() +
|
||||||
|
'</xml>';
|
||||||
|
var block = Blockly.Xml.textToDom(blockText).firstChild;
|
||||||
|
block.setAttribute("gap", 5);
|
||||||
|
xmlList.push(block);
|
||||||
|
}
|
||||||
|
return xmlList;
|
||||||
|
};
|
||||||
|
|
||||||
|
workspace.registerToolboxCategoryCallback(
|
||||||
|
'searchBlockCategory', editor_blockly.searchBlockCategoryCallback);
|
||||||
|
|
||||||
|
var onresize = function(e) {
|
||||||
|
blocklyDiv.style.width = blocklyArea.offsetWidth + 'px';
|
||||||
|
blocklyDiv.style.height = blocklyArea.offsetHeight + 'px';
|
||||||
|
Blockly.svgResize(workspace);
|
||||||
|
};
|
||||||
|
if(typeof editor !== "undefined" && !editor.isMobile)window.addEventListener('resize', onresize, false);
|
||||||
|
onresize();
|
||||||
|
//Blockly.svgResize(workspace);
|
||||||
|
|
||||||
|
//Blockly.bindEventWithChecks_(workspace.svgGroup_,"wheel",workspace,function(e){});
|
||||||
|
document.getElementById('blocklyDiv').onmousewheel = function(e){
|
||||||
|
//console.log(e);
|
||||||
|
e.preventDefault();
|
||||||
|
var hvScroll = e.shiftKey?'hScroll':'vScroll';
|
||||||
|
var mousewheelOffsetValue=20/380*workspace.scrollbar[hvScroll].handleLength_*3;
|
||||||
|
workspace.scrollbar[hvScroll].handlePosition_+=( ((e.deltaY||0)+(e.detail||0)) >0?mousewheelOffsetValue:-mousewheelOffsetValue);
|
||||||
|
workspace.scrollbar[hvScroll].onScroll_();
|
||||||
|
// workspace.setScale(workspace.scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
var doubleClickCheck=[[0,'abc']];
|
||||||
|
function omitedcheckUpdateFunction(event) {
|
||||||
|
if(event.type==='create'){
|
||||||
|
editor_blockly.addIntoLastUsedType(event.blockId);
|
||||||
|
}
|
||||||
|
if(event.type==='ui' && event.element == 'click'){
|
||||||
|
var newClick = [new Date().getTime(),event.blockId];
|
||||||
|
var lastClick = doubleClickCheck.shift();
|
||||||
|
doubleClickCheck.push(newClick);
|
||||||
|
if(newClick[0]-lastClick[0]<500){
|
||||||
|
if(newClick[1]===lastClick[1]){
|
||||||
|
editor_blockly.doubleClickBlock(newClick[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Only handle these events
|
||||||
|
if (["create", "move", "change", "delete"].indexOf(event.type) < 0) return;
|
||||||
|
if(editor_blockly.workspace.topBlocks_.length>=2){
|
||||||
|
editor_blockly.setValue('入口方块只能有一个');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var eventType = editor_blockly.entryType;
|
||||||
|
if(editor_blockly.workspace.topBlocks_.length==1){
|
||||||
|
var blockType = editor_blockly.workspace.topBlocks_[0].type;
|
||||||
|
if(blockType!==eventType+'_m' && !(editor_blockly.isCommonEntry() && blockType == 'common_m')){
|
||||||
|
editor_blockly.setValue('入口方块类型错误');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var code = Blockly.JavaScript.workspaceToCode(workspace).replace(/\\(i|c|d|e|g|z)/g, '\\\\$1');
|
||||||
|
editor_blockly.setValue(code);
|
||||||
|
} catch (error) {
|
||||||
|
editor_blockly.setValue(String(error));
|
||||||
|
if (error instanceof OmitedError){
|
||||||
|
var blockName = error.blockName;
|
||||||
|
var varName = error.varName;
|
||||||
|
var block = error.block;
|
||||||
|
}
|
||||||
|
// console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
workspace.addChangeListener(omitedcheckUpdateFunction);
|
||||||
|
|
||||||
|
workspace.addChangeListener(Blockly.Events.disableOrphans);
|
||||||
|
|
||||||
|
editor_blockly.workspace = workspace;
|
||||||
|
|
||||||
|
MotaActionFunctions.workspace = function(){
|
||||||
|
return editor_blockly.workspace;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 因为在editor_blockly.parse里已经HTML转义过一次了,所以这里要覆盖掉以避免在注释中出现<等
|
||||||
|
MotaActionFunctions.xmlText = function (ruleName,inputs,isShadow,comment,collapsed,disabled) {
|
||||||
|
var rule = MotaActionBlocks[ruleName];
|
||||||
|
var blocktext = isShadow?'shadow':'block';
|
||||||
|
var xmlText = [];
|
||||||
|
xmlText.push('<'+blocktext+' type="'+ruleName+'"'+(collapsed ? ' collapsed="true"' : '')+(disabled ? ' disabled="true"' : '')+'>');
|
||||||
|
if(!inputs)inputs=[];
|
||||||
|
for (var ii=0,inputType;inputType=rule.argsType[ii];ii++) {
|
||||||
|
var input = inputs[ii];
|
||||||
|
var _input = '';
|
||||||
|
var noinput = (input===null || input===undefined);
|
||||||
|
if(noinput && inputType==='field' && MotaActionBlocks[rule.argsGrammarName[ii]].type!=='field_dropdown') continue;
|
||||||
|
if(noinput && inputType==='field') {
|
||||||
|
noinput = false;
|
||||||
|
input = rule.fieldDefault(rule.args[ii])
|
||||||
|
}
|
||||||
|
if(noinput) input = '';
|
||||||
|
if(inputType==='field' && MotaActionBlocks[rule.argsGrammarName[ii]].type==='field_checkbox')input=input?'TRUE':'FALSE';
|
||||||
|
if(inputType!=='field') {
|
||||||
|
var subList = false;
|
||||||
|
var subrulename = rule.argsGrammarName[ii];
|
||||||
|
var subrule = MotaActionBlocks[subrulename];
|
||||||
|
if (subrule instanceof Array) {
|
||||||
|
subrulename=subrule[subrule.length-1];
|
||||||
|
subrule = MotaActionBlocks[subrulename];
|
||||||
|
subList = true;
|
||||||
|
}
|
||||||
|
_input = subrule.xmlText([],true);
|
||||||
|
if(noinput && !subList && !isShadow) {
|
||||||
|
//无输入的默认行为是: 如果语句块的备选方块只有一个,直接代入方块
|
||||||
|
input = subrule.xmlText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlText.push('<'+inputType+' name="'+rule.args[ii]+'">');
|
||||||
|
xmlText.push(_input+input);
|
||||||
|
xmlText.push('</'+inputType+'>');
|
||||||
|
}
|
||||||
|
if(comment){
|
||||||
|
xmlText.push('<comment>');
|
||||||
|
xmlText.push(comment);
|
||||||
|
xmlText.push('</comment>');
|
||||||
|
}
|
||||||
|
var next = inputs[rule.args.length];
|
||||||
|
if (next) {//next
|
||||||
|
xmlText.push('<next>');
|
||||||
|
xmlText.push(next);
|
||||||
|
xmlText.push('</next>');
|
||||||
|
}
|
||||||
|
xmlText.push('</'+blocktext+'>');
|
||||||
|
return xmlText.join('');
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// end mark sfergsvae
|
||||||
|
}).toString().split('// start mark sfergsvae')[1].split('// end mark sfergsvae')[0]
|
52
_server/editor_config.js
Normal file
52
_server/editor_config.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
function editor_config() {
|
||||||
|
this.address = "_server/config.json";
|
||||||
|
this._isWriting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_config.prototype.load = function(callback) {
|
||||||
|
var _this = this;
|
||||||
|
fs.readFile(this.address, "utf-8", function(e, d) {
|
||||||
|
if (e) {
|
||||||
|
console.error("无法读取配置文件, 已重新生成");
|
||||||
|
_this.config = {};
|
||||||
|
_this.save(callback);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
_this.config = JSON.parse(d);
|
||||||
|
if (callback) callback();
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
_this.config = {};
|
||||||
|
_this.save(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_config.prototype.get = function(key, defaultValue) {
|
||||||
|
value = this.config[key];
|
||||||
|
return value != null ? value : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_config.prototype.set = function(key, value, callback) {
|
||||||
|
this.config[key] = value;
|
||||||
|
if (callback !== false) this.save(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_config.prototype.save = function(callback) {
|
||||||
|
// 读写锁防止写文件冲突
|
||||||
|
if (this._isWriting) return;
|
||||||
|
try {
|
||||||
|
this._isWriting = true;
|
||||||
|
var _this = this;
|
||||||
|
fs.writeFile(this.address, JSON.stringify(this.config) ,'utf-8', function(e) {
|
||||||
|
_this._isWriting = false;
|
||||||
|
if (e) console.error("写入配置文件失败");
|
||||||
|
if (callback instanceof Function) callback();
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
this._isWriting = false;
|
||||||
|
console.error(e);
|
||||||
|
if (callback instanceof Function) callback();
|
||||||
|
}
|
||||||
|
}
|
1228
_server/editor_datapanel.js
Normal file
1228
_server/editor_datapanel.js
Normal file
File diff suppressed because it is too large
Load Diff
1118
_server/editor_file.js
Normal file
1118
_server/editor_file.js
Normal file
File diff suppressed because it is too large
Load Diff
199
_server/editor_game.js
Normal file
199
_server/editor_game.js
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
editor_game_wrapper = function (editor, main, core) {
|
||||||
|
// 原则上重构后只有此文件允许`\s(main|core)`形式的调用, 以及其初始化 editor_game_wrapper(editor, main, core)
|
||||||
|
|
||||||
|
editor_game = function () {
|
||||||
|
this.replacerRecord = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////// 修改数据相关 ////////////////////
|
||||||
|
// 三个 replacer 和 replacerRecord 暂时放在此处
|
||||||
|
|
||||||
|
editor_game.prototype.replacerForLoading = function (_key, value) {
|
||||||
|
var rmap = editor.game.replacerRecord;
|
||||||
|
if (value instanceof Function) {
|
||||||
|
var guid_ = editor.util.guid()
|
||||||
|
rmap[guid_] = value.toString()
|
||||||
|
return guid_
|
||||||
|
} else if (value === null) {
|
||||||
|
// 为了包含plugins的新建
|
||||||
|
var guid_ = editor.util.guid()
|
||||||
|
rmap[guid_] = null
|
||||||
|
return guid_
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_game.prototype.replacerForSaving = function (_key, value) {
|
||||||
|
var rmap = editor.game.replacerRecord;
|
||||||
|
if (rmap.hasOwnProperty(value)) {
|
||||||
|
return rmap[value]
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_game.prototype.getValue = function (field) {
|
||||||
|
var rmap = editor.game.replacerRecord;
|
||||||
|
var value = eval(field)
|
||||||
|
if (rmap.hasOwnProperty(oldval)) {
|
||||||
|
return rmap[value]
|
||||||
|
} else {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_game.prototype.setValue = function (field, value) {
|
||||||
|
var rmap = editor.game.replacerRecord;
|
||||||
|
var oldval = eval(field)
|
||||||
|
if (rmap.hasOwnProperty(oldval)) {
|
||||||
|
rmap[value] = eval(value)
|
||||||
|
} else {
|
||||||
|
eval(field + '=' + value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_game.prototype.replacerWithoutRecord = function (_key, value) {
|
||||||
|
if (value instanceof Function) {
|
||||||
|
return value.toString()
|
||||||
|
} else return value
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_game.prototype.fixFunctionInGameData = function () {
|
||||||
|
var rf = editor.game.replacerWithoutRecord
|
||||||
|
core.floors = JSON.parse(JSON.stringify(core.floors, rf));
|
||||||
|
core.data = JSON.parse(JSON.stringify(core.data, rf));
|
||||||
|
data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = JSON.parse(JSON.stringify(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d, rf));
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////// 加载游戏数据相关 ////////////////////
|
||||||
|
|
||||||
|
// 初始化数字与地图图块的对应
|
||||||
|
editor_game.prototype.idsInit = function (maps, icons) {
|
||||||
|
editor.ids = [0];
|
||||||
|
editor.indexs = [];
|
||||||
|
var MAX_NUM = 0;
|
||||||
|
var keys = Object.keys(maps_90f36752_8815_4be8_b32b_d7fad1d0542e);
|
||||||
|
for (var ii = 0; ii < keys.length; ii++) {
|
||||||
|
var v = ~~keys[ii];
|
||||||
|
if (v > MAX_NUM && v < core.icons.tilesetStartOffset) MAX_NUM = v;
|
||||||
|
}
|
||||||
|
editor.MAX_NUM = MAX_NUM;
|
||||||
|
var getInfoById = function (id) {
|
||||||
|
var block = maps.initBlock(0, 0, id);
|
||||||
|
if (Object.prototype.hasOwnProperty.call(block, 'event')) {
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var point = 0;
|
||||||
|
for (var i = 0; i <= MAX_NUM; i++) {
|
||||||
|
var indexBlock = getInfoById(i);
|
||||||
|
editor.indexs[i] = [];
|
||||||
|
if (indexBlock) {
|
||||||
|
var id = indexBlock.event.id;
|
||||||
|
var indexId = indexBlock.id;
|
||||||
|
var allCls = Object.keys(icons);
|
||||||
|
if (i == 17) {
|
||||||
|
editor.ids.push({ 'idnum': 17, 'id': id, 'images': 'terrains' });
|
||||||
|
point++;
|
||||||
|
editor.indexs[i].push(point);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (var j = 0; j < allCls.length; j++) {
|
||||||
|
if (id in icons[allCls[j]]) {
|
||||||
|
editor.ids.push({ 'idnum': indexId, 'id': id, 'images': allCls[j], 'y': icons[allCls[j]][id] });
|
||||||
|
point++;
|
||||||
|
editor.indexs[i].push(point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
editor.indexs[0] = [0];
|
||||||
|
|
||||||
|
var startOffset = core.icons.tilesetStartOffset;
|
||||||
|
for (var i in core.tilesets) {
|
||||||
|
var imgName = core.tilesets[i];
|
||||||
|
var img = core.material.images.tilesets[imgName];
|
||||||
|
var width = Math.floor(img.width / 32), height = Math.floor(img.height / 32);
|
||||||
|
if (img.width % 32 || img.height % 32) {
|
||||||
|
// alert(imgName + '的长或宽不是32的整数倍, 请修改后刷新页面');
|
||||||
|
console.warn(imgName + '的长或宽不是32的整数倍, 请修改后刷新页面');
|
||||||
|
}
|
||||||
|
if (img.width * img.height > 32 * 32 * 3000) {
|
||||||
|
// alert(imgName + '上的图块数量超过了3000,请修改后刷新页面');
|
||||||
|
console.warn(imgName + '上的图块数量超过了3000,请修改后刷新页面');
|
||||||
|
}
|
||||||
|
for (var id = startOffset; id < startOffset + width * height; id++) {
|
||||||
|
var x = (id - startOffset) % width, y = parseInt((id - startOffset) / width);
|
||||||
|
var indexBlock = getInfoById(id);
|
||||||
|
editor.ids.push({ 'idnum': id, 'id': indexBlock.event.id, 'images': imgName, "x": x, "y": y, isTile: true });
|
||||||
|
point++;
|
||||||
|
editor.indexs[id] = [point];
|
||||||
|
}
|
||||||
|
startOffset += core.icons.tilesetStartOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前地图
|
||||||
|
editor_game.prototype.fetchMapFromCore = function () {
|
||||||
|
var mapArray = core.getMapArray(core.status.floorId);
|
||||||
|
editor.map = mapArray.map(function (v) {
|
||||||
|
return v.map(function (v) {
|
||||||
|
var x = parseInt(v), y = editor.indexs[x];
|
||||||
|
if (y == null) {
|
||||||
|
printe("素材数字" + x + "未定义。是不是忘了注册,或者接档时没有覆盖icons.js和maps.js?");
|
||||||
|
y = [0];
|
||||||
|
}
|
||||||
|
return editor.ids[y[0]]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
editor.currentFloorId = core.status.floorId;
|
||||||
|
editor.currentFloorData = core.floors[core.status.floorId];
|
||||||
|
// 补出缺省的数据
|
||||||
|
editor.currentFloorData.autoEvent = editor.currentFloorData.autoEvent || {};
|
||||||
|
//
|
||||||
|
for (var ii = 0, name; name = editor.dom.canvas[ii]; ii++) {
|
||||||
|
name += 'map';
|
||||||
|
var mapArray = editor.currentFloorData[name];
|
||||||
|
if (!mapArray || JSON.stringify(mapArray) == JSON.stringify([])) {//未设置或空数组
|
||||||
|
//与editor.map同形的全0
|
||||||
|
mapArray = eval('[' + Array(editor.map.length + 1).join('[' + Array(editor.map[0].length + 1).join('0,') + '],') + ']');
|
||||||
|
}
|
||||||
|
mapArray = core.maps._processInvalidMap(mapArray, editor.map[0].length, editor.map.length);
|
||||||
|
editor[name] = mapArray.map(function (v) {
|
||||||
|
return v.map(function (v) {
|
||||||
|
var x = parseInt(v), y = editor.indexs[x];
|
||||||
|
if (y == null) {
|
||||||
|
printe("素材数字" + x + "未定义。是不是忘了注册,或者接档时没有覆盖icons.js和maps.js?");
|
||||||
|
y = [0];
|
||||||
|
}
|
||||||
|
return editor.ids[y[0]]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取地图列表
|
||||||
|
editor_game.prototype.getFloorFileList = function (callback) {
|
||||||
|
// callback([Array<String>,err:String])
|
||||||
|
editor.util.checkCallback(callback);
|
||||||
|
/* editor.fs.readdir('project/floors',function(err, data){
|
||||||
|
callback([data,err]);
|
||||||
|
}); */
|
||||||
|
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);
|
193
_server/editor_listen.js
Normal file
193
_server/editor_listen.js
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
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.eui.onmouseout = editor.uifunctions.map_onmoveout
|
||||||
|
|
||||||
|
editor.dom.mid.onmousewheel = editor.uifunctions.map_mousewheel
|
||||||
|
|
||||||
|
editor.uivalues.shortcut = editor.config.get('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.iconLib.onmousemove = editor.uifunctions.material_onmove
|
||||||
|
editor.dom.iconLib.onmouseup = editor.uifunctions.material_onup
|
||||||
|
editor.dom.iconLib.oncontextmenu = function (e) { e.preventDefault() }
|
||||||
|
|
||||||
|
editor.dom.extraEvent.onmouseup = editor.uifunctions.extraEvent_click
|
||||||
|
editor.dom.chooseThis.onmouseup = editor.uifunctions.chooseThis_click
|
||||||
|
editor.dom.chooseInRight.onmouseup = editor.uifunctions.chooseInRight_click
|
||||||
|
editor.dom.copyLoc.onmouseup = editor.uifunctions.copyLoc_click
|
||||||
|
editor.dom.pasteLoc.onmouseup = editor.uifunctions.pasteLoc_click
|
||||||
|
editor.dom.clearEvent.onmouseup = editor.uifunctions.clearEvent_click
|
||||||
|
editor.dom.clearLoc.onmouseup = editor.uifunctions.clearLoc_click
|
||||||
|
editor.dom.undoFloor.onclick = editor.uifunctions.undoFloor_click
|
||||||
|
editor.dom.selectFloorBtn.onclick = editor.uifunctions.selectFloorBtn_click
|
||||||
|
editor.dom.editorTheme.onchange = editor.uifunctions.editorTheme_onchange
|
||||||
|
|
||||||
|
editor.dom.lastUsed.onmouseup = editor.uifunctions.lastUsed_click;
|
||||||
|
editor.dom.lastUsed.oncontextmenu = function (e) { e.preventDefault(); }
|
||||||
|
editor.dom.clearLastUsedBtn.onclick = editor.uifunctions.clearLastUsedBtn_click;
|
||||||
|
editor.dom.showMovable.onchange = editor.uifunctions.showMovable_onchange;
|
||||||
|
|
||||||
|
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;
|
||||||
|
if (editor.dom.brushMod4) editor.dom.brushMod4.onchange = editor.uifunctions.brushMod4_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()
|
||||||
|
|
||||||
|
window.onbeforeunload = function () {
|
||||||
|
var saveFloor = document.getElementById('saveFloor');
|
||||||
|
if (saveFloor && saveFloor.classList.contains('highlight')) {
|
||||||
|
return '你尚未保存地图,确定退出么?';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = 'z-index:110';
|
||||||
|
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 = 'z-index:110';
|
||||||
|
// 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.pasteLoc.ontouchstart = editor.dom.pasteLoc.onmousedown
|
||||||
|
editor.dom.pasteLoc.onmousedown = null
|
||||||
|
editor.dom.clearLoc.ontouchstart = editor.dom.clearLoc.onmousedown
|
||||||
|
editor.dom.clearLoc.onmousedown = null
|
||||||
|
|
||||||
|
// 不使用以下6语句, 会使得素材区手机无法拖动, 手机的框选素材只能放弃, 要通过弹框实现框选
|
||||||
|
// editor.dom.iconLib.ontouchstart = editor.dom.iconLib.onmousedown
|
||||||
|
// editor.dom.iconLib.onmousedown = null
|
||||||
|
// editor.dom.iconLib.ontouchmove = editor.dom.iconLib.onmousemove
|
||||||
|
// editor.dom.iconLib.onmousemove = null
|
||||||
|
// editor.dom.iconLib.ontouchend = editor.dom.iconLib.onmouseup
|
||||||
|
// editor.dom.iconLib.onmouseup = null
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.constructor.prototype.mode_listen = function (callback) {
|
||||||
|
|
||||||
|
// 这里的函数还没有写jsdoc, 通过_func()的方式先完成分类
|
||||||
|
|
||||||
|
editor.uifunctions.newIdIdnum_func()
|
||||||
|
editor.uifunctions.changeId_func()
|
||||||
|
editor.uifunctions.copyPasteEnemyItem_func();
|
||||||
|
|
||||||
|
editor.uifunctions.selectFloor_func()
|
||||||
|
editor.uifunctions.saveFloor_func()
|
||||||
|
editor.uifunctions.openDoc_func();
|
||||||
|
|
||||||
|
editor.uifunctions.newMap_func()
|
||||||
|
|
||||||
|
editor.uifunctions.createNewMaps_func()
|
||||||
|
|
||||||
|
editor.uifunctions.changeFloorId_func()
|
||||||
|
editor.uifunctions.changeFloorSize_func()
|
||||||
|
|
||||||
|
// editor.uifunctions.fixCtx_func()
|
||||||
|
editor.uifunctions.appendPic_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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1190
_server/editor_mappanel.js
Normal file
1190
_server/editor_mappanel.js
Normal file
File diff suppressed because it is too large
Load Diff
243
_server/editor_materialpanel.js
Normal file
243
_server/editor_materialpanel.js
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
editor_materialpanel_wrapper = function (editor) {
|
||||||
|
|
||||||
|
// 由于历史遗留原因, 以下变量作为全局变量使用
|
||||||
|
// selectBox
|
||||||
|
|
||||||
|
window.selectBox=document.getElementById('selectBox')
|
||||||
|
selectBox._isSelected=false
|
||||||
|
selectBox.isSelected=function(value){
|
||||||
|
if(value!=null){
|
||||||
|
selectBox._isSelected=value;
|
||||||
|
editor.dom.dataSelection.style.display=value?'':'none'
|
||||||
|
}
|
||||||
|
return selectBox._isSelected
|
||||||
|
}
|
||||||
|
|
||||||
|
var locToPos = function (loc) {
|
||||||
|
return { 'x': ~~(loc.x / loc.size), 'y': ~~(loc.y / loc.size) };
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (editor.uivalues.folded) {
|
||||||
|
if (confirm("你想要展开素材吗?\n展开模式下将显示全素材内容。")) {
|
||||||
|
editor.config.set('folded', false, function() {
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var perCol = parseInt(prompt("请输入折叠素材模式下每列的个数:", "50")) || 0;
|
||||||
|
if (perCol > 0) {
|
||||||
|
editor.config.set('foldPerCol', perCol, false);
|
||||||
|
editor.config.set('folded', true, function() {
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* editor.dom.iconLib.onmousedown
|
||||||
|
* 素材区的单击/拖拽事件
|
||||||
|
*/
|
||||||
|
editor.uifunctions.material_ondown = function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
editor.uivalues.lastMoveMaterE=e;
|
||||||
|
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;
|
||||||
|
editor.uivalues.startLoc={
|
||||||
|
'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,
|
||||||
|
'px': e.clientX,
|
||||||
|
'py': e.clientY,
|
||||||
|
'size': 32
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* editor.dom.iconLib.onmousemove
|
||||||
|
* 素材区的单击/拖拽事件
|
||||||
|
*/
|
||||||
|
editor.uifunctions.material_onmove = function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
editor.uivalues.lastMoveMaterE=e;
|
||||||
|
if (!editor.uivalues.startLoc) return;
|
||||||
|
var pos0 = locToPos(editor.uivalues.startLoc);
|
||||||
|
|
||||||
|
editor.dom.dataSelection.style.left = 32 * pos0.x + 'px';
|
||||||
|
editor.dom.dataSelection.style.top = 32 * pos0.y + 'px';
|
||||||
|
editor.dom.dataSelection.style.width = e.clientX - editor.uivalues.startLoc.px + 'px';
|
||||||
|
editor.dom.dataSelection.style.height = e.clientY - editor.uivalues.startLoc.py + 'px';
|
||||||
|
editor.dom.dataSelection.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* editor.dom.iconLib.onmouseup
|
||||||
|
* 素材区的单击/拖拽事件
|
||||||
|
*/
|
||||||
|
editor.uifunctions.material_onup = function (ee) {
|
||||||
|
var startLoc = editor.uivalues.startLoc;
|
||||||
|
editor.uivalues.startLoc = null;
|
||||||
|
|
||||||
|
var e=editor.uivalues.lastMoveMaterE;
|
||||||
|
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;
|
||||||
|
editor.uivalues.tileSize = [1,1];
|
||||||
|
var pos0 = locToPos(startLoc);
|
||||||
|
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.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 (editor.uivalues.folded) {
|
||||||
|
pos.y = Math.min(pos.y, imNames.length - 1);
|
||||||
|
pos.images = imNames[pos.y];
|
||||||
|
} else {
|
||||||
|
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 (spriter == 'terrains') col += 2;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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';
|
||||||
|
editor.dom.dataSelection.style.width = 32 - 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') y -= 2;
|
||||||
|
editor.info = { 'images': pos.images, 'y': y }
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var idindex = 0; idindex < editor.ids.length; idindex++) {
|
||||||
|
if ((core.tilesets.indexOf(pos.images) != -1 && editor.info.images == editor.ids[idindex].images
|
||||||
|
&& editor.info.y == editor.ids[idindex].y && editor.info.x == editor.ids[idindex].x)
|
||||||
|
|| (Object.prototype.hasOwnProperty.call(autotiles, pos.images) && editor.info.images == editor.ids[idindex].id
|
||||||
|
&& editor.info.y == editor.ids[idindex].y)
|
||||||
|
|| (core.tilesets.indexOf(pos.images) == -1 && editor.info.images == editor.ids[idindex].images
|
||||||
|
&& editor.info.y == editor.ids[idindex].y)
|
||||||
|
) {
|
||||||
|
|
||||||
|
editor.info = editor.ids[idindex];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editor.info.isTile && (editor.isMobile || e.button == 2)) { //这段改一改之类的应该能给手机用,就不删了
|
||||||
|
var v = prompt("请输入该额外素材区域绑定宽高,以逗号分隔", "1,1");
|
||||||
|
if (v != null && /^\d+,\d+$/.test(v)) {
|
||||||
|
v = v.split(",");
|
||||||
|
var x = parseInt(v[0]), y = parseInt(v[1]);
|
||||||
|
var widthX = editor.widthsX[editor.info.images];
|
||||||
|
if (x <= 0 || y <= 0 || editor.info.x + x > widthX[2] - widthX[1] || 32*(editor.info.y + y) > widthX[3]) {
|
||||||
|
alert("不合法的输入范围,已经越界");
|
||||||
|
} else {
|
||||||
|
editor.uivalues.tileSize = [x, y];
|
||||||
|
editor.dom.dataSelection.style.left = pos.x * 32 + 'px';
|
||||||
|
editor.dom.dataSelection.style.top = pos.y * ysize + 'px';
|
||||||
|
editor.dom.dataSelection.style.height = ysize*y - 6 + 'px';
|
||||||
|
editor.dom.dataSelection.style.width = 32*x - 6 + 'px';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (editor.info.isTile && !editor.isMobile && e.button != 2) { //左键拖拽框选
|
||||||
|
|
||||||
|
var x = pos.x-pos0.x+1, y = pos.y-pos0.y+1;
|
||||||
|
var widthX = editor.widthsX[editor.info.images];
|
||||||
|
// 懒得仔细处理了, 只允许左上往右下拉
|
||||||
|
if (x <= 0 || y <= 0 || pos0.x < widthX[1]){
|
||||||
|
|
||||||
|
} else {
|
||||||
|
editor.info = editor.ids[idindex-(x-1)-(y-1)*(widthX[2]-widthX[1])];
|
||||||
|
editor.uivalues.tileSize = [x, y];
|
||||||
|
editor.dom.dataSelection.style.left = pos0.x * 32 + 'px';
|
||||||
|
editor.dom.dataSelection.style.top = pos0.y * ysize + 'px';
|
||||||
|
editor.dom.dataSelection.style.height = ysize*y - 6 + 'px';
|
||||||
|
editor.dom.dataSelection.style.width = 32*x - 6 + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
editor.uifunctions.showBlockInfo(JSON.parse(JSON.stringify(editor.info)));
|
||||||
|
editor_mode.onmode('nextChange');
|
||||||
|
editor_mode.onmode('enemyitem');
|
||||||
|
editor.updateLastUsedMap();
|
||||||
|
//editor_mode.enemyitem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
371
_server/editor_mode.js
Normal file
371
_server/editor_mode.js
Normal file
@ -0,0 +1,371 @@
|
|||||||
|
editor_mode = function (editor) {
|
||||||
|
var core = editor.core;
|
||||||
|
|
||||||
|
function editor_mode() {
|
||||||
|
this.ids = {
|
||||||
|
'loc': 'left2',
|
||||||
|
'enemyitem': 'left3',
|
||||||
|
'floor': 'left4',
|
||||||
|
'tower': 'left5',
|
||||||
|
'functions': 'left8',
|
||||||
|
|
||||||
|
'map': 'left',
|
||||||
|
'appendpic': 'left1',
|
||||||
|
|
||||||
|
'commonevent': 'left9',
|
||||||
|
'plugins': 'left10',
|
||||||
|
}
|
||||||
|
this._ids = {}
|
||||||
|
this.dom = {}
|
||||||
|
this.actionList = [];
|
||||||
|
this.mode = 'tower'; // 初始默认显示全塔属性
|
||||||
|
this.info = {};
|
||||||
|
this.appendPic = {};
|
||||||
|
this.doubleClickMode = 'change';
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_mode.prototype.init = function (callback) {
|
||||||
|
if (Boolean(callback)) callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_mode.prototype.init_dom_ids = function (callback) {
|
||||||
|
|
||||||
|
Object.keys(editor_mode.ids).forEach(function (v) {
|
||||||
|
editor_mode.dom[v] = document.getElementById(editor_mode.ids[v]);
|
||||||
|
editor_mode._ids[editor_mode.ids[v]] = v;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Boolean(callback)) callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_mode.prototype.indent = function (field) {
|
||||||
|
var num = '\t';
|
||||||
|
if (field.indexOf("['main']") === 0) return 0;
|
||||||
|
if (field === "['special']") return 0;
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_mode.prototype.addAction = function (action) {
|
||||||
|
editor_mode.actionList.push(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_mode.prototype.doActionList = function (mode, actionList, callback) {
|
||||||
|
if (actionList.length == 0) return;
|
||||||
|
printf('修改中...');
|
||||||
|
var cb = function (objs_) {
|
||||||
|
if (objs_.slice(-1)[0] != null) {
|
||||||
|
printe(objs_.slice(-1)[0]);
|
||||||
|
throw (objs_.slice(-1)[0])
|
||||||
|
}
|
||||||
|
;
|
||||||
|
var str = '修改成功!';
|
||||||
|
if (data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.name == 'template')
|
||||||
|
str += '<br/>请注意:全塔属性的name尚未修改,请及时予以设置。';
|
||||||
|
if (mode == 'enemyitem') {
|
||||||
|
if (editor.info && editor.info.idnum) {
|
||||||
|
var block = editor.core.maps.blocksInfo[editor.info.idnum];
|
||||||
|
if (block.doorInfo != null && block.doorInfo.keys != null && Object.keys(block.doorInfo.keys).length > 0
|
||||||
|
&& block.trigger != 'openDoor') {
|
||||||
|
str += "<br/>你修改了门信息,但触发器未改成openDoor,请修改否则无法撞击开门。"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (editor_mode.info.images == 'enemys' || editor_mode.info.images == 'enemy48') {
|
||||||
|
if (core.getFaceDownId(editor_mode.info.id) != editor_mode.info.id) {
|
||||||
|
str += "<br/>绑定行走图朝向后只需要对应设置朝下怪物的属性,会自动同步而无需修改其他朝向的属性。"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf(str);
|
||||||
|
if (callback) callback();
|
||||||
|
}
|
||||||
|
switch (mode) {
|
||||||
|
case 'loc':
|
||||||
|
editor.file.editLoc(editor_mode.pos.x, editor_mode.pos.y, actionList, function (objs_) {
|
||||||
|
cb(objs_);
|
||||||
|
editor.drawPosSelection();
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'enemyitem':
|
||||||
|
if (editor_mode.info.images == 'enemys' || editor_mode.info.images == 'enemy48') {
|
||||||
|
editor.file.editEnemy(editor_mode.info.id, actionList, cb);
|
||||||
|
} else if (editor_mode.info.images == 'items') {
|
||||||
|
editor.file.editItem(editor_mode.info.id, actionList, cb);
|
||||||
|
} else {
|
||||||
|
editor.file.editMapBlocksInfo(editor_mode.info.idnum, actionList, cb);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'floor':
|
||||||
|
editor.file.editFloor(actionList, cb);
|
||||||
|
break;
|
||||||
|
case 'tower':
|
||||||
|
editor.file.editTower(actionList, cb);
|
||||||
|
break;
|
||||||
|
case 'functions':
|
||||||
|
editor.file.editFunctions(actionList, cb);
|
||||||
|
break;
|
||||||
|
case 'commonevent':
|
||||||
|
editor.file.editCommonEvent(actionList, cb);
|
||||||
|
break;
|
||||||
|
case 'plugins':
|
||||||
|
editor.file.editPlugins(actionList, cb);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_mode.prototype.onmode = function (mode, callback) {
|
||||||
|
if (editor_mode.mode != mode) {
|
||||||
|
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 = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_mode.prototype.showMode = function (mode) {
|
||||||
|
for (var name in this.dom) {
|
||||||
|
editor_mode.dom[name].style = 'z-index:-1;opacity: 0;';
|
||||||
|
}
|
||||||
|
editor_mode.dom[mode].style = '';
|
||||||
|
editor_mode.doubleClickMode = 'change';
|
||||||
|
// clear
|
||||||
|
editor.drawEventBlock();
|
||||||
|
if (editor_mode[mode]) editor_mode[mode]();
|
||||||
|
editor.dom.editModeSelect.value = mode;
|
||||||
|
if (!selectBox.isSelected()) editor.uifunctions.showTips();
|
||||||
|
}
|
||||||
|
|
||||||
|
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.checkImages = function (thiseval, directory) {
|
||||||
|
if (!directory) return true;
|
||||||
|
if (!editor_mode.checkUnique(thiseval)) return false;
|
||||||
|
fs.readdir(directory, function (err, data) {
|
||||||
|
if (err) {
|
||||||
|
printe(err);
|
||||||
|
throw Error(err);
|
||||||
|
}
|
||||||
|
var notExist = null;
|
||||||
|
thiseval.map(function (v) {
|
||||||
|
var name = v.indexOf('.') < 0 ? (v+'.png') : v;
|
||||||
|
if (data.indexOf(name) < 0) notExist = name;
|
||||||
|
return name;
|
||||||
|
});
|
||||||
|
if (notExist) {
|
||||||
|
alert('警告!图片' + notExist + '不存在!保存可能导致工程无法打开,请及时修改!');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
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;
|
||||||
|
editor_mode.pos = editor.pos;
|
||||||
|
document.getElementById('pos_a6771a78_a099_417c_828f_0a24851ebfce').innerText = editor_mode.pos.x + ',' + editor_mode.pos.y;
|
||||||
|
|
||||||
|
var objs = [];
|
||||||
|
editor.file.editLoc(editor_mode.pos.x, editor_mode.pos.y, [], function (objs_) {
|
||||||
|
objs = objs_;
|
||||||
|
//console.log(objs_)
|
||||||
|
});
|
||||||
|
//只查询不修改时,内部实现不是异步的,所以可以这么写
|
||||||
|
var tableinfo = editor.table.objToTable(objs[0], objs[1]);
|
||||||
|
document.getElementById('table_3d846fc4_7644_44d1_aa04_433d266a73df').innerHTML = tableinfo.HTML;
|
||||||
|
tableinfo.listen(tableinfo.guids);
|
||||||
|
editor.drawPosSelection();
|
||||||
|
if (Boolean(callback)) callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_mode.prototype.enemyitem = function (callback) {
|
||||||
|
//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 (!core.isset(editor_mode.info.id)) {
|
||||||
|
// document.getElementById('table_a3f03d4c_55b8_4ef6_b362_b345783acd72').innerHTML = '';
|
||||||
|
document.getElementById('newIdIdnum').style.display = 'block';
|
||||||
|
document.getElementById('enemyItemTable').style.display = 'none';
|
||||||
|
document.getElementById('changeId').style.display = 'none';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('newIdIdnum').style.display = 'none';
|
||||||
|
document.getElementById('enemyItemTable').style.display = 'block';
|
||||||
|
document.getElementById('changeId').style.display = 'block';
|
||||||
|
|
||||||
|
var objs = [];
|
||||||
|
if (editor_mode.info.images == 'enemys' || editor_mode.info.images == 'enemy48') {
|
||||||
|
editor.file.editEnemy(editor_mode.info.id, [], function (objs_) {
|
||||||
|
objs = objs_;
|
||||||
|
//console.log(objs_)
|
||||||
|
});
|
||||||
|
} else if (editor_mode.info.images == 'items') {
|
||||||
|
editor.file.editItem(editor_mode.info.id, [], function (objs_) {
|
||||||
|
objs = objs_;
|
||||||
|
//console.log(objs_)
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
/* document.getElementById('table_a3f03d4c_55b8_4ef6_b362_b345783acd72').innerHTML='';
|
||||||
|
return; */
|
||||||
|
editor.file.editMapBlocksInfo(editor_mode.info.idnum, [], function (objs_) {
|
||||||
|
objs = objs_;
|
||||||
|
//console.log(objs_)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
//只查询不修改时,内部实现不是异步的,所以可以这么写
|
||||||
|
var tableinfo = editor.table.objToTable(objs[0], objs[1]);
|
||||||
|
document.getElementById('table_a3f03d4c_55b8_4ef6_b362_b345783acd72').innerHTML = tableinfo.HTML;
|
||||||
|
tableinfo.listen(tableinfo.guids);
|
||||||
|
|
||||||
|
if (Boolean(callback)) callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_mode.prototype.floor = function (callback) {
|
||||||
|
var objs = [];
|
||||||
|
editor.file.editFloor([], function (objs_) {
|
||||||
|
objs = objs_;
|
||||||
|
//console.log(objs_)
|
||||||
|
});
|
||||||
|
//只查询不修改时,内部实现不是异步的,所以可以这么写
|
||||||
|
var tableinfo = editor.table.objToTable(objs[0], objs[1]);
|
||||||
|
document.getElementById('table_4a3b1b09_b2fb_4bdf_b9ab_9f4cdac14c74').innerHTML = tableinfo.HTML;
|
||||||
|
tableinfo.listen(tableinfo.guids);
|
||||||
|
if (Boolean(callback)) callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_mode.prototype.tower = function (callback) {
|
||||||
|
var objs = [];
|
||||||
|
editor.file.editTower([], function (objs_) {
|
||||||
|
objs = objs_;
|
||||||
|
//console.log(objs_)
|
||||||
|
});
|
||||||
|
//只查询不修改时,内部实现不是异步的,所以可以这么写
|
||||||
|
var tableinfo = editor.table.objToTable(objs[0], objs[1]);
|
||||||
|
document.getElementById('table_b6a03e4c_5968_4633_ac40_0dfdd2c9cde5').innerHTML = tableinfo.HTML;
|
||||||
|
tableinfo.listen(tableinfo.guids);
|
||||||
|
if (Boolean(callback)) callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_mode.prototype.functions = function (callback) {
|
||||||
|
var objs = [];
|
||||||
|
editor.file.editFunctions([], function (objs_) {
|
||||||
|
objs = objs_;
|
||||||
|
//console.log(objs_)
|
||||||
|
});
|
||||||
|
//只查询不修改时,内部实现不是异步的,所以可以这么写
|
||||||
|
var tableinfo = editor.table.objToTable(objs[0], objs[1]);
|
||||||
|
document.getElementById('table_e260a2be_5690_476a_b04e_dacddede78b3').innerHTML = tableinfo.HTML;
|
||||||
|
tableinfo.listen(tableinfo.guids);
|
||||||
|
if (Boolean(callback)) callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_mode.prototype.commonevent = function (callback) {
|
||||||
|
var objs = [];
|
||||||
|
editor.file.editCommonEvent([], function (objs_) {
|
||||||
|
objs = objs_;
|
||||||
|
//console.log(objs_)
|
||||||
|
});
|
||||||
|
//只查询不修改时,内部实现不是异步的,所以可以这么写
|
||||||
|
var tableinfo = editor.table.objToTable(objs[0], objs[1]);
|
||||||
|
document.getElementById('table_b7bf0124_99fd_4af8_ae2f_0017f04a7c7d').innerHTML = tableinfo.HTML;
|
||||||
|
tableinfo.listen(tableinfo.guids);
|
||||||
|
if (Boolean(callback)) callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_mode.prototype.plugins = function (callback) {
|
||||||
|
var objs = [];
|
||||||
|
editor.file.editPlugins([], function (objs_) {
|
||||||
|
objs = objs_;
|
||||||
|
//console.log(objs_)
|
||||||
|
});
|
||||||
|
//只查询不修改时,内部实现不是异步的,所以可以这么写
|
||||||
|
var tableinfo = editor.table.objToTable(objs[0], objs[1]);
|
||||||
|
document.getElementById('table_e2c034ec_47c6_48ae_8db8_4f8f32fea2d6').innerHTML = tableinfo.HTML;
|
||||||
|
tableinfo.listen(tableinfo.guids);
|
||||||
|
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_listen.js -> editor.constructor.prototype.mode_listen
|
||||||
|
}
|
||||||
|
|
||||||
|
var editor_mode = new editor_mode();
|
||||||
|
editor_mode.init_dom_ids();
|
||||||
|
|
||||||
|
return editor_mode;
|
||||||
|
}
|
||||||
|
//editor_mode = editor_mode(editor);
|
515
_server/editor_multi.js
Normal file
515
_server/editor_multi.js
Normal file
@ -0,0 +1,515 @@
|
|||||||
|
|
||||||
|
|
||||||
|
editor_multi = function () {
|
||||||
|
|
||||||
|
var editor_multi = {};
|
||||||
|
|
||||||
|
var extraKeys = {
|
||||||
|
"Ctrl-/": function (cm) { cm.toggleComment(); },
|
||||||
|
"Ctrl-B": function (cm) { ternServer.jumpToDef(cm); },
|
||||||
|
"Ctrl-Q": function (cm) { ternServer.rename(cm); },
|
||||||
|
"Cmd-F": CodeMirror.commands.findPersistent,
|
||||||
|
"Ctrl-F": CodeMirror.commands.findPersistent,
|
||||||
|
"Ctrl-R": CodeMirror.commands.replaceAll,
|
||||||
|
"Ctrl-D": function (cm) { cm.foldCode(cm.getCursor()); },
|
||||||
|
"Ctrl-O": function () { editor_multi.openUrl('/_docs/#/api'); },
|
||||||
|
"Ctrl-P": function () { editor_multi.openUrl('https://h5mota.com/plugins/'); }
|
||||||
|
};
|
||||||
|
|
||||||
|
var codeEditor = CodeMirror.fromTextArea(document.getElementById("multiLineCode"), {
|
||||||
|
lineNumbers: true,
|
||||||
|
matchBrackets: true,
|
||||||
|
indentUnit: 4,
|
||||||
|
tabSize: 4,
|
||||||
|
indentWithTabs: true,
|
||||||
|
smartIndent: true,
|
||||||
|
mode: { name: "javascript", globalVars: true, localVars: true },
|
||||||
|
lineWrapping: true,
|
||||||
|
continueComments: "Enter",
|
||||||
|
gutters: ["CodeMirror-lint-markers", "CodeMirror-linenumbers", "CodeMirror-foldgutter"],
|
||||||
|
lint: true,
|
||||||
|
autocomplete: true,
|
||||||
|
autoCloseBrackets: true,
|
||||||
|
styleActiveLine: true,
|
||||||
|
extraKeys: extraKeys,
|
||||||
|
foldGutter: true,
|
||||||
|
inputStyle: "textarea",
|
||||||
|
highlightSelectionMatches: { showToken: /\w/, annotateScrollbar: true }
|
||||||
|
});
|
||||||
|
|
||||||
|
var commandsName = {
|
||||||
|
'Ctrl-/': '注释当前选中行(Ctrl+/)',
|
||||||
|
'Ctrl-B': '跳转到定义(Ctrl+B)',
|
||||||
|
'Ctrl-Q': '重命名变量(Ctrl+Q)',
|
||||||
|
'Ctrl-F': '查找(Ctrl+F)',
|
||||||
|
'Ctrl-R': '全部替换(Ctrl+R)',
|
||||||
|
'Ctrl-D': '折叠或展开块(Ctrl+D)',
|
||||||
|
'Ctrl-O': '打开API列表(Ctrl+O)',
|
||||||
|
'Ctrl-P': '打开在线插件列表(Ctrl+P)'
|
||||||
|
};
|
||||||
|
|
||||||
|
document.getElementById('codemirrorCommands').innerHTML =
|
||||||
|
"<option value='' selected>执行操作...</option>" +
|
||||||
|
Object.keys(commandsName).map(function (name) {
|
||||||
|
return "<option value='" + name + "'>" + commandsName[name] + "</option>"
|
||||||
|
}).join('');
|
||||||
|
|
||||||
|
var coredef = terndefs_f6783a0a_522d_417e_8407_94c67b692e50[2];
|
||||||
|
Object.keys(core.material.enemys).forEach(function (name) {
|
||||||
|
coredef.core.material.enemys[name] = {
|
||||||
|
"!type": "enemy",
|
||||||
|
"!doc": core.material.enemys[name].name || "怪物"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.keys(core.material.bgms).forEach(function (name) {
|
||||||
|
coredef.core.material.bgms[name] = {
|
||||||
|
"!type": "audio",
|
||||||
|
"!doc": "背景音乐"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.keys(core.material.sounds).forEach(function (name) {
|
||||||
|
coredef.core.material.sounds[name] = {
|
||||||
|
"!type": "audio",
|
||||||
|
"!doc": "音效"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.keys(core.material.animates).forEach(function (name) {
|
||||||
|
coredef.core.material.animates[name] = {
|
||||||
|
"!type": "animate",
|
||||||
|
"!doc": "动画"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.keys(core.material.images).forEach(function (name) {
|
||||||
|
if (core.material.images[name] instanceof Image) {
|
||||||
|
coredef.core.material.images[name] = {
|
||||||
|
"!type": "image",
|
||||||
|
"!doc": "系统图片"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
coredef.core.material.images[name] = {
|
||||||
|
"!doc": name == 'autotile' ? '自动元件' : name == 'tilesets' ? '额外素材' : name == 'images' ? '自定义图片' : '系统图片'
|
||||||
|
}
|
||||||
|
for (var v in core.material.images[name]) {
|
||||||
|
coredef.core.material.images[name][v] = {
|
||||||
|
"!type": "image",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
Object.keys(core.material.items).forEach(function (name) {
|
||||||
|
coredef.core.material.items[name] = {
|
||||||
|
"!type": "item",
|
||||||
|
"!doc": core.material.items[name].name || "道具"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a.enemys.getSpecials().forEach(function (one) {
|
||||||
|
var name = one[1];
|
||||||
|
if (name instanceof Function) name = name({});
|
||||||
|
coredef.core.enemys.hasSpecial["!doc"] += name + "(" + one[0] + "); ";
|
||||||
|
});
|
||||||
|
Object.keys(core.canvas).forEach(function (name) {
|
||||||
|
coredef.core.canvas[name] = {
|
||||||
|
"!type": "CanvasRenderingContext2D",
|
||||||
|
"!doc": "系统画布"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.keys(core.status.maps).forEach(function (name) {
|
||||||
|
coredef.core.status.maps[name] = {
|
||||||
|
"!type": "floor",
|
||||||
|
"!doc": core.status.maps[name].title || ''
|
||||||
|
}
|
||||||
|
coredef.core.status.bgmaps[name] = {
|
||||||
|
"!type": "[[number]]",
|
||||||
|
"!doc": core.status.maps[name].title || ''
|
||||||
|
}
|
||||||
|
coredef.core.status.fgmaps[name] = {
|
||||||
|
"!type": "[[number]]",
|
||||||
|
"!doc": core.status.maps[name].title || ''
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.keys(core.status.shops).forEach(function (id) {
|
||||||
|
coredef.core.status.shops[id] = {
|
||||||
|
"!doc": core.status.shops[id].textInList || "全局商店"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.keys(core.status.textAttribute).forEach(function (id) {
|
||||||
|
coredef.core.status.textAttribute[id] = {};
|
||||||
|
});
|
||||||
|
// --- 转发函数
|
||||||
|
for (var name in coredef.core) {
|
||||||
|
if (typeof coredef.core[name] === 'object') {
|
||||||
|
for (var funcname in coredef.core[name]) {
|
||||||
|
var one = coredef.core[name][funcname] || {};
|
||||||
|
var type = one["!type"] || "";
|
||||||
|
if (type.startsWith("fn(")) {
|
||||||
|
var forwardname = (functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a[name] || {})[funcname] ? '脚本编辑' : name;
|
||||||
|
coredef.core[funcname] = {
|
||||||
|
"!type": one["!type"],
|
||||||
|
"!doc": one["!doc"] + "<br/>(转发到" + forwardname + "中)"
|
||||||
|
};
|
||||||
|
if (one["!url"]) coredef.core[funcname]["!url"] = one["!url"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var funcname in core[name]) {
|
||||||
|
if (!(core[name][funcname] instanceof Function) || funcname.charAt(0) == '_' || coredef.core[name][funcname]) continue;
|
||||||
|
var parameterInfo = /^\s*function\s*[\w_$]*\(([\w_,$\s]*)\)\s*\{/.exec(core[name][funcname].toString());
|
||||||
|
var parameters = (parameterInfo == null ? "" : parameterInfo[1])
|
||||||
|
.replace(/\s*/g, '').replace(/,/g, ', ').split(', ')
|
||||||
|
.filter(function (one) { return one.trim() != ''; })
|
||||||
|
.map(function (one) { return one.trim() + ': ?'; }).join(', ');
|
||||||
|
coredef.core[funcname] = coredef.core[name][funcname] = {
|
||||||
|
"!type": "fn(" + parameters + ")"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(core.values).forEach(function (id) {
|
||||||
|
var one = data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc._data.values._data[id];
|
||||||
|
if (!one) return;
|
||||||
|
coredef.core.values[id] = {
|
||||||
|
"!type": "number",
|
||||||
|
"!doc": one._data,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Object.keys(core.flags).forEach(function (id) {
|
||||||
|
var one = data_comment_c456ea59_6018_45ef_8bcc_211a24c627dc._data.flags._data[id];
|
||||||
|
if (!one) return;
|
||||||
|
coredef.core.flags[id] = {
|
||||||
|
"!type": id == 'statusBarItems' ? '[string]' : 'bool',
|
||||||
|
"!doc": one._data,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var ternServer = new CodeMirror.TernServer({
|
||||||
|
defs: terndefs_f6783a0a_522d_417e_8407_94c67b692e50,
|
||||||
|
plugins: {
|
||||||
|
doc_comment: true,
|
||||||
|
complete_strings: true,
|
||||||
|
},
|
||||||
|
useWorker: false
|
||||||
|
});
|
||||||
|
|
||||||
|
editor_multi.ternServer = ternServer;
|
||||||
|
editor_multi.codeEditor = codeEditor;
|
||||||
|
|
||||||
|
codeEditor.on("cursorActivity", function (cm) {
|
||||||
|
var cursor = cm.getCursor();
|
||||||
|
if (codeEditor.getOption("autocomplete") && !(cursor.line == 0 && cursor.ch == 0)) {
|
||||||
|
ternServer.updateArgHints(cm);
|
||||||
|
ternServer.showDocs(cm);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var ctrlRelease = new Date();
|
||||||
|
codeEditor.on("keyup", function (cm, event) {
|
||||||
|
var date = new Date();
|
||||||
|
if (event.keyCode == 17 || event.keyCode == 91) { // ctrl, cmd
|
||||||
|
ctrlRelease = date;
|
||||||
|
}
|
||||||
|
else if (codeEditor.getOption("autocomplete") && !event.ctrlKey && date - ctrlRelease >= 1000 && (
|
||||||
|
(event.keyCode >= 65 && event.keyCode <= 90) ||
|
||||||
|
(!event.shiftKey && event.keyCode == 190) || (event.shiftKey && event.keyCode == 189))) {
|
||||||
|
try {
|
||||||
|
ternServer.complete(cm);
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
editor_multi.id = '';
|
||||||
|
editor_multi.isString = false;
|
||||||
|
editor_multi.lintAutocomplete = false;
|
||||||
|
|
||||||
|
var lastOffset = {};
|
||||||
|
|
||||||
|
editor_multi.show = function () {
|
||||||
|
if (typeof (selectBox) !== typeof (undefined)) selectBox.isSelected(false);
|
||||||
|
var valueNow = codeEditor.getValue();
|
||||||
|
//try{eval('function _asdygakufyg_() { return '+valueNow+'\n}');editor_multi.lintAutocomplete=true;}catch(ee){}
|
||||||
|
if (valueNow.slice(0, 8) === 'function') editor_multi.lintAutocomplete = true;
|
||||||
|
editor_multi.setLint();
|
||||||
|
document.getElementById('left7').style = '';
|
||||||
|
}
|
||||||
|
editor_multi.hide = function () {
|
||||||
|
document.getElementById('left7').style = 'z-index:-1;opacity: 0;';
|
||||||
|
}
|
||||||
|
editor_multi.setLint = function () {
|
||||||
|
if (editor_multi.lintAutocomplete) {
|
||||||
|
codeEditor.setOption("lint", {
|
||||||
|
options: {
|
||||||
|
esversion: 2021
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
codeEditor.setOption("lint", false);
|
||||||
|
}
|
||||||
|
codeEditor.setOption("autocomplete", editor_multi.lintAutocomplete);
|
||||||
|
document.getElementById("lintCheckbox").checked = editor_multi.lintAutocomplete;
|
||||||
|
}
|
||||||
|
editor_multi.toggerLint = function () {
|
||||||
|
editor_multi.lintAutocomplete = document.getElementById("lintCheckbox").checked;
|
||||||
|
editor_multi.setLint();
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_multi.indent = function (field) {
|
||||||
|
if (typeof (editor) !== typeof (undefined) && editor && editor.mode && editor.mode.indent) return editor.mode.indent(field);
|
||||||
|
return '\t';
|
||||||
|
}
|
||||||
|
|
||||||
|
var _format = function () {
|
||||||
|
if (!editor_multi.lintAutocomplete) return;
|
||||||
|
var offset = (codeEditor.getScrollInfo() || {}).top || 0;
|
||||||
|
_setValue(beautifier.js(codeEditor.getValue(), {
|
||||||
|
brace_style: "collapse-preserve-inline",
|
||||||
|
indent_with_tabs: true,
|
||||||
|
jslint_happy: true
|
||||||
|
}));
|
||||||
|
codeEditor.scrollTo(0, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
var _setValue = function (val) {
|
||||||
|
codeEditor.setValue(val || '');
|
||||||
|
ternServer.delDoc('doc');
|
||||||
|
ternServer.addDoc('doc', new CodeMirror.Doc(val || '', 'javascript'));
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_multi.format = function () {
|
||||||
|
if (!editor_multi.lintAutocomplete) {
|
||||||
|
alert("只有代码才能进行格式化操作!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_format();
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_multi.hasError = function () {
|
||||||
|
if (!editor_multi.lintAutocomplete) return false;
|
||||||
|
return JSHINT.errors.filter(function (e) {
|
||||||
|
return e.code.startsWith("E")
|
||||||
|
}).length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var _previewButton = document.getElementById('editor_multi_preview');
|
||||||
|
|
||||||
|
_previewButton.onclick = function () {
|
||||||
|
if (!editor_multi.preview) return;
|
||||||
|
_format();
|
||||||
|
if (editor_multi.hasError()) {
|
||||||
|
alert("当前好像存在严重的语法错误,请处理后再预览。");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
editor.uievent.previewEditorMulti(editor_multi.preview, codeEditor.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_multi.import = function (id_, args) {
|
||||||
|
var thisTr = document.getElementById(id_);
|
||||||
|
if (!thisTr) return false;
|
||||||
|
var input = thisTr.children[2].children[0].children[0];
|
||||||
|
var field = thisTr.children[0].getAttribute('title');
|
||||||
|
var comment = thisTr.children[1].getAttribute('title');
|
||||||
|
if (!input.type || input.type !== 'textarea') return false;
|
||||||
|
editor_multi.id = id_;
|
||||||
|
editor_multi.isString = false;
|
||||||
|
editor_multi.lintAutocomplete = false;
|
||||||
|
editor_multi.preview = args.preview;
|
||||||
|
_previewButton.style.display = editor_multi.preview ? 'inline' : 'none';
|
||||||
|
if (args.lint === true) editor_multi.lintAutocomplete = true;
|
||||||
|
if ((!input.value || input.value == 'null') && args.template)
|
||||||
|
input.value = '"' + args.template + '"';
|
||||||
|
if ((!input.value || input.value == 'null') && editor_mode.mode == 'plugins')
|
||||||
|
input.value = '"function () {\\n\\t// 在此增加新插件\\n\\t\\n}"';
|
||||||
|
// if ((!input.value || input.value == 'null') && args)
|
||||||
|
if (input.value.slice(0, 1) === '"' || args.string) {
|
||||||
|
editor_multi.isString = true;
|
||||||
|
_setValue(JSON.parse(input.value) || '');
|
||||||
|
} else {
|
||||||
|
var num = editor_multi.indent(field);
|
||||||
|
eval('var tobj=' + (input.value || 'null'));
|
||||||
|
var tmap = {};
|
||||||
|
var tstr = JSON.stringify(tobj, function (k, v) {
|
||||||
|
if (typeof (v) === typeof ('') && v.slice(0, 8) === 'function') {
|
||||||
|
var id_ = editor.util.guid();
|
||||||
|
tmap[id_] = v.toString();
|
||||||
|
return id_;
|
||||||
|
} else return v
|
||||||
|
}, num);
|
||||||
|
for (var id_ in tmap) {
|
||||||
|
tstr = tstr.replace('"' + id_ + '"', tmap[id_])
|
||||||
|
}
|
||||||
|
_setValue(tstr || '');
|
||||||
|
}
|
||||||
|
editor_multi.show();
|
||||||
|
codeEditor.scrollTo(0, lastOffset[editor_multi.id] || 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_multi.cancel = function () {
|
||||||
|
if (editor_multi.id && editor_multi.id != 'callFromBlockly' && editor_multi.id != 'importFile') {
|
||||||
|
lastOffset[editor_multi.id] = (codeEditor.getScrollInfo() || {}).top;
|
||||||
|
}
|
||||||
|
editor_multi.hide();
|
||||||
|
editor_multi.id = '';
|
||||||
|
multiLineArgs = [null, null, null];
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_multi.confirm = function (keep) {
|
||||||
|
if (editor_multi.hasError()) {
|
||||||
|
alert("当前好像存在严重的语法错误,请处理后再保存。\n严重的语法错误可能会导致整个编辑器的崩溃。");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!editor_multi.id) {
|
||||||
|
editor_multi.id = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editor_multi.id === 'callFromBlockly') {
|
||||||
|
// ----- 自动格式化
|
||||||
|
_format();
|
||||||
|
editor_multi.multiLineDone(keep);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editor_multi.id === 'importFile') {
|
||||||
|
_format();
|
||||||
|
editor_multi.writeFileDone(keep);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var setvalue = function (value) {
|
||||||
|
var thisTr = document.getElementById(editor_multi.id);
|
||||||
|
var input = thisTr.children[2].children[0].children[0];
|
||||||
|
if (editor_multi.isString) {
|
||||||
|
input.value = JSON.stringify(value);
|
||||||
|
} else {
|
||||||
|
eval('var tobj=' + (value || 'null'));
|
||||||
|
var tmap = {};
|
||||||
|
var tstr = JSON.stringify(tobj, function (k, v) {
|
||||||
|
if (v instanceof Function) {
|
||||||
|
var id_ = editor.util.guid();
|
||||||
|
tmap[id_] = v.toString();
|
||||||
|
return id_;
|
||||||
|
} else return v
|
||||||
|
}, 4);
|
||||||
|
for (var id_ in tmap) {
|
||||||
|
tstr = tstr.replace('"' + id_ + '"', JSON.stringify(tmap[id_]))
|
||||||
|
}
|
||||||
|
input.value = tstr;
|
||||||
|
}
|
||||||
|
if (!keep) {
|
||||||
|
editor_multi.id = '';
|
||||||
|
editor_multi.hide();
|
||||||
|
} else {
|
||||||
|
alert('写入成功!');
|
||||||
|
}
|
||||||
|
input.onchange();
|
||||||
|
}
|
||||||
|
lastOffset[editor_multi.id] = (codeEditor.getScrollInfo() || {}).top;
|
||||||
|
// ----- 自动格式化
|
||||||
|
_format();
|
||||||
|
setvalue(codeEditor.getValue() || '');
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_multi.doCommand = function (select) {
|
||||||
|
var value = select.value;
|
||||||
|
select.selectedIndex = 0;
|
||||||
|
if (extraKeys[value]) {
|
||||||
|
extraKeys[value](codeEditor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_multi.openUrl = function (url) {
|
||||||
|
if (editor.isMobile && !confirm('你确定要离开本页面么?')) return;
|
||||||
|
window.open(url, '_blank');
|
||||||
|
}
|
||||||
|
|
||||||
|
var multiLineArgs = [null, null, null];
|
||||||
|
editor_multi.multiLineEdit = function (value, b, f, args, callback) {
|
||||||
|
editor_multi.id = 'callFromBlockly';
|
||||||
|
_setValue(value.split('\\n').join('\n') || '');
|
||||||
|
multiLineArgs[0] = b;
|
||||||
|
multiLineArgs[1] = f;
|
||||||
|
multiLineArgs[2] = callback;
|
||||||
|
editor_multi.lintAutocomplete = Boolean(args.lint);
|
||||||
|
editor_multi.show();
|
||||||
|
}
|
||||||
|
editor_multi.multiLineDone = function (keep) {
|
||||||
|
if (!multiLineArgs[0] || !multiLineArgs[1] || !multiLineArgs[2]) return;
|
||||||
|
var newvalue = codeEditor.getValue() || '';
|
||||||
|
multiLineArgs[2](newvalue, multiLineArgs[0], multiLineArgs[1])
|
||||||
|
if (!keep) {
|
||||||
|
editor_multi.id = '';
|
||||||
|
editor_multi.hide();
|
||||||
|
} else {
|
||||||
|
alert('写入成功!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var _fileValues = ['']
|
||||||
|
editor_multi.importFile = function (filename) {
|
||||||
|
editor_multi.id = 'importFile'
|
||||||
|
_fileValues[0] = filename
|
||||||
|
_setValue('loading')
|
||||||
|
editor_multi.show();
|
||||||
|
fs.readFile(filename, 'base64', function (e, d) {
|
||||||
|
if (e) {
|
||||||
|
_setValue('加载文件失败:\n' + e)
|
||||||
|
editor_multi.id = ''
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var str = editor.util.decode64(d)
|
||||||
|
_setValue(str)
|
||||||
|
_fileValues[1] = str
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_multi.writeFileDone = function (keep) {
|
||||||
|
fs.writeFile(_fileValues[0], editor.util.encode64(codeEditor.getValue() || ''), 'base64', function (err, data) {
|
||||||
|
if (err) printe('文件写入失败,请手动粘贴至' + _fileValues[0] + '\n' + err);
|
||||||
|
else {
|
||||||
|
if (!keep) {
|
||||||
|
editor_multi.id = '';
|
||||||
|
editor_multi.hide();
|
||||||
|
} else {
|
||||||
|
alert('写入成功!');
|
||||||
|
}
|
||||||
|
printf(_fileValues[0] + " 写入成功,F5刷新后生效");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_multi.editCommentJs = function (mod) {
|
||||||
|
var dict = {
|
||||||
|
loc: '_server/table/comment.js',
|
||||||
|
enemyitem: '_server/table/comment.js',
|
||||||
|
floor: '_server/table/comment.js',
|
||||||
|
tower: '_server/table/data.comment.js',
|
||||||
|
functions: '_server/table/functions.comment.js',
|
||||||
|
commonevent: '_server/table/events.comment.js',
|
||||||
|
plugins: '_server/table/plugins.comment.js',
|
||||||
|
}
|
||||||
|
editor_multi.lintAutocomplete = true
|
||||||
|
editor_multi.setLint()
|
||||||
|
editor_multi.importFile(dict[mod])
|
||||||
|
}
|
||||||
|
|
||||||
|
// 字体大小
|
||||||
|
{
|
||||||
|
const CONFIG_KEY = "editor_multi.fontSize";
|
||||||
|
let fontsize = editor.config.get(CONFIG_KEY, 14);
|
||||||
|
const input = document.getElementById("editor_multi_fontsize");
|
||||||
|
const check = document.getElementById("editor_multi_fontweight")
|
||||||
|
input.value = fontsize;
|
||||||
|
editor_multi.setFontSize = function () {
|
||||||
|
const value = Number(input.value);
|
||||||
|
editor.config.set(CONFIG_KEY, value);
|
||||||
|
const ele = codeEditor.getWrapperElement()
|
||||||
|
ele.style.fontSize = `${value}px`;
|
||||||
|
ele.style.fontWeight = `${check.checked ? 'bold' : 'normal'}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return editor_multi;
|
||||||
|
}
|
||||||
|
//editor_multi=editor_multi();
|
602
_server/editor_table.js
Normal file
602
_server/editor_table.js
Normal file
@ -0,0 +1,602 @@
|
|||||||
|
editor_table_wrapper = function (editor) {
|
||||||
|
|
||||||
|
editor_table = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// HTML模板
|
||||||
|
|
||||||
|
editor_table.prototype.select = function (value, values) {
|
||||||
|
if (values.indexOf(value) < 0) values = [value].concat(values);
|
||||||
|
var content = values.map(function (v) {
|
||||||
|
return editor.table.option(v, v == value)
|
||||||
|
}).join('')
|
||||||
|
return /* html */`<select>\n${content}</select>\n`
|
||||||
|
}
|
||||||
|
editor_table.prototype.option = function (value, selected) {
|
||||||
|
return /* html */`<option value='${JSON.stringify(value)}' ${selected ? 'selected' : ''}>${JSON.stringify(value)}</option>\n`
|
||||||
|
}
|
||||||
|
editor_table.prototype.text = function (value) {
|
||||||
|
return /* html */`<input type='text' spellcheck='false' value='${JSON.stringify(value)}'/>\n`
|
||||||
|
}
|
||||||
|
editor_table.prototype.checkbox = function (value) {
|
||||||
|
return /* html */`<input type='checkbox' class='checkbox' ${(value ? 'checked ' : '')}/>\n`
|
||||||
|
}
|
||||||
|
editor_table.prototype.textarea = function (value, indent, disable) {
|
||||||
|
return /* html */`<textarea spellcheck='false' ${disable ? 'disabled readonly' : ''}>${JSON.stringify(value, null, indent || 0)}</textarea>\n`
|
||||||
|
}
|
||||||
|
editor_table.prototype.checkboxSet = function (value, keys, prefixStrings) {
|
||||||
|
if (value == null) value = [];
|
||||||
|
if (!(value instanceof Array)) {
|
||||||
|
if (value == 0) value = [];
|
||||||
|
else value = [value];
|
||||||
|
}
|
||||||
|
keys=Array.from(keys)
|
||||||
|
prefixStrings=Array.from(prefixStrings)
|
||||||
|
for (var index = 0; index < value.length; index++) {
|
||||||
|
if (keys.indexOf(value[index])==-1) {
|
||||||
|
keys.push(value[index])
|
||||||
|
prefixStrings.push('<br>'+value[index]+': ')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var content=[]
|
||||||
|
for (var index = 0; index < keys.length; index++) {
|
||||||
|
content.push(editor.table.checkboxSetMember(value.indexOf(keys[index])!=-1,keys[index],prefixStrings[index]))
|
||||||
|
}
|
||||||
|
return /* html */`<div class='checkboxSet'>${content.join('')}</div>\n`;
|
||||||
|
}
|
||||||
|
editor_table.prototype.checkboxSetMember = function (value,key,prefixString) {
|
||||||
|
return /* html */`${prefixString}<input key='${key}' ctype='${typeof key}' type='checkbox' class='checkboxSetMember' onchange='editor.table.checkboxSetMemberOnchange(this)' ${(value ? 'checked ' : '')}/>\n`;
|
||||||
|
}
|
||||||
|
editor_table.prototype.editGrid = function (showComment, type) {
|
||||||
|
var list = [];
|
||||||
|
if (showComment) list.push("<button onclick='editor.table.onCommentBtnClick(this)'>注释</button>");
|
||||||
|
if (type != 'select' && type != 'checkbox' && type != 'checkboxSet' && type != 'popCheckboxSet' && type != 'disable')
|
||||||
|
list.push("<button onclick='editor.table.onEditBtnClick(this)' class='editorTableEditBtn'>编辑</button>");
|
||||||
|
if (type == 'popCheckboxSet')
|
||||||
|
list.push("<button onclick='editor.table.onEditBtnClick(this)' class='editorTableEditBtn'>多选框编辑</button>");
|
||||||
|
if (type == 'disable') list.push("<button onclick='editor.table.onCopyBtnClick(this)'>复制</button>");
|
||||||
|
return list.join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_table.prototype.title = function () {
|
||||||
|
return /* html */`\n<tr><td>条目</td><td>注释</td><td>值</td><td>操作</td></tr>\n`
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_table.prototype.gap = function (field) {
|
||||||
|
var tokenlist = field.slice(2, -2).split("']['");
|
||||||
|
var rule = tokenlist.join("-");
|
||||||
|
tokenlist.pop();
|
||||||
|
var self = tokenlist.join("-");
|
||||||
|
var status = !!tokenPool[rule];
|
||||||
|
return /* html */`<tr data-gap="${rule}" data-field="${self}">
|
||||||
|
<td>----</td>
|
||||||
|
<td>----</td>
|
||||||
|
<td>${field}</td>
|
||||||
|
<td><button class='editorTableFoldBtn' onclick='editor.table.onFoldBtnClick(this)' data-fold="${ status ? "true" : "false" }">${ status ? "展开" : "折叠" }</button></td>
|
||||||
|
</tr>\n`
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_table.prototype.tr = function (guid, field, shortField, commentHTMLescape, cobjstr, shortComment, tdstr, type) {
|
||||||
|
return /* html */`<tr id="${guid}" data-field="${field.slice(2, -2).split("']['").join("-")}">
|
||||||
|
<td title="${field}">${shortField}</td>
|
||||||
|
<td title="${commentHTMLescape}" cobj="${cobjstr}">${shortComment || commentHTMLescape}</td>
|
||||||
|
<td><div class="etableInputDiv ${type}">${tdstr}</div></td>
|
||||||
|
<td>${editor.table.editGrid(shortComment, type)}</td>
|
||||||
|
</tr>\n`
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checkboxset中checkbox的onchange
|
||||||
|
* 这个函数本质是模板editor_table.prototype.checkboxSetMember的一部分
|
||||||
|
* 故放在HTML模板分类下
|
||||||
|
*/
|
||||||
|
editor_table.prototype.checkboxSetMemberOnchange = function (onemember) {
|
||||||
|
var thisset=onemember.parentNode
|
||||||
|
var inputs=thisset.children
|
||||||
|
var value=[]
|
||||||
|
for (var i in inputs) {
|
||||||
|
if (inputs[i].nodeName == 'INPUT') {
|
||||||
|
if (inputs[i].checked) {
|
||||||
|
var one = inputs[i].getAttribute('key');
|
||||||
|
if (inputs[i].getAttribute('ctype') == 'number') one = parseFloat(one);
|
||||||
|
value.push(one);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
thiseval = value;
|
||||||
|
// if (value.length == 0) thiseval = null;
|
||||||
|
thisset.value=JSON.stringify(thiseval)
|
||||||
|
thisset.onchange()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 表格生成的控制
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注释对象的默认值
|
||||||
|
*/
|
||||||
|
editor_table.prototype.defaultcobj = {
|
||||||
|
// 默认是文本域
|
||||||
|
_type: 'textarea',
|
||||||
|
_data: '',
|
||||||
|
_string: function (args) {//object~[field,cfield,vobj,cobj]
|
||||||
|
var thiseval = args.vobj;
|
||||||
|
return (typeof (thiseval) === typeof ('')) && thiseval[0] === '"';
|
||||||
|
},
|
||||||
|
// 默认情况下 非对象和数组的视为叶节点
|
||||||
|
_leaf: function (args) {//object~[field,cfield,vobj,cobj]
|
||||||
|
var thiseval = args.vobj;
|
||||||
|
if (thiseval == null || thiseval == undefined) return true;//null,undefined
|
||||||
|
if (typeof (thiseval) === typeof ('')) return true;//字符串
|
||||||
|
if (Object.keys(thiseval).length === 0) return true;//数字,true,false,空数组,空对象
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 把来自数据文件的obj和来自*comment.js的commentObj组装成表格
|
||||||
|
* commentObj在无视['_data']的意义下与obj同形
|
||||||
|
* 即: commentObj['_data']['a']['_data']['b'] 与 obj['a']['b'] 是对应的
|
||||||
|
* 在此意义下, 两者的结构是一致的
|
||||||
|
* 在commentObj没有被定义的obj的分支, 会取defaultcobj作为默认值
|
||||||
|
* 因此在深度优先遍历时,维护
|
||||||
|
* field="['a']['b']"
|
||||||
|
* cfield="['_data']['a']['_data']['b']"
|
||||||
|
* vobj=obj['a']['b']
|
||||||
|
* cobj=commentObj['_data']['a']['_data']['b']
|
||||||
|
* cobj
|
||||||
|
* cobj = Object.assign({}, defaultcobj, pcobj['_data'][ii])
|
||||||
|
* 每一项若未定义,就从defaultcobj中取
|
||||||
|
* 当其是函数不是具体值时,把args = {field: field, cfield: cfield, vobj: vobj, cobj: cobj}代入算出该值
|
||||||
|
* 得到的叶节点的<tr>结构如下
|
||||||
|
* tr>td[title=field]
|
||||||
|
* >td[title=comment,cobj=cobj:json]
|
||||||
|
* >td>div>input[value=thiseval]
|
||||||
|
* 返回结果
|
||||||
|
* 返回一个对象, 假设被命名为tableinfo
|
||||||
|
* 在把一个 table 的 innerHTML 赋值为 tableinfo.HTML 后
|
||||||
|
* 再调 tableinfo.listen(tableinfo.guids) 进行绑定事件
|
||||||
|
* @param {Object} obj
|
||||||
|
* @param {Object} commentObj
|
||||||
|
* @returns {{"HTML":String,"guids":String[],"listen":Function}}
|
||||||
|
*/
|
||||||
|
editor_table.prototype.objToTable = function (obj, commentObj) {
|
||||||
|
// 表格抬头
|
||||||
|
var outstr = [editor.table.title()];
|
||||||
|
var guids = [];
|
||||||
|
var defaultcobj = this.defaultcobj
|
||||||
|
/**
|
||||||
|
* 深度优先遍历, p*即为父节点的四个属性
|
||||||
|
* @param {String} pfield
|
||||||
|
* @param {String} pcfield
|
||||||
|
* @param {Object} pvobj
|
||||||
|
* @param {Object} pcobj
|
||||||
|
*/
|
||||||
|
var recursionParse = function (pfield, pcfield, pvobj, pcobj) {
|
||||||
|
var keysForTableOrder = {};
|
||||||
|
var voidMark = {};
|
||||||
|
// 1. 按照pcobj排序生成
|
||||||
|
if (pcobj && pcobj['_data']) {
|
||||||
|
for (var ii in pcobj['_data']) keysForTableOrder[ii] = voidMark;
|
||||||
|
}
|
||||||
|
// 2. 对每个pvobj且不在pcobj的,再添加到最后
|
||||||
|
keysForTableOrder = Object.assign(keysForTableOrder, pvobj)
|
||||||
|
for (var ii in keysForTableOrder) {
|
||||||
|
// 3. 对于pcobj有但是pvobj中没有的, 弹出提示, (正常情况下editor_file会补全成null)
|
||||||
|
// 事实上能执行到这一步工程没崩掉打不开,就继续吧..
|
||||||
|
if (keysForTableOrder[ii] === voidMark) {
|
||||||
|
if (typeof id_815975ad_ee6f_4684_aac7_397b7e392702 === "undefined") {
|
||||||
|
// alert('comment和data不匹配,请在群 HTML5造塔技术交流群 959329661 内反馈')
|
||||||
|
console.error('comment和data不匹配,请在群 HTML5造塔技术交流群 959329661 内反馈')
|
||||||
|
id_815975ad_ee6f_4684_aac7_397b7e392702 = 1;
|
||||||
|
}
|
||||||
|
pvobj[ii] = null;
|
||||||
|
}
|
||||||
|
var field = pfield + "['" + ii + "']";
|
||||||
|
var cfield = pcfield + "['_data']['" + ii + "']";
|
||||||
|
var vobj = pvobj[ii];
|
||||||
|
var cobj = null;
|
||||||
|
if (pcobj && pcobj['_data'] && pcobj['_data'][ii]) {
|
||||||
|
// cobj存在时直接取
|
||||||
|
cobj = Object.assign({}, defaultcobj, pcobj['_data'][ii]);
|
||||||
|
} else {
|
||||||
|
// 当其函数时代入参数算出cobj, 不存在时只取defaultcobj
|
||||||
|
if (pcobj && (pcobj['_data'] instanceof Function)) cobj = Object.assign({}, defaultcobj, pcobj['_data'](ii));
|
||||||
|
else cobj = Object.assign({}, defaultcobj);
|
||||||
|
}
|
||||||
|
var args = { field: field, cfield: cfield, vobj: vobj, cobj: cobj }
|
||||||
|
// 当cobj的参数为函数时,代入args算出值
|
||||||
|
for (var key in cobj) {
|
||||||
|
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) {
|
||||||
|
// 不是叶节点时, 插入展开的标记并继续遍历, 此处可以改成按钮用来添加新项或折叠等
|
||||||
|
outstr.push(editor.table.gap(field));
|
||||||
|
recursionParse(field, cfield, vobj, cobj);
|
||||||
|
} else {
|
||||||
|
// 是叶节点时, 调objToTr_渲染<tr>
|
||||||
|
var leafnode = editor.table.objToTr(obj, commentObj, field, cfield, vobj, cobj);
|
||||||
|
outstr.push(leafnode[0]);
|
||||||
|
guids.push(leafnode[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 开始遍历
|
||||||
|
recursionParse("", "", obj, commentObj);
|
||||||
|
|
||||||
|
var listen = function (guids) {
|
||||||
|
// 每个叶节点的事件绑定
|
||||||
|
var tableid = editor.util.guid();
|
||||||
|
editor.mode.currentTable=tableid;
|
||||||
|
guids.forEach(function (guid) {
|
||||||
|
editor.table.guidListen(guid, tableid, obj, commentObj)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return { "HTML": outstr.join(''), "guids": guids, "listen": listen };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回叶节点<tr>形如
|
||||||
|
* tr>td[title=field]
|
||||||
|
* >td[title=comment,cobj=cobj:json]
|
||||||
|
* >td>div>input[value=thiseval]
|
||||||
|
* 参数意义在 objToTable 中已解释
|
||||||
|
* @param {Object} obj
|
||||||
|
* @param {Object} commentObj
|
||||||
|
* @param {String} field
|
||||||
|
* @param {String} cfield
|
||||||
|
* @param {Object} vobj
|
||||||
|
* @param {Object} cobj
|
||||||
|
*/
|
||||||
|
editor_table.prototype.objToTr = function (obj, commentObj, field, cfield, vobj, cobj) {
|
||||||
|
var guid = editor.util.guid();
|
||||||
|
var thiseval = vobj;
|
||||||
|
var comment = String(cobj._data);
|
||||||
|
|
||||||
|
// var charlength = 15;
|
||||||
|
// "['a']['b']" => "b"
|
||||||
|
var shortField = field.split("']").slice(-2)[0].split("['").slice(-1)[0];
|
||||||
|
// 把长度超过 charlength 的字符改成 固定长度+...的形式
|
||||||
|
// shortField = (shortField.length < charlength ? shortField : shortField.slice(0, charlength) + '...');
|
||||||
|
|
||||||
|
// 完整的内容转义后供悬停查看
|
||||||
|
var commentHTMLescape = editor.util.HTMLescape(comment);
|
||||||
|
// 把长度超过 charlength 的字符改成 固定长度+...的形式
|
||||||
|
// var shortCommentHTMLescape = (comment.length < charlength ? commentHTMLescape : editor.util.HTMLescape(comment.slice(0, charlength)) + '...');
|
||||||
|
|
||||||
|
var cobjstr = Object.assign({}, cobj);
|
||||||
|
delete cobjstr._data;
|
||||||
|
// 把cobj塞到第二个td的[cobj]中, 方便绑定事件时取
|
||||||
|
cobjstr = editor.util.HTMLescape(JSON.stringify(cobjstr));
|
||||||
|
|
||||||
|
var tdstr = editor.table.objToTd(obj, commentObj, field, cfield, vobj, cobj)
|
||||||
|
var outstr = editor.table.tr(guid, field, shortField, commentHTMLescape, cobjstr, cobj._docs, tdstr, cobj._type)
|
||||||
|
return [outstr, guid];
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_table.prototype.objToTd = function (obj, commentObj, field, cfield, vobj, cobj) {
|
||||||
|
var thiseval = vobj;
|
||||||
|
switch (cobj._type) {
|
||||||
|
case 'select':
|
||||||
|
return editor.table.select(thiseval, cobj._select.values);
|
||||||
|
case 'checkbox':
|
||||||
|
return editor.table.checkbox(thiseval);
|
||||||
|
case 'checkboxSet':
|
||||||
|
return editor.table.checkboxSet(thiseval, cobj._checkboxSet.key, cobj._checkboxSet.prefix);
|
||||||
|
default:
|
||||||
|
return editor.table.textarea(thiseval, cobj.indent || 0, cobj._type == 'disable');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 表格的用户交互
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查一个值是否允许被设置为当前输入
|
||||||
|
* @param {Object} cobj
|
||||||
|
* @param {*} thiseval
|
||||||
|
*/
|
||||||
|
editor_table.prototype.checkRange = function (cobj, thiseval) {
|
||||||
|
if (cobj._range) {
|
||||||
|
return eval(cobj._range);
|
||||||
|
}
|
||||||
|
if (cobj._select) {
|
||||||
|
return cobj._select.values.indexOf(thiseval) !== -1;
|
||||||
|
}
|
||||||
|
if (cobj._bool) {
|
||||||
|
return [true, false].indexOf(thiseval) !== -1;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监听一个guid对应的表格项
|
||||||
|
* @param {String} guid
|
||||||
|
*/
|
||||||
|
editor_table.prototype.guidListen = function (guid, tableid, obj, commentObj) {
|
||||||
|
// tr>td[title=field]
|
||||||
|
// >td[title=comment,cobj=cobj:json]
|
||||||
|
// >td>div>input[value=thiseval]
|
||||||
|
var thisTr = document.getElementById(guid);
|
||||||
|
var input = thisTr.children[2].children[0].children[0];
|
||||||
|
var field = thisTr.children[0].getAttribute('title');
|
||||||
|
var cobj = JSON.parse(thisTr.children[1].getAttribute('cobj'));
|
||||||
|
var modeNode = thisTr.parentNode;
|
||||||
|
thisTr.setAttribute('tableid',tableid)
|
||||||
|
while (!editor_mode._ids.hasOwnProperty(modeNode.getAttribute('id'))) {
|
||||||
|
modeNode = modeNode.parentNode;
|
||||||
|
}
|
||||||
|
input.onchange = function () {
|
||||||
|
editor.table.onchange(guid, obj, commentObj, thisTr, input, field, cobj, modeNode)
|
||||||
|
}
|
||||||
|
// 用检测两次单击的方式来实现双击(以支持手机端的双击)
|
||||||
|
var doubleClickCheck = [0];
|
||||||
|
thisTr.onclick = function () {
|
||||||
|
var newClick = new Date().getTime();
|
||||||
|
var lastClick = doubleClickCheck.shift();
|
||||||
|
doubleClickCheck.push(newClick);
|
||||||
|
if (newClick - lastClick < 500) {
|
||||||
|
editor.table.dblclickfunc(guid, obj, commentObj, thisTr, input, field, cobj, modeNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表格的值变化时
|
||||||
|
*/
|
||||||
|
editor_table.prototype.onchange = function (guid, obj, commentObj, thisTr, input, field, cobj, modeNode) {
|
||||||
|
editor_mode.onmode(editor_mode._ids[modeNode.getAttribute('id')]);
|
||||||
|
if (editor.mode.currentTable!=thisTr.getAttribute('tableid')) return;
|
||||||
|
var thiseval = null;
|
||||||
|
if (input.checked != null) input.value = input.checked;
|
||||||
|
try {
|
||||||
|
if (input.value == '') input.value = 'null';
|
||||||
|
thiseval = JSON.parse(input.value);
|
||||||
|
} catch (ee) {
|
||||||
|
printe(field + ' : ' + ee);
|
||||||
|
throw ee;
|
||||||
|
}
|
||||||
|
if (editor.table.checkRange(cobj, thiseval)) {
|
||||||
|
editor_mode.addAction(['change', field, thiseval]);
|
||||||
|
editor_mode.onmode('save');//自动保存 删掉此行的话点保存按钮才会保存
|
||||||
|
} else {
|
||||||
|
printe(field + ' : 输入的值不合要求,请鼠标放置在注释上查看说明');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tokenPool = {};
|
||||||
|
var tokenstyle = document.createElement("style");
|
||||||
|
document.body.appendChild(tokenstyle);
|
||||||
|
|
||||||
|
var tokenPoolRender = function() {
|
||||||
|
var content = "";
|
||||||
|
Object.keys(tokenPool).forEach(function(k) {
|
||||||
|
content += /* CSS */`[data-field|=${k}]{ display: none }`;
|
||||||
|
})
|
||||||
|
tokenstyle.innerHTML = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当"折叠"被按下时
|
||||||
|
*/
|
||||||
|
editor_table.prototype.onFoldBtnClick = function (button) {
|
||||||
|
var tr = button.parentNode.parentNode;
|
||||||
|
if (button.dataset.fold == "true") {
|
||||||
|
delete tokenPool[tr.dataset.gap];
|
||||||
|
tokenPoolRender();
|
||||||
|
button.dataset.fold = "false";
|
||||||
|
button.innerText = "折叠";
|
||||||
|
} else {
|
||||||
|
tokenPool[tr.dataset.gap] = true;
|
||||||
|
tokenPoolRender();
|
||||||
|
button.dataset.fold = "true";
|
||||||
|
button.innerText = "展开";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当"显示完整注释"被按下时
|
||||||
|
*/
|
||||||
|
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'));
|
||||||
|
var input = tr.children[2].children[0].children[0];
|
||||||
|
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, template: cobj._template, preview: cobj._preview });
|
||||||
|
if (cobj._type === 'material') editor.table.selectMaterial(input, cobj);
|
||||||
|
if (cobj._type === 'color') editor.table.selectColor(input);
|
||||||
|
if (cobj._type === 'point') editor.table.selectPoint(input);
|
||||||
|
if (cobj._type === 'popCheckboxSet') editor.table.popCheckboxSet(input, cobj);
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_table.prototype.onCopyBtnClick = function (button) {
|
||||||
|
var tr = button.parentNode.parentNode;
|
||||||
|
var input = tr.children[2].children[0].children[0];
|
||||||
|
var value = JSON.parse(input.value);
|
||||||
|
if (value == null) {
|
||||||
|
printe('没有赋值的内容');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (core.copy(value.toString())) {
|
||||||
|
printf('复制成功!');
|
||||||
|
} else {
|
||||||
|
printe('无法复制此内容,请手动选择复制');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 双击表格时
|
||||||
|
* 正常编辑: 尝试用事件编辑器或多行文本编辑器打开
|
||||||
|
* 添加: 在该项的同一级创建一个内容为null新的项, 刷新后生效并可以继续编辑
|
||||||
|
* 删除: 删除该项, 刷新后生效
|
||||||
|
* 在点击按钮 添加/删除 后,下一次双击将被视为 添加/删除
|
||||||
|
*/
|
||||||
|
editor_table.prototype.dblclickfunc = function (guid, obj, commentObj, thisTr, input, field, cobj, modeNode) {
|
||||||
|
if (editor_mode.doubleClickMode === 'change') {
|
||||||
|
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, template: cobj._template, preview: cobj._preview });
|
||||||
|
if (cobj._type === 'material') editor.table.selectMaterial(input, cobj);
|
||||||
|
if (cobj._type === 'color') editor.table.selectColor(input);
|
||||||
|
if (cobj._type === 'point') editor.table.selectPoint(input);
|
||||||
|
if (cobj._type === 'popCheckboxSet') editor.table.popCheckboxSet(input, cobj);
|
||||||
|
} else if (editor_mode.doubleClickMode === 'add') {
|
||||||
|
editor_mode.doubleClickMode = 'change';
|
||||||
|
editor.table.addfunc(guid, obj, commentObj, thisTr, input, field, cobj, modeNode)
|
||||||
|
} else if (editor_mode.doubleClickMode === 'delete') {
|
||||||
|
editor_mode.doubleClickMode = 'change';
|
||||||
|
editor.table.deletefunc(guid, obj, commentObj, thisTr, input, field, cobj, modeNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_table.prototype.selectMaterial = function (input, cobj) {
|
||||||
|
editor.uievent.selectMaterial(input.value, cobj._docs || cobj._data || '请选择素材', cobj._directory, function (one) {
|
||||||
|
if (!/^[-A-Za-z0-9_.]+$/.test(one)) return null;
|
||||||
|
if (cobj._transform) return eval("("+cobj._transform+")(one)");
|
||||||
|
return one;
|
||||||
|
}, function (data) {
|
||||||
|
input.value = JSON.stringify(cobj._onconfirm ? eval("("+cobj._onconfirm+")(JSON.parse(input.value), data)") : data);
|
||||||
|
input.onchange();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_table.prototype.selectColor = function (input) {
|
||||||
|
if (input.value != null) {
|
||||||
|
var str = input.value.toString().replace(/[^\d.,]/g, '');
|
||||||
|
if (/^[0-9 ]+,[0-9 ]+,[0-9 ]+(,[0-9. ]+)?$/.test(str)) {
|
||||||
|
document.getElementById('colorPicker').value = str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var boundingBox = input.getBoundingClientRect();
|
||||||
|
openColorPicker(boundingBox.x, boundingBox.y + boundingBox.height, function (value) {
|
||||||
|
value = value.replace(/[^\d.,]/g, '');
|
||||||
|
input.value = '[' + value +']';
|
||||||
|
input.onchange();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_table.prototype.selectPoint = function (input) {
|
||||||
|
var x = 0, y = 0, value = input.value;
|
||||||
|
if (value != null) {
|
||||||
|
try {
|
||||||
|
var loc = JSON.parse(value);
|
||||||
|
if (loc instanceof Array && loc.length == 2) {
|
||||||
|
x = loc[0];
|
||||||
|
y = loc[1];
|
||||||
|
}
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
editor.uievent.selectPoint(editor.currentFloorId, x, y, false, function (floorId, x, y) {
|
||||||
|
input.value = '['+x+','+y+']';
|
||||||
|
input.onchange();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_table.prototype.popCheckboxSet = function (input, cobj) {
|
||||||
|
editor.uievent.popCheckboxSet(JSON.parse(input.value), cobj._checkboxSet, cobj._docs || cobj._data || '请选择多选项', function (value) {
|
||||||
|
input.value = JSON.stringify(value);
|
||||||
|
input.onchange();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除表格项
|
||||||
|
*/
|
||||||
|
editor_table.prototype.deletefunc = function (guid, obj, commentObj, thisTr, input, field, cobj, modeNode) {
|
||||||
|
editor_mode.onmode(editor_mode._ids[modeNode.getAttribute('id')]);
|
||||||
|
if (editor.table.checkRange(cobj, null)) {
|
||||||
|
editor_mode.addAction(['delete', field, undefined]);
|
||||||
|
editor_mode.onmode('save', function () {
|
||||||
|
printf('删除成功,刷新后生效。')
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
printe(field + ' : 该值不允许为null,无法删除');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加表格项
|
||||||
|
*/
|
||||||
|
editor_table.prototype.addfunc = function (guid, obj, commentObj, thisTr, input, field, cobj, modeNode) {
|
||||||
|
if (modeNode) {
|
||||||
|
editor_mode.onmode(editor_mode._ids[modeNode.getAttribute('id')]);
|
||||||
|
}
|
||||||
|
|
||||||
|
var mode = editor.dom.editModeSelect.value;
|
||||||
|
var supportText = mode === 'commonevent' || mode === 'plugins';
|
||||||
|
|
||||||
|
if (obj == null) {
|
||||||
|
if (mode === 'commonevent') obj = events_c12a15a8_c380_4b28_8144_256cba95f760;
|
||||||
|
else if (mode === 'plugins') obj = plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1;
|
||||||
|
else return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1.输入id
|
||||||
|
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(supportText ? '请输入新项的ID(支持中文)' : '请输入新项的ID(数字字母下划线)');
|
||||||
|
if (newid == null || newid.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.检查id是否符合规范或与已有id重复
|
||||||
|
if (!supportText) {
|
||||||
|
if (!/^[a-zA-Z0-9_]+$/.test(newid)) {
|
||||||
|
printe('id不符合规范, 请使用大小写字母数字下划线来构成');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var conflict = true;
|
||||||
|
var basefield = (field || "").replace(/\[[^\[]*\]$/, '');
|
||||||
|
if (basefield === "['main']") {
|
||||||
|
printe("全塔属性 ~ ['main'] 不允许添加新值");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
var baseobj = eval('obj' + basefield);
|
||||||
|
conflict = newid in baseobj;
|
||||||
|
} catch (ee) {
|
||||||
|
// 理论上这里不会发生错误
|
||||||
|
printe(ee);
|
||||||
|
throw ee;
|
||||||
|
}
|
||||||
|
if (conflict) {
|
||||||
|
printe('id已存在, 请直接修改该项的值');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 3.添加
|
||||||
|
editor_mode.addAction(['add', basefield + "['" + newid + "']", null]);
|
||||||
|
editor_mode.onmode('save', function () {
|
||||||
|
printf('添加成功,刷新后生效;也可以继续新增其他项目。')
|
||||||
|
});//自动保存 删掉此行的话点保存按钮才会保存
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
editor.constructor.prototype.table = new editor_table();
|
||||||
|
}
|
||||||
|
//editor_table_wrapper(editor);
|
339
_server/editor_ui.js
Normal file
339
_server/editor_ui.js
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
editor_ui_wrapper = function (editor) {
|
||||||
|
|
||||||
|
var tip=document.getElementById('tip');
|
||||||
|
var print = function (msg, cls) {
|
||||||
|
if (msg == '') {
|
||||||
|
tip.innerHTML = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tip.innerHTML = '<p class="'+cls+'">' + msg + "</p>";
|
||||||
|
}
|
||||||
|
|
||||||
|
window.printf = function (msg) {
|
||||||
|
selectBox.isSelected(false);
|
||||||
|
print(msg, 'successText');
|
||||||
|
}
|
||||||
|
window.printe = function (msg) {
|
||||||
|
selectBox.isSelected(false);
|
||||||
|
print(msg, 'warnText');
|
||||||
|
}
|
||||||
|
window.printi = function (msg) {
|
||||||
|
print(msg, 'infoText');
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.uifunctions.showBlockInfo = function (value) {
|
||||||
|
if (value == 0) {
|
||||||
|
printi("当前选择为清除块,可擦除地图上块");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var hasId = 'id' in value;
|
||||||
|
if (hasId && value.idnum == 17) {
|
||||||
|
printi("当前选择为空气墙, 在编辑器中可视, 在游戏中隐藏的墙, 用来配合前景/背景的贴图");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var isAutotile = hasId && value.images == "autotile";
|
||||||
|
tip.innerHTML = (hasId?`<p>图块编号:<span class="infoText">${ value['idnum'] }</span></p>
|
||||||
|
<p>图块ID:<span class="infoText">${ value['id'] }</span></p>`:`
|
||||||
|
<p class="warnText">该图块无对应的数字或ID存在,请先前往icons.js和maps.js中进行定义!</p>`)+`
|
||||||
|
<p>图块所在素材:<span class="infoText">${ value['images'] + (isAutotile ? '( '+value['id']+' )' : '') }</span>
|
||||||
|
</p>
|
||||||
|
<p>图块索引:<span class="infoText">${ value['y'] }</span></p>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.uifunctions.showTips = function (value) {
|
||||||
|
var tips = [
|
||||||
|
'表格的文本域可以双击进行编辑',
|
||||||
|
'双击地图可以选中素材,右键可以弹出菜单',
|
||||||
|
'双击事件编辑器的图块可以进行长文本编辑/脚本编辑/地图选点/UI绘制预览等操作',
|
||||||
|
'ESC或点击空白处可以自动保存当前修改',
|
||||||
|
'H键可以打开操作帮助哦',
|
||||||
|
'tileset平铺模式可以在地图上拖动来平铺框选的图形',
|
||||||
|
'可以拖动地图上的图块和事件;或按Ctrl+C, Ctrl+X和Ctrl+V进行复制,剪切和粘贴,Delete删除;右键也可以拉框选择区域',
|
||||||
|
'Alt+数字键保存图块,数字键读取保存的图块',
|
||||||
|
];
|
||||||
|
if (value == null) value = Math.floor(Math.random() * tips.length);
|
||||||
|
printf('tips: ' + tips[value])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据鼠标点击, 得到从元素向上到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', 'brushMode4', 'layerMod', 'layerMod2', 'layerMod3', 'viewportButtons'][ii]; ii++) {
|
||||||
|
if (clickpath.indexOf(thisId) !== -1) {
|
||||||
|
unselect = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (unselect && !editor.uivalues.lockMode) {
|
||||||
|
if (clickpath.indexOf('eui') === -1 && clickpath.indexOf('lastUsed') === -1) {
|
||||||
|
if (selectBox.isSelected()) {
|
||||||
|
editor_mode.onmode('');
|
||||||
|
editor.file.saveFloorFile(function (err) {
|
||||||
|
if (err) {
|
||||||
|
printe(err);
|
||||||
|
throw (err)
|
||||||
|
}
|
||||||
|
; printf('地图保存成功');
|
||||||
|
editor.uifunctions.unhighlightSaveFloorButton();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
selectBox.isSelected(false);
|
||||||
|
editor.info = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//editor.mode.onmode('');
|
||||||
|
if (e.button != 2 && !editor.isMobile && clickpath.indexOf('midMenu') === -1) {
|
||||||
|
editor.uifunctions.hideMidMenu();
|
||||||
|
}
|
||||||
|
if (clickpath.indexOf('down') !== -1 && clickpath.indexOf('midMenu') === -1 && editor.isMobile) {
|
||||||
|
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) {
|
||||||
|
editor.uivalues.tileSize = [1,1];
|
||||||
|
|
||||||
|
// UI预览 & 地图选点
|
||||||
|
if (editor.uievent && editor.uievent.isOpen) {
|
||||||
|
editor.uievent.onKeyDown(e);
|
||||||
|
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;
|
||||||
|
|
||||||
|
// PGUP和PGDOWN切换楼层
|
||||||
|
if (e.keyCode == 33 || e.keyCode == 34) {
|
||||||
|
e.preventDefault();
|
||||||
|
var saveFloor = document.getElementById('saveFloor');
|
||||||
|
if (saveFloor && saveFloor.classList.contains('highlight')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.uivalues.recentFloors.push(editor.currentFloorId);
|
||||||
|
editor.changeFloor(toId);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var focusElement = document.activeElement;
|
||||||
|
if (!focusElement || focusElement.tagName.toLowerCase() == 'body'
|
||||||
|
|| focusElement.id == 'selectFloor' || focusElement.id == 'bigmapBtn'
|
||||||
|
|| focusElement.id.startsWith('layerMod')) {
|
||||||
|
|
||||||
|
//Ctrl+z 撤销上一步undo
|
||||||
|
if (e.keyCode == 90 && e.ctrlKey) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (editor.uivalues.preMapData.length > 0) {
|
||||||
|
var data = editor.uivalues.preMapData.pop();
|
||||||
|
editor.dom.maps.forEach(function (one) {
|
||||||
|
editor[one] = JSON.parse(JSON.stringify(data[one]));
|
||||||
|
});
|
||||||
|
editor.updateMap();
|
||||||
|
editor.uivalues.postMapData.push(data);
|
||||||
|
editor.uifunctions.highlightSaveFloorButton();
|
||||||
|
printf("已撤销此操作,你可能需要重新保存地图。");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//Ctrl+y 重做一步redo
|
||||||
|
if (e.keyCode == 89 && e.ctrlKey) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (editor.uivalues.postMapData.length > 0) {
|
||||||
|
var data = editor.uivalues.postMapData.pop();
|
||||||
|
editor.dom.maps.forEach(function (one) {
|
||||||
|
editor[one] = JSON.parse(JSON.stringify(data[one]));
|
||||||
|
});
|
||||||
|
editor.updateMap();
|
||||||
|
editor.uivalues.preMapData.push(data);
|
||||||
|
editor.uifunctions.highlightSaveFloorButton();
|
||||||
|
printf("已重做此操作,你可能需要重新保存地图。");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ctrl+C, Ctrl+X, Ctrl+V
|
||||||
|
if (e.ctrlKey && e.keyCode == 67 && !selectBox.isSelected()) {
|
||||||
|
e.preventDefault();
|
||||||
|
editor.uivalues.copyedInfo = editor.copyFromPos(editor.uivalues.selectedArea);
|
||||||
|
printf('该点事件已复制;请注意右键地图拉框可以复制一个区域;若有时复制失灵请多点几下空白处');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.ctrlKey && e.keyCode == 88 && !selectBox.isSelected()) {
|
||||||
|
e.preventDefault();
|
||||||
|
editor.savePreMap();
|
||||||
|
editor.uivalues.copyedInfo = editor.copyFromPos(editor.uivalues.selectedArea);
|
||||||
|
editor.clearPos(true, editor.uivalues.selectedArea, function () {
|
||||||
|
printf('该点事件已剪切;请注意右键地图拉框可以剪切一个区域;若有时剪切失灵请多点几下空白处');
|
||||||
|
editor.uifunctions.unhighlightSaveFloorButton();
|
||||||
|
})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e.ctrlKey && e.keyCode == 86 && !selectBox.isSelected()) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (!editor.uivalues.copyedInfo) {
|
||||||
|
printe("没有复制的事件");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
editor.savePreMap();
|
||||||
|
editor.pasteToPos(editor.uivalues.copyedInfo);
|
||||||
|
editor.updateMap();
|
||||||
|
editor.file.saveFloorFile(function (err) {
|
||||||
|
if (err) {
|
||||||
|
printe(err);
|
||||||
|
throw (err)
|
||||||
|
}
|
||||||
|
; printf('粘贴事件成功;若有时粘贴失灵请多点几下空白处');
|
||||||
|
editor.uifunctions.unhighlightSaveFloorButton();
|
||||||
|
editor.drawPosSelection();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// DELETE
|
||||||
|
if (e.keyCode == 46 && !selectBox.isSelected()) {
|
||||||
|
editor.savePreMap();
|
||||||
|
editor.clearPos(true, editor.uivalues.selectedArea, function () {
|
||||||
|
printf('该点事件已删除;请注意右键地图拉框可以删除一个区域;;若有时删除失灵请多点几下空白处');
|
||||||
|
editor.uifunctions.unhighlightSaveFloorButton();
|
||||||
|
})
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
//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('已保存该快捷图块, 数字键 ' + (e.keyCode - 48) + ' 使用.')
|
||||||
|
editor.config.set('shortcut', editor.uivalues.shortcut);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//ctrl + 0~9 切换到快捷图块
|
||||||
|
if ([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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
// F
|
||||||
|
case 70: editor.uifunctions.triggerBigmap(); 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 / 点击空白处:自动保存当前修改\n" +
|
||||||
|
"F:切换大地图\n" +
|
||||||
|
"WASD / 长按箭头:平移大地图\n" +
|
||||||
|
"PgUp, PgDn / 鼠标滚轮:上下切换楼层\n" +
|
||||||
|
"Z~.(键盘的第三排):快捷切换标签\n" +
|
||||||
|
"双击地图:选中对应点的素材\n" +
|
||||||
|
"右键地图:弹出菜单栏\n" +
|
||||||
|
"Alt+0~9:保存当前使用的图块\n" +
|
||||||
|
"0~9:选中保存的图块\n" +
|
||||||
|
"Ctrl+Z / Ctrl+Y:撤销/重做上次绘制\n" +
|
||||||
|
"Ctrl+S:事件与脚本编辑器的保存并退出\n" +
|
||||||
|
"双击事件编辑器:长文本编辑/脚本编辑/地图选点/UI绘制预览"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
1068
_server/editor_uievent.js
Normal file
1068
_server/editor_uievent.js
Normal file
File diff suppressed because it is too large
Load Diff
173
_server/editor_util.js
Normal file
173
_server/editor_util.js
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
editor_util_wrapper = function (editor) {
|
||||||
|
|
||||||
|
editor_util = function () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_util.prototype.guid = function () {
|
||||||
|
return 'id_' + 'xxxxxxxx_xxxx_4xxx_yxxx_xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||||
|
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||||||
|
return v.toString(16);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_util.prototype.HTMLescape = function (str_) {
|
||||||
|
return String(str_).split('').map(function (v) {
|
||||||
|
return '&#' + v.charCodeAt(0) + ';'
|
||||||
|
}).join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_util.prototype.getPixel = function (imgData, x, y) {
|
||||||
|
var offset = (x + y * imgData.width) * 4;
|
||||||
|
var r = imgData.data[offset + 0];
|
||||||
|
var g = imgData.data[offset + 1];
|
||||||
|
var b = imgData.data[offset + 2];
|
||||||
|
var a = imgData.data[offset + 3];
|
||||||
|
return [r, g, b, a];
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_util.prototype.setPixel = function (imgData, x, y, rgba) {
|
||||||
|
var offset = (x + y * imgData.width) * 4;
|
||||||
|
imgData.data[offset + 0] = rgba[0];
|
||||||
|
imgData.data[offset + 1] = rgba[1];
|
||||||
|
imgData.data[offset + 2] = rgba[2];
|
||||||
|
imgData.data[offset + 3] = rgba[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
// rgbToHsl hue2rgb hslToRgb from https://github.com/carloscabo/colz.git
|
||||||
|
//--------------------------------------------
|
||||||
|
// The MIT License (MIT)
|
||||||
|
//
|
||||||
|
// Copyright (c) 2014 Carlos Cabo
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in all
|
||||||
|
// copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
// SOFTWARE.
|
||||||
|
//--------------------------------------------
|
||||||
|
// https://github.com/carloscabo/colz/blob/master/public/js/colz.class.js
|
||||||
|
var round = Math.round;
|
||||||
|
var rgbToHsl = function (rgba) {
|
||||||
|
var arg, r, g, b, h, s, l, d, max, min;
|
||||||
|
|
||||||
|
arg = rgba;
|
||||||
|
|
||||||
|
if (typeof arg[0] === 'number') {
|
||||||
|
r = arg[0];
|
||||||
|
g = arg[1];
|
||||||
|
b = arg[2];
|
||||||
|
} else {
|
||||||
|
r = arg[0][0];
|
||||||
|
g = arg[0][1];
|
||||||
|
b = arg[0][2];
|
||||||
|
}
|
||||||
|
|
||||||
|
r /= 255;
|
||||||
|
g /= 255;
|
||||||
|
b /= 255;
|
||||||
|
|
||||||
|
max = Math.max(r, g, b);
|
||||||
|
min = Math.min(r, g, b);
|
||||||
|
l = (max + min) / 2;
|
||||||
|
|
||||||
|
if (max === min) {
|
||||||
|
h = s = 0; // achromatic
|
||||||
|
} else {
|
||||||
|
d = max - min;
|
||||||
|
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
||||||
|
|
||||||
|
switch (max) {
|
||||||
|
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
||||||
|
case g: h = (b - r) / d + 2; break;
|
||||||
|
case b: h = (r - g) / d + 4; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
h /= 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
//CARLOS
|
||||||
|
h = round(h * 360);
|
||||||
|
s = round(s * 100);
|
||||||
|
l = round(l * 100);
|
||||||
|
|
||||||
|
return [h, s, l];
|
||||||
|
}
|
||||||
|
//
|
||||||
|
var hue2rgb = function (p, q, t) {
|
||||||
|
if (t < 0) { t += 1; }
|
||||||
|
if (t > 1) { t -= 1; }
|
||||||
|
if (t < 1 / 6) { return p + (q - p) * 6 * t; }
|
||||||
|
if (t < 1 / 2) { return q; }
|
||||||
|
if (t < 2 / 3) { return p + (q - p) * (2 / 3 - t) * 6; }
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
var hslToRgb = function (hsl) {
|
||||||
|
var arg, r, g, b, h, s, l, q, p;
|
||||||
|
|
||||||
|
arg = hsl;
|
||||||
|
|
||||||
|
if (typeof arg[0] === 'number') {
|
||||||
|
h = arg[0] / 360;
|
||||||
|
s = arg[1] / 100;
|
||||||
|
l = arg[2] / 100;
|
||||||
|
} else {
|
||||||
|
h = arg[0][0] / 360;
|
||||||
|
s = arg[0][1] / 100;
|
||||||
|
l = arg[0][2] / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s === 0) {
|
||||||
|
r = g = b = l; // achromatic
|
||||||
|
} else {
|
||||||
|
|
||||||
|
q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
||||||
|
p = 2 * l - q;
|
||||||
|
r = hue2rgb(p, q, h + 1 / 3);
|
||||||
|
g = hue2rgb(p, q, h);
|
||||||
|
b = hue2rgb(p, q, h - 1 / 3);
|
||||||
|
}
|
||||||
|
return [round(r * 255), round(g * 255), round(b * 255)];
|
||||||
|
}
|
||||||
|
editor_util.prototype.rgbToHsl = rgbToHsl
|
||||||
|
editor_util.prototype.hue2rgb = hue2rgb
|
||||||
|
editor_util.prototype.hslToRgb = hslToRgb
|
||||||
|
|
||||||
|
editor_util.prototype.encode64 = function (str) {
|
||||||
|
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
|
||||||
|
return String.fromCharCode(parseInt(p1, 16))
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_util.prototype.decode64 = function (str) {
|
||||||
|
return decodeURIComponent(atob(str.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, '')).split('').map(function (c) {
|
||||||
|
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
|
||||||
|
}).join(''))
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_util.prototype.isset = function (val) {
|
||||||
|
return val != null && !(typeof val == 'number' && isNaN(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
editor_util.prototype.checkCallback = function (callback) {
|
||||||
|
if (!editor.util.isset(callback)) {
|
||||||
|
editor.printe('未设置callback');
|
||||||
|
throw ('未设置callback')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.constructor.prototype.util = new editor_util();
|
||||||
|
}
|
||||||
|
//editor_util_wrapper(editor);
|
186
_server/fs.js
Normal file
186
_server/fs.js
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
(function () {
|
||||||
|
window.fs = {};
|
||||||
|
|
||||||
|
|
||||||
|
var _isset = function (val) {
|
||||||
|
if (val == undefined || val == null || (typeof val == 'number' && isNaN(val))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var _http = function (type, url, formData, success, error, mimeType, responseType) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open(type, url, true);
|
||||||
|
if (_isset(mimeType))
|
||||||
|
xhr.overrideMimeType(mimeType);
|
||||||
|
if (_isset(responseType))
|
||||||
|
xhr.responseType = responseType;
|
||||||
|
xhr.onload = function (e) {
|
||||||
|
if (xhr.status == 200) {
|
||||||
|
if (_isset(success)) {
|
||||||
|
success(xhr.response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (_isset(error))
|
||||||
|
error("HTTP " + xhr.status);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.onabort = function () {
|
||||||
|
if (_isset(error))
|
||||||
|
error("Abort");
|
||||||
|
}
|
||||||
|
xhr.ontimeout = function () {
|
||||||
|
if (_isset(error))
|
||||||
|
error("Timeout");
|
||||||
|
}
|
||||||
|
xhr.onerror = function () {
|
||||||
|
if (_isset(error))
|
||||||
|
error("Error on Connection");
|
||||||
|
}
|
||||||
|
if (_isset(formData))
|
||||||
|
xhr.send(formData);
|
||||||
|
else xhr.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var postsomething = function (data, _ip, callback) {
|
||||||
|
if (typeof (data) == typeof ([][0]) || data == null) data = JSON.stringify({ 1: 2 });
|
||||||
|
|
||||||
|
_http("POST", _ip, data, function (data) {
|
||||||
|
if (data.slice(0, 6) == 'error:') {
|
||||||
|
callback(data, null);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
callback(null, data);
|
||||||
|
}
|
||||||
|
}, function (e) {
|
||||||
|
if (window.main != null) console.log(e);
|
||||||
|
else console.log(e);
|
||||||
|
callback(e + ":请检查启动服务是否处于正常运行状态。");
|
||||||
|
}, "text/plain; charset=x-user-defined");
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.readFile = function (filename, encoding, callback) {
|
||||||
|
if (typeof (filename) != typeof (''))
|
||||||
|
throw 'Type Error in fs.readFile';
|
||||||
|
if (encoding == 'utf-8') {
|
||||||
|
//读文本文件
|
||||||
|
//filename:支持"/"做分隔符
|
||||||
|
//callback:function(err, data)
|
||||||
|
//data:字符串
|
||||||
|
var data = '';
|
||||||
|
data += 'type=utf8&';
|
||||||
|
data += 'name=' + filename;
|
||||||
|
postsomething(data, '/readFile', callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (encoding == 'base64') {
|
||||||
|
//读二进制文件
|
||||||
|
//filename:支持"/"做分隔符
|
||||||
|
//callback:function(err, data)
|
||||||
|
//data:base64字符串
|
||||||
|
var data = '';
|
||||||
|
data += 'type=base64&';
|
||||||
|
data += 'name=' + filename;
|
||||||
|
postsomething(data, '/readFile', callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw 'Type Error in fs.readFile';
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFile = function (filename, datastr, encoding, callback) {
|
||||||
|
if (typeof (filename) != typeof ('') || typeof (datastr) != typeof (''))
|
||||||
|
throw 'Type Error in fs.writeFile';
|
||||||
|
if (encoding == 'utf-8') {
|
||||||
|
//写文本文件
|
||||||
|
//filename:支持"/"做分隔符
|
||||||
|
//callback:function(err)
|
||||||
|
//datastr:字符串
|
||||||
|
var data = '';
|
||||||
|
data += 'type=utf8&';
|
||||||
|
data += 'name=' + filename;
|
||||||
|
data += '&value=' + datastr;
|
||||||
|
postsomething(data, '/writeFile', callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (encoding == 'base64') {
|
||||||
|
//写二进制文件
|
||||||
|
//filename:支持"/"做分隔符
|
||||||
|
//callback:function(err)
|
||||||
|
//datastr:base64字符串
|
||||||
|
var data = '';
|
||||||
|
data += 'type=base64&';
|
||||||
|
data += 'name=' + filename;
|
||||||
|
data += '&value=' + datastr;
|
||||||
|
postsomething(data, '/writeFile', callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw 'Type Error in fs.writeFile';
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeMultiFiles = function (filenames, datastrs, callback) {
|
||||||
|
postsomething('name=' + filenames.join(';') + '&value=' + datastrs.join(';'), '/writeMultiFiles', callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.readdir = function (path, callback) {
|
||||||
|
//callback:function(err, data)
|
||||||
|
//path:支持"/"做分隔符,不以"/"结尾
|
||||||
|
//data:[filename1,filename2,..] filename是字符串,只包含文件不包含目录
|
||||||
|
if (typeof (path) != typeof (''))
|
||||||
|
throw 'Type Error in fs.readdir';
|
||||||
|
var data = '';
|
||||||
|
data += 'name=' + path;
|
||||||
|
postsomething(data, '/listFile', function (err, data) {
|
||||||
|
try {
|
||||||
|
data = JSON.parse(data);
|
||||||
|
} catch (e) {
|
||||||
|
err = "Invalid /listFile";
|
||||||
|
data = null;
|
||||||
|
}
|
||||||
|
callback(err, data);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path 支持"/"做分隔符
|
||||||
|
* @param {() => {err: string, data}} callback
|
||||||
|
*/
|
||||||
|
fs.mkdir = function (path, callback) {
|
||||||
|
//callback:function(err, data)
|
||||||
|
if (typeof (path) != typeof (''))
|
||||||
|
throw 'Type Error in fs.readdir';
|
||||||
|
var data = '';
|
||||||
|
data += 'name=' + path;
|
||||||
|
postsomething(data, '/makeDir', callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path 支持"/"做分隔符, 不以"/"结尾
|
||||||
|
* @param {() => {err: string, data}} callback
|
||||||
|
*/
|
||||||
|
fs.moveFile = function (src, dest, callback) {
|
||||||
|
if (typeof (src) != typeof ('') || typeof (dest) != typeof (''))
|
||||||
|
throw 'Type Error in fs.readdir';
|
||||||
|
var data = '';
|
||||||
|
data += 'src=' + src + "&dest=" + dest;
|
||||||
|
postsomething(data, '/moveFile', callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path 支持"/"做分隔符, 不以"/"结尾
|
||||||
|
* @param {() => {err: string, data}} callback
|
||||||
|
*/
|
||||||
|
fs.deleteFile = function (path, callback) {
|
||||||
|
if (typeof (path) != typeof (''))
|
||||||
|
throw 'Type Error in fs.readdir';
|
||||||
|
var data = '';
|
||||||
|
data += 'name=' + path;
|
||||||
|
postsomething(data, '/deleteFile', callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
})();
|
70
_server/fsTest_cs.html
Normal file
70
_server/fsTest_cs.html
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="./fs.js"></script>
|
||||||
|
<script>
|
||||||
|
fs.writeFile('_test.txt', '123中a文bc', 'utf-8', function (e, d) {
|
||||||
|
console.log(e, d);
|
||||||
|
})
|
||||||
|
setTimeout(function () {
|
||||||
|
fs.writeFile('_test_bin.txt', 'abc=', 'base64', function (e, d) {
|
||||||
|
console.log(e, d);
|
||||||
|
})
|
||||||
|
}, 1000);
|
||||||
|
setTimeout(function () {
|
||||||
|
fs.readFile('_test.txt', 'utf-8', function (e, d) {
|
||||||
|
console.log(e, d);
|
||||||
|
})
|
||||||
|
}, 2000);
|
||||||
|
setTimeout(function () {
|
||||||
|
fs.readFile('_test_bin.txt', 'base64', function (e, d) {
|
||||||
|
console.log(e, d);
|
||||||
|
})
|
||||||
|
}, 3000);
|
||||||
|
setTimeout(function () {
|
||||||
|
fs.readdir('.', function (e, d) {
|
||||||
|
console.log(e, d);
|
||||||
|
})
|
||||||
|
}, 4000);
|
||||||
|
setTimeout(function () {
|
||||||
|
fs.writeMultiFiles(['_test.txt','_test_multi.txt'], ['abc=','abe='], function (e, d) {
|
||||||
|
console.log(e, d);
|
||||||
|
})
|
||||||
|
}, 5000);
|
||||||
|
setTimeout(function () {
|
||||||
|
fs.mkdir('__test__', function (e, d) {
|
||||||
|
console.log(e, d);
|
||||||
|
})
|
||||||
|
}, 6000);
|
||||||
|
setTimeout(function () {
|
||||||
|
fs.moveFile('_test_bin.txt', '__test__/_test_bin.txt', function (e, d) {
|
||||||
|
console.log(e, d);
|
||||||
|
})
|
||||||
|
}, 7000);
|
||||||
|
setTimeout(function () {
|
||||||
|
fs.moveFile('_test.txt', '__test__/_test.txt', function (e, d) {
|
||||||
|
console.log(e, d);
|
||||||
|
})
|
||||||
|
}, 8000);
|
||||||
|
setTimeout(function () {
|
||||||
|
fs.moveFile('_test_multi.txt', '__test__/_test.txt', function (e, d) {
|
||||||
|
console.log(e, d);
|
||||||
|
})
|
||||||
|
}, 8000);
|
||||||
|
setTimeout(function () {
|
||||||
|
fs.deleteFile('__test__/_test_bin.txt', function (e, d) {
|
||||||
|
console.log(e, d);
|
||||||
|
})
|
||||||
|
}, 9000);
|
||||||
|
setTimeout(function () {
|
||||||
|
fs.deleteFile('__test__', function (e, d) {
|
||||||
|
console.log(e, d);
|
||||||
|
})
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
136
_server/refactoring.md
Normal file
136
_server/refactoring.md
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
# 重构
|
||||||
|
|
||||||
|
> 目前状态: 按功能分类, 维持稳定状态, 在3.0中重写
|
||||||
|
|
||||||
|
总体思路
|
||||||
|
+ 按功能拆分文件
|
||||||
|
+ 左侧页面模块化, 方便添加
|
||||||
|
+ 不同的模式的文件操作尽可能模块化
|
||||||
|
|
||||||
|
目前主要在重构editor_file, 思路是editor.file负责把editor.game内的游戏数据格式化成字符串以及写入到文件, 由editor.game来修改数据
|
||||||
|
+ editor.file维护一些标记, 描述哪些数据需要格式化并写入, 在save时写入文件(自动保存的话就是每次修改数据都触发save)
|
||||||
|
+ editor.game修改数据, 并修改editor.file中的标记
|
||||||
|
+ 此思路下editor.file的大部分内容会挪到editor.game, editor.game和editor.table可能会再进一步合并拆分
|
||||||
|
|
||||||
|
editor_file之后是更改editor.map的储存方式, 现有的存对象的模式要在对象和数字间来回转换, 非常繁琐和奇怪
|
||||||
|
|
||||||
|
## 文件结构
|
||||||
|
|
||||||
|
(全部小写,必要时用下划线分割)
|
||||||
|
|
||||||
|
+ [ ] 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 移除
|
||||||
|
+ [x] \*comment.js 表格注释与结构, 移至table/\*comment.js
|
||||||
|
|
||||||
|
## 对象结构
|
||||||
|
|
||||||
|
```
|
||||||
|
editor: {
|
||||||
|
__proto__: {
|
||||||
|
fs
|
||||||
|
util
|
||||||
|
file
|
||||||
|
table
|
||||||
|
multi
|
||||||
|
blockly
|
||||||
|
game
|
||||||
|
}
|
||||||
|
config: 编辑器配置
|
||||||
|
mode: 当前的模式(左侧的选择)
|
||||||
|
map: 当前编辑层的地图
|
||||||
|
isMobile: 编辑器是否是手机端
|
||||||
|
currentFloorData: 当前编辑的楼层数据
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 某些注意到的点&准备修改的内容
|
||||||
|
|
||||||
|
+ 插入公共事件的参数的转义处理, .g4中添加ObjectString, 要求其中的值可以JSON.parse, 生成的code中也是作为对象而不是字符串出现
|
||||||
|
|
||||||
|
+ 修改editor.multi中的转义处理, 目前双击某些方块使用文本编辑的处理, 一部分在editor.blockly, 一部分在editor.multi, 比较混乱
|
||||||
|
|
||||||
|
+ 地图的编辑与其他(如全塔属性和楼层属性), 现在的文件操作的模式是完全不同的
|
||||||
|
楼层文件的储存与其他不同
|
||||||
|
|
||||||
|
+ [x] editor.file在修改时不再返回obj和commentobj,只在查询时返回
|
||||||
|
|
||||||
|
+ editor.file中的各个条目, 非常相似, 但是细节的不同处理非常麻烦. 是类似的代码复制后修改一部分, 尝试模块化(或者重写)
|
||||||
|
|
||||||
|
+ functions和plugins的借助JSON.stringify的replacer特殊处理, 与其他项的处理完全不同, 改成用统一的方法处理(为了统一,全部使用这种不直观的replacer的处理)
|
||||||
|
|
||||||
|
+ 怪物/物品/地图选点事件的处理, field中怪物id等明显与其他节地位不等, 处理起来很繁琐
|
||||||
|
|
||||||
|
+ 目前editor.map中储存的是info\<object\>, 准备改为和core一致只储存数字
|
||||||
|
|
||||||
|
+ editor.widthX特别不直观
|
||||||
|
|
||||||
|
+ ? 编辑器使用可拖拽和调大小的窗口做容器
|
||||||
|
|
||||||
|
## 功能改进
|
||||||
|
|
||||||
|
+ [x] 大地图
|
||||||
|
在切换时, 每次都回到最左上->每个楼层记录一个位置
|
||||||
|
四个箭头支持长按
|
||||||
|
? 滚动条
|
||||||
|
|
||||||
|
+ [ ] ? 表格折叠
|
||||||
|
变为四栏, 可以折叠展开
|
||||||
|
|
||||||
|
+ [x] blockly对于无法识别的图块原样返回
|
||||||
|
|
||||||
|
+ [ ] ? 简洁的事件方块注册
|
||||||
|
`editor.registerEvent('log',[['test','Int','测试',0],['floorId','Idstring','楼层','MT0']])`
|
||||||
|
|
||||||
|
+ [x] 一个显示所有快捷键的文本
|
||||||
|
|
||||||
|
+ [x] 更多快捷键
|
||||||
|
【全塔属性】、【楼层属性】等常用的编辑栏切换
|
||||||
|
|
||||||
|
+ [x] ? 地图编辑优化
|
||||||
|
常用的地图编辑快捷键/命令:复制ctrl+c、粘贴ctrl+v、(复制可绑定为现在的“选中xx位置事件” 粘贴为复制xx事件到此处),撤回ctrl+z、取消撤回ctrl+y
|
||||||
|
可以按住拖动图块与事件。
|
||||||
|
|
||||||
|
+ [ ] ? 自由建立快捷键到命令的注册表。
|
||||||
|
|
||||||
|
+ [ ] 画地图也自动保存
|
||||||
|
|
||||||
|
+ [x] 修改系统的触发器(下拉菜单增加新项)
|
||||||
|
在编辑器修改`comment.js`:现场发readFile请求读文件,然后开脚本编辑器进行编辑
|
||||||
|
|
||||||
|
+ [x] ? 删除注册项/修改图块ID
|
||||||
|
|
||||||
|
+ [ ] ? 怪物和道具也能像其他类型那样查看“图块信息”(而不只是具体的怪物属性)
|
||||||
|
|
||||||
|
+ [x] 素材区自动换列
|
||||||
|
怪物或道具太多时, 按照每100个进行拆分新开列来显示
|
||||||
|
|
||||||
|
+ [x] 多帧素材只显示第一帧
|
||||||
|
|
||||||
|
+ [x] `显示文章`以及`选项`等方块, 把`标题`和`图像`从字符串提取出填回相应的空
|
||||||
|
|
||||||
|
+ [x] blockly中某些需要选点的填空, 增加按钮, 点击后从缩略图中点击位置
|
||||||
|
|
||||||
|
+ [ ] 插件编写增加判定,如果保存时框内不是以 "function\s*()" 开头(也就是用户直接写的脚本),则自动添加一个 function() { } 将代码包装起来。
|
||||||
|
|
||||||
|
## 左侧页面模式
|
||||||
|
|
||||||
|
标题? 保存按钮? 添加按钮? 删除按钮?
|
||||||
|
|
||||||
|
自定义内容?
|
||||||
|
|
||||||
|
表格?
|
Loading…
Reference in New Issue
Block a user