This commit is contained in:
voderl 2020-03-20 17:44:57 +08:00
parent 099f0112b1
commit 6b92ae192b
158 changed files with 17888 additions and 4247 deletions

2185
API列表.txt Normal file

File diff suppressed because it is too large Load Diff

104
README.md
View File

@ -17,6 +17,7 @@ HTML5 canvas制作的魔塔样板支持全平台游戏
``` bash
├── /_server/ # 为可视化地图编辑器提供一些支持的目录
├── /docs/ # 文档目录
├── /extensions/ # 拓展工具目录,发布到网站后不会加载
├── /libs/ # 系统库目录
│ ├─ /thirdparty/ # 游戏所用到的第三方库文件
│ ├─ actions.js # 处理用户交互的文件
@ -25,6 +26,7 @@ HTML5 canvas制作的魔塔样板支持全平台游戏
│ ├─ data.js # 记录了一些初始化信息
│ ├─ enemys.js # 记录了怪物的信息,包括特殊属性、伤害计算公式、临界值计算等。
│ ├─ events.js # 处理事件的文件,所有自定义事件都会在此文件中进行处理
│ ├─ extensions.js # 加载拓展工具的文件
│ ├─ icons.js # 图标信息会被转发到project下
│ ├─ items.js # 道具信息会被转发到project下
│ ├─ loader.js # 动态加载JS代码、图片、音效等
@ -55,6 +57,108 @@ HTML5 canvas制作的魔塔样板支持全平台游戏
## 更新说明
### 2019.12.31 HTML5魔塔样板V2.6.6
* [x] 编辑器增加【最近使用的图块】的区域
* [x] 编辑器拉伸到铺满全屏幕还可以Ctrl+滚轮放缩
* [x] 编辑器支持连续Ctrl+Z的撤销Ctrl+Y的重做
* [x] 新增tileset右键绑定宽高以替代贴图模式
* [x] 多重自动存档可以连续A键读档
* [x] 高层塔分区域支持
* [x] 自绘状态栏点击事件
* [x] 绘制的锁定模式
* [x] 等待用户操作增设分歧选项
* [x] 增设压缩模式会对图片等进行zip压缩
* [x] 追加素材现在可以同时进行自动注册
* [x] 可以复制和粘贴怪物或道具的属性
* [x] 折叠素材时设置每一列个数
* [x] 标题界面和显示选择项时光标跟随鼠标
* [x] 修复所有已知的bug大量细节优化
### 2019.12.1 HTML5魔塔样板V2.6.5
* [x] 事件:设置怪物属性;穿脱装备
* [x] 新值块enemy:xxx:atk可获得怪物数据
* [x] 新值块blockId:x,y获得某点图块ID
* [x] 部分事件预编译,加快执行速度
* [x] 在系统设置中可以设置bgm的播放音量
* [x] 通关事件可以不退出游戏
* [x] 失败时允许直接读取自动存档
* [x] NPC48自动注册可以自动绑定faceIds
* [x] 编辑器Alt+1-9存图块1-9读取图块
* [x] 编辑器现在可以跨楼层复制粘贴图块了
* [x] 可以对flags.进行自动补全
* [x] 部分Bug修复大量细节优化
### 2019.10.29 HTML5魔塔样板V2.6.4
* [x] 自动事件,多事件页
* [x] 增加开场logo动画
* [x] 拓展:游戏时动态修改地图和怪物数据
* [x] 插件:道具商店,支持买入和卖出道具
* [x] 编辑器可以搜索变量出现位置
* [x] 变量的中文替换
* [x] 可以给图块绑定自定义脚本,碰触时触发
* [x] 编辑器右键可以绑定机关门和出生点
* [x] 支持多个drawTip同时出现
* [x] 闪烁光标同时支持多个同时存在
* [x] 插件:镜头平滑移动,默认禁用
* [x] 素材的快速追加
* [x] 批量导出动画
* [x] 部分Bug修复大量细节优化
### 2019.7.24 V2.6.3
* [x] 标题界面大幅美化,增加闪烁光标,支持键盘开始游戏
* [x] 事件编辑器支持自动补全能对flag和API列表等进行补全
* [x] 剧情文本中\\c修改字体大小\\d和\\e切换粗体和斜体
* [x] 事件:设置视角&移动视角
* [x] 可以指定显示选择项的出现条件并动态生成
* [x] 楼层传送器的平面传送模式(哪里离开飞回到哪里)
* [x] UI绘制事件增添绘制圆和绘制圆边框
* [x] 所有的UI绘制事件均可以双击预览
* [x] 播放BGM事件可以一直持续播放直到下次调用
* [x] \f立绘支持alpha值
* [x] 支持在脚本编辑中直接flags.xxx调用自定义变量
* [x] 首次获得道具将给予提示
* [x] 等待用户操作支持滚轮视为PgUp和PgDn
* [x] 脚本编辑器语法错误将禁止保存
* [x] 录像播放时B键查看数据统计
* [x] 所有已知bug的修复大量细节优化
### 2019.6.7 V2.6.2
* [x] 可以拖动地图上的图块和事件,复制剪切和跨楼层粘贴
* [x] 新增事件的地图选点功能,可以在地图上选择落点
* [x] 现在素材区可以进行折叠与自动换列了
* [x] 新增UI绘制系列事件并且可以进行预览
* [x] 显示文本事件的标题解析
* [x] 新增常用工具:额外素材合并工具
* [x] 进一步提升24倍速的播放速度
* [x] 楼层转换增加对称点
* [x] 增加编辑器快捷键说明H键查看
* [x] 文档-事件增加事件编辑器截图
* [x] 大量细节优化所有已知的Bug修复
### 2019.5.2 V2.6.1
* [x] 区域优化的录像播放功能R键使用
* [x] 强制战斗可以指定怪物坐标,将自动隐藏并执行该点战后事件
* [x] flag:xxx也支持中文例如 flag:2楼机关门
* [x] 增加文件名映射可以用中文映射到某个图片或bgm文件并使用
* [x] 勇士宽度可以超过32例如48x48的勇士行走图
* [x] 现在允许修改floorId和图块ID了在表格下方
* [x] 增加事件:自动存档,返回标题界面;部分事件优化
* [x] 商店长按空格可以连续加点
* [x] 增设global:xxx使用全局存储可被录像支持
* [x] 支持\b[hero]和\b[null,x,y]来自动调整上下方向
* [x] 支持\t[yellowKey]等只显示图标而没有标题
* [x] 编辑器中前景层对于有事件的点半透明显示
* [x] 存档改成1000页长按上下页可快速翻页
* [x] 录像播放初始默认暂停N键可以单步执行
* [x] 增设本地API文档部分API和事件的优化
* [x] 所有已知的bug修复大量细节优化
### 2019.4.13 V2.6
* [x] 拆分整个项目大幅重构代码新增大量API

View File

@ -1,6 +1,6 @@
# V2.0版本介绍
?> 目前版本**v2.5.5**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.6*,上次更新时间:* {docsify-updated} *
目前样板已经更新到V2.0版本以上本章将对V2.0的一些内容进行介绍。

View File

@ -1,6 +1,6 @@
# 附录API列表
?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.6**,上次更新时间:* {docsify-updated} *
这里将列出所有被转发到core的API没有被转发的函数此处不会列出请自行在代码中查看。
@ -57,7 +57,6 @@ core.platform.isPC (是否是电脑端)
core.platform.isAndroid (是否是安卓端)
core.platform.isIOS 是否是iOS端
core.platform.useLocalForage (是否开启了新版存档)
core.platform.extendKeyBoard (是否开启了拓展键盘)
core.domStyle
@ -339,7 +338,7 @@ core.setHeroMoveInterval(callback)
core.moveOneStep(x, y)
每走完一步后执行的操作,被转发到了脚本编辑中。
每走完一步后执行的操作,被转发到了脚本编辑中执行脚本编辑moveOneStep中的内容
core.moveAction(callback)
@ -350,6 +349,7 @@ core.moveAction(callback)
core.moveHero(direction, callback)
令勇士朝一个方向行走。如果设置了callback则只会行走一步并执行回调。
否则将一直朝该方向行走直到core.status.heroStop为true为止。
direction可为"up","down","right","left",分别对应上,下,右,左。
core.isMoving()
@ -362,10 +362,11 @@ core.waitHeroToStop(callback)
core.turnHero(direction)
转向。如果设置了direction则会转到该方向否则会右转。该函数会自动计入录像。
direction可为"up","down","right","left",分别对应上,下,右,左。
core.moveDirectly(destX, destY)
尝试瞬间移动到某点,被转发到了脚本编辑中。
尝试瞬间移动到某点,被转发到了脚本编辑中,执行脚本编辑中的内容
此函数返回非负值代表成功进行瞬移,返回值是省略的步数;如果返回-1则代表没有成功瞬移。
@ -500,12 +501,12 @@ core.syncSave(type) / core.syncLoad()
core.saveData()
获得要存档的内容,实际转发到了脚本编辑中。
获得要存档的内容,实际转发到了脚本编辑中,执行脚本编辑中的内容
core.loadData(data, callback)
实际执行一次读档行为data为读取到的数据callback为执行完毕的回调。
实际转发到了脚本编辑中。
实际转发到了脚本编辑中,执行脚本编辑中的内容
core.getSave(index, callback)
@ -535,19 +536,23 @@ core.removeSave(index)
// ------ 属性、状态、位置、变量等 ------ //
core.setStatus(name, value)
设置勇士当前的某个属性。
设置勇士当前的某个属性name可为"atk","def","hp"等。
如core.setStatus("atk", 100)则为设置勇士攻击为100。
core.addStatus(name, value)
加减勇士当前的某个属性。等价于 core.setStatus(name, core.getStatus(name) + value)
加减勇士当前的某个属性name可为"atk","def","hp"等。
如core.addStatus("atk", 100)则为增加勇士攻击100点。
等价于 core.setStatus(name, core.getStatus(name) + value)。
core.getStatus(name)
获得勇士的某个原始属性值。
获得勇士的某个原始属性值,该值不受百分比增幅影响。
譬如你有一件道具加10%的攻击,你可以使用该函数获得你的攻击被增幅前的数值
core.getStatusOrDefault(status, name)
尝试从status中获得某个原始属性值如果status为null或不存在对应属性值则从勇士属性中获取。
尝试从status中获得某个原始属性值,该值不受百分比增幅影响如果status为null或不存在对应属性值则从勇士属性中获取。
此项在伤害计算函数中使用较多例如传递新的攻击和防御来计算临界和1防减伤。
@ -573,12 +578,14 @@ core.getBuff(name)
core.setHeroLoc(name, value, noGather)
设置勇士位置属性。name只能为'x', 'y'和'direction'之一。
设置勇士位置属性。name只能为'x'勇士x坐标, 'y'勇士y坐标和'direction'(勇士朝向)之一。
如果noGather为true则不会聚集所有的跟随者。
譬如core.setHeroLoc("x", 1, true)则为设置勇士x坐标为1不聚集所有跟随者。
core.getHeroLoc(name)
获得勇士的某个位置属性。如果name为null则直接返回core.status.hero.loc。
譬如core.getHeroLoc("x")则返回勇士当前x坐标
core.getLvName(lv)
@ -587,19 +594,26 @@ core.getLvName(lv)
core.setFlag(name, value)
设置某个自定义变量或flag。如果value为null则会调用core.removeFlag进行删除。
这里的变量与事件中使用的变量等价
譬如core.setFlag("xxx",1)则为设置变量xxx为1。
core.addFlag(name, value)
加减某个自定义的变量或flag。等价于 core.setFlag(name, core.getFlag(name, 0) + value)
这里的变量与事件中使用的变量等价
譬如core.addFlag("xxx",1)则为增加变量xxx1
core.getFlag(name, defaultValue)
获得某个自定义的变量或flag。如果该flag不存在从未赋值过则返回defaultValue值。
获得某个自定义的变量或flag。如果该flag不存在从未赋值过则返回defaultValue的值。
这里的变量与事件中使用的变量等价
譬如core.getFlag("xxx",1)则为获得变量xxx的值如变量xxx不存在则返回1
core.hasFlag(name)
判定是否拥有某个自定义变量或flag。等价于 !!core.getFlag(name, 0)
这里的变量与事件中使用的变量等价
譬如core.hasFlag("xxx",1)则为判断变量xxx是否存在
core.removeFlag(name)
删除一个自定义变量或flag。
@ -620,6 +634,8 @@ core.setWeather(type, level)
core.setCurtain(color, time, callback)
更改画面色调。color为更改到的色调是个三元或四元组time为渐变时间0代表立刻切换。
譬如core.setCurtain([255,255,255,1], 0)即为无回调无等待更改画面色调为白色
core.screenFlash(color, time, times, callback)
@ -655,9 +671,9 @@ core.clearStatusBar()
清空状态栏的数据。
core.updateStatusBar()
core.updateStatusBar(doNotCheckAutoEvents)
更新状态栏,被转发到了脚本编辑中。此函数还会根据是否在回放来设置工具栏的图标。
如果doNotCheckAutoEvents为true则此时不检查自动事件。
core.showStatusBar() / core.hideStatusBar(showToolbox)
显示和隐藏状态栏。
@ -708,7 +724,7 @@ special为要测试的内容允许接收如下类型参数
core.getSpecials()
获得所有特殊属性的列表。实际上被转发到了脚本编辑中。
获得所有特殊属性的列表。实际上被转发到了脚本编辑中,执行脚本编辑中的内容
core.getSpecialText(enemy)
@ -748,7 +764,7 @@ number为要计算的临界值数量不填默认为1。
core.getDefDamage(enemy, k, x, y, floorId)
获得某个怪物的k防减伤值。k可不填默认为1。
获得某个怪物的k防减伤值。k可不填默认为1x,y,floorId为当前xy坐标和楼层
core.getEnemyInfo(enemy, hero, x, y, floorId)
@ -765,10 +781,6 @@ hero可为null或一个对象具体将使用core.getRealStatusOrDefault(hero,
从V2.5.5开始该函数也允许直接返回一个数字代表战斗伤害值此时回合数将视为0。
core.updateEnemys()
更新怪物数据。该函数实际被转发到了脚本编辑中。详见文档-事件-更新怪物数据。
core.getCurrentEnemys(floorId)
获得某个楼层不重复的怪物信息floorId不填默认为当前楼层。该函数会被怪物手册所调用。
该函数将返回一个列表,每一项都是一个不同的怪物,按照伤害值从小到大排序。
@ -776,7 +788,8 @@ core.getCurrentEnemys(floorId)
core.hasEnemyLeft(enemyId, floorId)
检查某个楼层是否还有剩余的指定怪物。floorId为楼层ID可忽略表示当前楼层。
检查某个楼层是否还有剩余的(指定)怪物。
floorId为楼层ID可忽略表示当前楼层。也可以填数组如["MT0","MT1"]同时检测多个楼层。
enemyId如果不填或null则检查是否剩余任何怪物否则只检查是否剩余指定的某类怪物。
```
@ -806,16 +819,16 @@ seed为开始时要设置的的种子route为要开始播放的录像callb
core.setInitData()
根据难度分歧来初始化难度包括设置flag:hard设置初始属性等。
该函数实际被转发到了脚本编辑中。
该函数实际被转发到了脚本编辑中,执行脚本编辑中的内容
core.win(reason, norank)
游戏胜利reason为结局名norank如果为真则该结局不计入榜单。
该函数实际被转发到了脚本编辑中。
该函数实际被转发到了脚本编辑中,执行脚本编辑中的内容
core.lose(reason)
游戏失败reason为结局名。该函数实际被转发到了脚本编辑中。
游戏失败reason为结局名。该函数实际被转发到了脚本编辑中,执行脚本编辑中的内容
core.gameOver(ending, fromReplay, norank)
@ -855,7 +868,7 @@ id为怪物的IDx和y为怪物坐标force如果为真将强制战斗cal
core.beforeBattle(enemyId, x, y)
战前事件。实际被转发到了脚本编辑中,可以在这里加上一些战前特效。
战前事件。实际被转发到了脚本编辑中,执行脚本编辑中的内容,可以用于加上一些战前特效。
此函数在“检测能否战斗和自动存档”【之后】执行。
如果需要更早的战前事件,请在插件中覆重写 core.events.doSystemEvent 函数。
此函数返回true则将继续本次战斗返回false将不再战斗。
@ -863,7 +876,7 @@ core.beforeBattle(enemyId, x, y)
core.afterBattle(enemyId, x, y, callback)
战后事件,将执行扣血、加金币经验、特殊属性处理、战后事件处理等操作。
实际被转发到了脚本编辑中。
实际被转发到了脚本编辑中,执行脚本编辑中的内容
core.openDoor(x, y, needKey, callback)
@ -872,16 +885,17 @@ core.openDoor(x, y, needKey, callback)
core.afterOpenDoor(doorId, x, y, callback)
开完一个门后执行的事件,实际被转发到了脚本编辑中。
开完一个门后执行的事件,实际被转发到了脚本编辑中,执行脚本编辑中的内容
core.getItem(id, num, x, y, callback)
获得若干个道具。itemId为道具IDitemNum为获得的道具个数不填默认为1。
x和y为道具点的坐标如果设置则会擦除地图上的该点。
x和y为道具点的坐标如果设置则会擦除地图上的该点也可不填。
譬如core.getItem("yellowKey",2)会直接获得两把黄钥匙。
core.afterGetItem(id, x, y, callback)
获得一个道具后执行的事件,实际被转发到了脚本编辑中。
获得一个道具后执行的事件,实际被转发到了脚本编辑中,执行脚本编辑中的内容
core.getNextItem(noRoute)
@ -918,7 +932,7 @@ core.pushBox(data)
core.afterPushBox()
推箱子之后触发的事件,实际被转发到了脚本编辑中。
推箱子之后触发的事件,实际被转发到了脚本编辑中,执行脚本编辑中的内容
core.changeLight(id, x, y)
@ -951,10 +965,11 @@ core.startEvents(list, x, y, callback)
此函数将调用core.setEvents然后停止勇士再执行core.doAction()。
core.doAction()
core.doAction(keepUI)
执行下一个自定义事件。
此函数将检测事件列表是否全部执行完毕,如果是则执行回调函数。
否则将从事件列表中弹出下一个事件并调用core.doEvent进行执行。
如果keepUI为true则不会清掉UI层和selector适合于自己用脚本的绘制。
core.insertAction(action, x, y, callback, addToLast)
@ -972,6 +987,15 @@ core.getCommonEvent(name)
core.recoverEvents(data)
恢复事件现场。一般用于呼出怪物手册、呼出存读档页面等时,恢复事件执行流。
core.checkAutoEvents()
检测自动事件并执行。
core.precompile(events)
尝试预编译一段事件。
// ------ 点击状态栏图标时执行的一些操作 ------ //
core.openBook(fromUserAction)
@ -1019,15 +1043,21 @@ core.follow(name) / core.unfollow(name)
core.setValue(name, value, prefix) / core.addValue(name, value, prefix)
设置/增减某个数值。name可以是status:xxxitem:xxx或flag:xxx。
value可以是一个表达式将调用core.calValue()计算。prefix为前缀独立开关使用。
value可以是一个表达式将调用core.calValue()计算。prefix为前缀独立开关使用,脚本中一般忽略
core.doEffect(effect, need, times)
执行一个effect操作。该函数目前仅被全局商店的status:xxx+=yyy所调用。
core.setEnemy(id, name, value, prefix)
设置一个怪物属性。id为怪物的IDname为要设置的项比如hp,atk,def等等。
value可以是一个表达式将调用core.calValue()计算。prefix为前缀独立开关使用脚本中一般忽略。
core.setFloorInfo(name, values, floorId, prefix)
设置某层楼的楼层属性。
设置某层楼的楼层属性其中name为该楼层属性对应的条目values为要设置的值floorId为楼层idprefix一般直接忽略。
譬如core.setFloorInfo("name","4", "MT1")则为设置MT1显示在状态栏中的层数为4
core.setGlobalAttribute(name, value)
@ -1186,8 +1216,9 @@ core.addItem(itemId, itemNum)
core.getEquipTypeByName(name)
根据装备位名称来找到一个空的装备孔,适用于多重装备。
根据装备位名称来找到一个空的装备孔,适用于多重装备,装备位名称可在全塔属性中设置
如果没有一个装备孔是该装备名称,则返回-1。
譬如core.getEquipTypeByName("武器")默认返回全塔属性中武器对应的装备孔号0。
core.getEquipTypeById(equipId)
@ -1200,11 +1231,12 @@ core.canEquip(equipId, hint)
core.loadEquip(equipId, callback)
穿上某个装备。
穿上某个装备equipId为装备id
core.unloadEquip(equipType, callback)
脱下某个装备孔的装备。
譬如core.unloadEquip(0)则为脱下0号装备孔中的装备默认0号装备孔对应“武器”1号装备孔对应“盾牌”
core.compareEquipment(compareEquipId, beComparedEquipId)
@ -1219,6 +1251,10 @@ core.quickSaveEquip(index)
core.quickLoadEquip()
读取当前套装。index为读取的套装编号。
core.getEquippedStatus(name)
获得装备直接增加的属性数据。
```
## loader.js
@ -1276,7 +1312,7 @@ map为存档信息如果某项在map中不存在则会从core.floors中读取
core.getNumberById(id)
给定一个图块ID找到对应的数字
给定一个图块ID找到图块对应的图块编号
core.initBlock(x, y, id, addInfo, eventFloor)
@ -1305,6 +1341,12 @@ core.loadMap(data, floorId)
从data中读取楼层数据并调用core.loadFloor()进行初始化。
core.removeMaps(fromId, toId)
删除某个区域的地图。调用此函数后,这些楼层将不可飞,不可被浏览地图,也不计入存档。
fromId和toId为要删除的起终点楼层IDtoId也可以不填代表只删除某一层。
此函数适用于高层塔的砍层例如每100层一个区域且互相独立不可再返回的情况。
core.resizeMap(floorId)
根据某层楼的地图大小来调整大地图的画布大小。floorId可为null表示当前层。
@ -1412,7 +1454,7 @@ toDraw为要绘制到的信息可为null或为一个画布名包括
// ------ 获得某个点的图块信息 ------ //
core.noPass(x, y, floorId)
判定某个点是否有noPass的图块。
判定某个点是否有noPass(不可通行)的图块。
core.npcExists(x, y, floorId)
@ -1420,7 +1462,7 @@ core.npcExists(x, y, floorId)
core.terrainExists(x, y, id, floorId)
判定某个点是否有(指定的)地形存在。
判定某个点是否有(id对应的)地形存在。
如果id为null则只要存在terrains即为真否则还会判定对应点的ID。
@ -1433,7 +1475,7 @@ core.nearStair()
core.enemyExists(x, y, id, floorId)
判定某个点是否有(指定的)怪物存在。
判定某个点是否有(id对应的)怪物存在。
如果id为null则只要存在怪物即为真否则还会判定对应点的怪物ID。
请注意如果需要判定某个楼层是否存在怪物请使用core.hasEnemyLeft()函数。
@ -1490,14 +1532,17 @@ core.removeBlock(x, y, floorId)
core.removeBlockById(index, floorId)
每个楼层的图块存成一个数组index即为该数组中的索引每个索引对应该地图中的一个图块
根据索引从地图的block数组中尽可能删除一个图块。floorId可不填或null表示当前楼层。
core.removeBlockByIds(floorId, ids)
ids为由索引组成的数组如[0,1]等
根据索引数组从地图的block数组中尽可能删除一系列图块。floorId可不填或null表示当前楼层。
core.canRemoveBlock(block, floorId)
block为图块信息可由core.getBlock获取
判定当前能否完全删除某个图块。floorId可不填或null表示当前楼层。
如果该点存在自定义事件,或者是重生怪,则不可进行删除。
@ -1541,7 +1586,7 @@ number为要设置到的图块数字x,y和floorId为目标点坐标和楼层
core.resetMap(floorId)
重置某层或若干层的地图和楼层属性。
floorId可为某个楼层ID或者一个楼层数组同时重置若干层如果不填则只重置当前楼层。
floorId可为某个楼层ID或者一个楼层数组如["MT1","MT2"](同时重置若干层);如果不填则只重置当前楼层。
// ------ 移动/跳跃图块,淡入淡出图块 ------ //
@ -1585,6 +1630,12 @@ core.drawAnimate(name, x, y, callback)
此函数会返回一个动画id可以通过core.stopAnimate()立刻停止该动画的播放。
core.drawHeroAnimate(name, callback)
绘制一个跟随勇士行动的动画。name为动画名callback为绘制完毕的回调函数。
此函数将播放动画音效,并异步开始绘制该动画。
此函数会返回一个动画id可以通过core.stopAnimate()立刻停止该动画的播放。
core.stopAnimate(id, doCallback)
立刻停止某个动画的播放。id为上面core.drawAnimate的返回值。
如果doCallback为真则会执行该动画所对应的回调函数。
@ -1614,11 +1665,16 @@ core.clearMap(name)
该函数的name也可以是'all',若为'all'则为清空所有系统画布。
core.fillText(name, text, x, y, style, font)
core.fillText(name, text, x, y, style, font, maxWidth)
在某个画布上绘制一段文字。
text为要绘制的文本x,y为要绘制的坐标style可选为绘制的样式font可选为绘制的字体。下同
style可直接使用"red","white"等或用"rgba(255,255,255,1)"或用"#FFFFFF"等方式来获得字体对应的颜色
font的格式为"20px Verdana"前者为字体大小,后者为字体
如果maxWidth不为null则视为文字最大宽度如果超过此宽度则会自动放缩文字直到自适应为止。
请注意textAlign和textBaseline将决定绘制的左右对齐和上下对齐方式。
具体可详见core.setTextAlign()和core.setTextBaseline()函数。
譬如core.fillText("ui", "这是要描绘的文字", 10, 10, "red", "20px Verdana", 100)
即是在ui图层上以10,10为起始点描绘20像素大小Verdana字体的红色字长度不超过100像素
core.fillBoldText(name, text, x, y, style, font)
@ -1626,7 +1682,7 @@ core.fillBoldText(name, text, x, y, style, font)
core.fillRect(name, x, y, width, height, style)
绘制一个矩形。style可选为绘制样式。如果设置将调用core.setFillStyle()。(下同)
绘制一个矩形。width, height为矩形宽高style可选为绘制样式。如果设置将调用core.setFillStyle()。(下同)
core.strokeRect(name, x, y, width, height, style, lineWidth)
@ -1635,11 +1691,11 @@ lineWidth如果设置将调用core.setLineWidth()。(下同)
core.drawLine(name, x1, y1, x2, y2, style, lineWidth)
绘制一条线。
绘制一条线x1y1为起始点像素x2y2为终止点像素
core.drawArrow(name, x1, y1, x2, y2, style, lineWidth)
绘制一个箭头。
绘制一个箭头x1y1为起始点像素x2y2为终止点像素
core.setFont(name, font) / core.setLineWidth(name, lineWidth)
@ -1661,7 +1717,7 @@ core.setFillStyle(name, style) / core.setStrokeStyle(name, style)
core.setTextAlign(name, align)
设置一个画布的文字横向对齐模式这里的align只能为'left', 'right'和'center'。
设置一个画布的文字横向对齐模式这里的align只能为'left', 'right'和'center',分别对应左对齐,右对齐,居中
默认为'left'。
@ -1692,6 +1748,13 @@ core.drawImage(name, image, x, y, w, h, x1, y1, w1, h1)
http://www.w3school.com.cn/html5/canvas_drawimage.asp
这里的image允许传一个图片画布。也允许传递图片名将从你导入的图片中获取图片内容。
core.drawIcon(name, id, x, y, w, h)
在一张画布上绘制一个图标。
id为注册过的图标ID也可以使用状态栏的图标ID例如lv, hp, up, save, settings等。
x和y为绘制的左上角坐标w和h可选为绘制的宽高如果不填或null则使用该图标的默认宽高。
// ------ 具体的某个UI界面的绘制 ------ //
core.closePanel()
结束一切事件和UI绘制关闭UI窗口返回游戏。
@ -1702,16 +1765,21 @@ core.clearUI()
重置UI窗口。此函数将清掉所有的UI帧动画和光标清空UI画布并将alpha设为1。
core.drawTip(text, id)
core.drawTip(text, id, clear)
在左上角以气泡的形式绘制一段提示。
text为文字内容仅支持${}的表达式计算,不支持换行和变色。
id可选为同时绘制的图标ID如果不为null则会同时绘制该图标仅对32x32的素材有效
也可以使用状态栏的图标ID例如lv, hp, up, save, settings等。
如果clear为true则会清空当前所有正在显示的提示。
core.clearTip()
清空当前所有正在显示的提示。
core.drawText(content, callback)
绘制一段文字。contents为一个字符串或一个字符串数组callback为全部绘制完毕的回调。
支持所有的文字效果(如\n${}\r\\i等也支持\t和\b的语法。
支持所有的文字效果(如\n${}\r\\i\\c\\d\\e等),也支持\t和\b的语法。
如果当前在事件处理中或录像回放中则会自动转成core.insertAction处理。
不建议使用该函数如有绘制文字的需求请尽量使用core.insertAction()插入剧情文本事件。
@ -1736,7 +1804,8 @@ posInfo如果不为null则是一个含position, px和py的对象表示一个
core.drawTextContent(ctx, content, config)
根据配置在某个画布上绘制一段文字。此函数会被core.drawTextBox()所调用。
ctx为画布名或画布本身如果不设置则会忽略该函数。
content为要绘制的文字内容支持所有的文字效果如\n${}\r\\i等但不支持支持\t和\b的语法。
content为要绘制的文字内容支持所有的文字效果如\n${}\r\\i\\c\\d\\e等
,但不支持支持\t和\b的语法。
config为绘制的配置项目前可以包括如下几项
- left, top在该画布上绘制的左上角像素位置不设置默认为(0,0)。
> 该函数绘制时会将textBaseline设置为'top',因此只需要考虑第一个字的左上角位置。
@ -1745,13 +1814,14 @@ config为绘制的配置项目前可以包括如下几项
- bold是否粗体。如果不设置默认为false。
- align文字对齐方式仅在maxWidth设置时有效默认为'left'。
- fontSize字体大小如果不设置则使用剧情文本设置中的正文字体大小。
- lineHeight绘制的行距值如果不设置则使用fontSize*1.3即1.3行距)。
- lineHeight绘制的行距值如果不设置则使用fontSize*1.3即1.3行距)。
- time打字机效果。若不为0则会逐个字进行绘制并设置core.status.event.interval定时器。
- interval字符间的间距。值表示绘制每个字符之间间隔的距离默认为0。
core.drawTextBox(content, showAll)
绘制一个对话框。content为一个字符串或一个字符串数组。
支持所有的文字效果(如\n${}\r\\i等也支持\t和\b的语法。
支持所有的文字效果(如\n${}\r\\i\\c\\d\\e等),也支持\t和\b的语法。
该函数将使用用户在剧情文本设置中的配置项进行绘制。
实际执行时会计算文本框宽度并绘制背景绘制标题和头像再调用core.drawTextContent()绘制正文内容。
showAll可选如果为true则不会使用打字机效果而全部显示主要用于打字机效果的点击显示全部。
@ -1759,7 +1829,7 @@ showAll可选如果为true则不会使用打字机效果而全部显示
core.drawScrollText(content, time, lineHeight, callback)
绘制一个滚动字幕。content为绘制内容time为总时间默认为5000lineHeight为行距比例默认为1.4)。
滚动字幕将绘制在UI上支持所有的文字效果如\n${}\r\\i等但不支持\t和\b效果。
滚动字幕将绘制在UI上支持所有的文字效果如\n${}\r\\i\\c\\d\\e等),但不支持\t和\b效果。
可以通过剧情文本设置中的align控制是否居中绘制offset控制其距离左边的偏移量。
@ -1771,7 +1841,7 @@ core.textImage(content, lineHeight)
core.drawChoices(content, choices)
绘制一个选项框。
content可选为选项上方的提示文字支持所有的文字效果如\n${}\r\\i等也支持\t效果
content可选为选项上方的提示文字支持所有的文字效果如\n${}\r\\i\\c\\d\\e等),也支持\t。
choices必选为要绘制的选项内容是一个列表。其中的每一项
- 可以是一个字符串,表示选项文字,将使用剧情文本设置中的正文颜色来绘制,仅支持${}表达式计算。
- 或者是一个包含text, color和icon的对象。
@ -1838,11 +1908,14 @@ z值为创建的纵向高度关系到画布之间的覆盖z值高的将
core.ui.relocateCanvas(name, x, y)
重新定位一个自定义画布。x和y为画布的左上角坐标。
重新定位一个自定义画布。x和y为画布的左上角坐标name为画布名
core.ui.resizeCanvas(name, width, height)
重新设置一个自定义画布的大小。width和height为新设置的宽高。此操作会清空画布。
core.ui.resizeCanvas(name, width, height, styleOnly)
重新设置一个自定义画布的大小。width和height为新设置的宽高。
styleOnly控制是否只修改画布的显示大小而不修改画布的内部大小
如果styleOnly为true则只修改其显示大小即canvas.style.width
否则,则会同时修改画布的显示大小和内部大小并清空画布内容。
core.ui.deleteCanvas(name)
@ -1862,6 +1935,11 @@ core.replayText(text, need, times)
将一段文字中的${}表达式进行替换。need和time一般可以直接忽略。
core.replaceValue(value)
对一个表达式中的特殊规则进行替换如status:xxx等。
请注意此项不会对独立开关如switch:A进行替换。
core.calValue(value, prefix, need, time)
计算一个表达式的值支持status:xxx等的计算。
prefix为前缀switch:xxx的独立开关使用need和time一般可以直接忽略。
@ -1914,6 +1992,17 @@ errorCallback可选如果失败则会将错误信息传入errorCallback()
此函数是异步的,只能通过回调函数来获得读取的结果或错误信息。
core.setGlobal(key, value)
设置一个全局存储适用于global:xxx。
录像播放时将忽略此函数否则直接调用core.setLocalStorage。
core.getGlobal(key, value)
获得一个全局存储适用于global:xxx支持录像。
正常游戏时将使用core.getLocalStorage获得具体的数据并将结果存放到录像中。
录像播放时会直接从录像中获得对应的数据。
core.clone(data, filter, recursion)
深拷贝一个对象。有关浅拷贝,深拷贝,基本类型和引用类型等相关知识可参见:
https://zhuanlan.zhihu.com/p/26282765
@ -2013,6 +2102,7 @@ core.matchWildcard(pattern, string)
core.encodeBase64(str) / core.decodeBase64(str)
将字符串进行base64加密或解密。
可用于解压缩录像数据
core.convertBase(str, fromBase, toBase)
@ -2035,8 +2125,9 @@ num如果设置大于0则生成一个[0, num-1]之间的数;否则生成一
即先生成一个真随机数根据该数来推进伪随机的种子这样就可以放心调用core.rand()啦。
core.readFile(success, error)
core.readFile(success, error, accept)
读取一个本地文件内容。success和error分别为读取成功或失败的回调函数。
accept如果设置则控制能选择的文件类型。
iOS平台暂不支持读取文件操作。
@ -2087,7 +2178,16 @@ core.same(a, b)
如果a和b都是数组则会递归依次比较数组中的值如果都是对象亦然。
core.utils.http(type, url, formData, success, error, mimeType, responseType)
core.unzip(blobOrUrl, success, error, convertToText)
解压一个zip文件。
blobOrUrl为传入的二进制zip文件Blob格式或zip文件的地址。
success为成功后的回调接收 文件名-文件内容 形式的对象,即
{"filename1": ..., "filename2": ...}
error为失败的回调接收参数message为错误信息。
convertToText如果为true则会将每个文件内容转成纯文本而不是二进制格式。
core.http(type, url, formData, success, error, mimeType, responseType)
发送一个异步HTTP请求。
type为'GET'或者'POST'url为目标地址formData如果是POST请求则为表单数据。
success为成功后的回调error为失败后的回调。

View File

@ -1,6 +1,6 @@
# 元件说明
?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.6**,上次更新时间:* {docsify-updated} *
在本章中,将对样板里的各个元件进行说明。各个元件主要包括道具、门、怪物、楼梯等等。
@ -282,10 +282,13 @@ floorId指定的是目标楼层的唯一标识符ID
- 使用`${}`来计算一个表达式的值,如`${status:atk+status:def}`。
- 使用`\f[...]`来同时插入一张立绘图,如`\f[1.png,100,200]`。
- 使用`\\i[...]`来在对话框中绘制一个图标,如`\\i[fly]`。
- 使用`\\c[...]`来修改字体大小,如`\\b[16]`。
- 使用`\\d`来加粗或者取消粗体。
- 使用`\\e`来加斜体或取消斜体。
从V2.5.2开始,也允许绘制一张头像图在对话框中,只要通过`\t[1.png]`或`\t[标题,1.png]`的写法。
**使用`\\i[...]`绘制图标请注意:在事件块中,允许只写一个反斜杠`\i`,系统会自动转义成`\\i`;但是在脚本中必须两个反斜杠都写上!**
**使用`\\i,\\c,\\d,\\e`时请注意:在事件块中,允许只写一个反斜杠`\`,系统会自动转义成`\\`;但是在脚本中必须两个反斜杠都写上!**
详细信息请参见[剧情文本控制](event#text显示一段文字剧情)中的说明。

File diff suppressed because it is too large Load Diff

BIN
_docs/img/autoEvent.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
_docs/img/events/1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
_docs/img/events/10.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
_docs/img/events/11.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
_docs/img/events/12.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
_docs/img/events/13.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
_docs/img/events/14.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
_docs/img/events/15.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
_docs/img/events/15.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
_docs/img/events/16.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
_docs/img/events/17.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
_docs/img/events/18.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
_docs/img/events/19.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
_docs/img/events/2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
_docs/img/events/20.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
_docs/img/events/21.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
_docs/img/events/22.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
_docs/img/events/23.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
_docs/img/events/24.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
_docs/img/events/25.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
_docs/img/events/26.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
_docs/img/events/27.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
_docs/img/events/28.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
_docs/img/events/29.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
_docs/img/events/3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
_docs/img/events/30.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
_docs/img/events/31.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
_docs/img/events/32.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
_docs/img/events/33.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
_docs/img/events/34.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
_docs/img/events/35.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
_docs/img/events/36.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
_docs/img/events/37.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
_docs/img/events/38.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
_docs/img/events/39.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
_docs/img/events/4.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
_docs/img/events/40.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
_docs/img/events/41.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
_docs/img/events/42.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
_docs/img/events/43.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
_docs/img/events/44.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
_docs/img/events/45.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
_docs/img/events/46.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
_docs/img/events/47.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
_docs/img/events/48.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
_docs/img/events/49.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
_docs/img/events/5.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
_docs/img/events/50.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
_docs/img/events/51.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
_docs/img/events/52.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
_docs/img/events/52.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

BIN
_docs/img/events/53.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
_docs/img/events/54.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
_docs/img/events/55.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

BIN
_docs/img/events/56.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
_docs/img/events/57.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
_docs/img/events/58.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
_docs/img/events/59.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
_docs/img/events/6.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
_docs/img/events/60.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
_docs/img/events/7.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
_docs/img/events/7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

BIN
_docs/img/events/8.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
_docs/img/events/9.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -1,6 +1,6 @@
# HTML5 魔塔样板说明文档
?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.6**,上次更新时间:* {docsify-updated} *
众所周知魔塔的趋势是向移动端发展贴吧中也常常能见到“求手机魔塔”的帖子。然而现有的工具中NekoRPG有着比较大的局限性游戏感较差更是完全没法在iOS上运行。而一些APP的魔塔虽然可用但是必须要下载安装对于Android和iOS还必须开发不同的版本非常麻烦。

View File

@ -1,6 +1,6 @@
# 个性化
?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.6**,上次更新时间:* {docsify-updated} *
有时候只靠样板本身可能是不够的。我们需要一些个性化、自定义的素材,道具效果,怪物属性,等等。
@ -22,6 +22,7 @@ HTML5魔塔是使用画布canvas来绘制存在若干个图层它们
- paint**[D]**绘图层主要用来进行绘图模式。z-index: 95)
- curtain色调层用来控制当前楼层的画面色调 (z-index: 125)
- image1\~50**[D]**图片层用来绘制图片等操作。z-index: 100+code, 101~150
- uievent**[D]**自定义UI绘制层用来进行自定义UI绘制等操作。z-index135可以通过事件设置该值
- uiUI层用来绘制一切UI窗口如剧情文本、怪物手册、楼传器、系统菜单等等 (z-index: 140)
- data数据层用来绘制一些顶层的或更新比较快的数据如左上角的提示战斗界面中数据的变化等等。 (z-index: 170)
@ -29,6 +30,8 @@ HTML5魔塔是使用画布canvas来绘制存在若干个图层它们
色调层的z-index是25ui层的z-index是140因此图片编号在1~24的将被色调层遮挡25~40的将被ui层遮挡41~50的将遮挡UI层。
uievent层为自定义UI绘制所在的层其z值初始是135可以通过事件设置自定义绘制的闪烁光标所在层的z值永远比该值大1。
### 动态创建canvas
从V2.5.3开始可以在H5样板中任意动态创建canvas并进行使用。
@ -559,8 +562,6 @@ core.statusBar.speed.innerHTML = core.getFlag('speed', 0);
如果flag:skill不为0则代表当前处于某个技能开启状态且状态栏显示flag:skillName值。伤害计算函数中只需要对flag:skill进行处理即可。
!> 关于魔力上限样板中默认没有提供status:manamax
### 状态栏的显示
从V2.5开始,魔力值和技能名的状态栏项目已经被添加,可以直接使用。

View File

@ -1,6 +1,6 @@
# 脚本
?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.6**,上次更新时间:* {docsify-updated} *
在V2.6版本中,基本对整个项目代码进行了重写,更加方便造塔者的使用和复写函数。
@ -224,7 +224,11 @@ function () {
- 清晰明了。很容易方便知道自己修改过什么,尤其是可以和系统原有代码进行对比。
- 方便整理成新的插件,给其他的塔使用。
如果我想对xxx文件中的yyy函数进行重写其模式一般是`core.xxx.yyy = function (参数列表) { ... }`
一般而言,复写规则如下:
**对xxx文件中的yyy函数进行复写规则是`core.xxx.yyy = function (参数列表) { ... }`。**
但是,对于`registerXXX`所注册的函数是无效的,例如直接复写`core.control._animationFrame_globalAnimate`函数是没有效果的。对于这种情况引入的函数,需要注册同名函数,可参见最下面的样例。
下面是几个例子,从简单到复杂。
@ -317,6 +321,32 @@ core.maps.drawMap = function (floorId, callback) {
详见[call和apply的用法](https://www.jianshu.com/p/80ea0d1c04f8)。
### 复写全局动画绘制函数
全局动画绘制在`control.js`的`_animationFrame_globalAnimate`函数。
注意到此函数是由`registerAnimationFrame`注册的,因此直接复写是无效的。
其在control.js的注册的定义如下
```js
// 注册全局动画函数
this.registerAnimationFrame("globalAnimate", true, this._animationFrame_globalAnimate);
```
因此,可以在插件中自行注册一个**同名**的函数来覆盖原始的内容。
```js
// 插件中复写全局动画绘制函数
this.myGlobalAnimate = function (timestamp) {
// ...... 实际复写的函数内容
}
// 注册同名globalAnimate函数来覆盖系统原始内容
core.registerAnimationFrame("globalAnimate", true, "myGlobalAnimate");
```
==========================================================================================
[继续阅读下一章API列表](api)

View File

@ -1,6 +1,6 @@
# 快速上手
?> 目前版本**v2.6**,上次更新时间:* {docsify-updated} *
?> 目前版本**v2.6.6**,上次更新时间:* {docsify-updated} *
在这一节中,将详细介绍做一部塔的流程。现在,让我们来做一部单层塔!
@ -235,7 +235,7 @@ HTML5的塔都是可以进行控制台调试的。
## 编辑器的基本操作
- **Alt+0~9, Ctrl+0~9** 保存和读取当前选中图块
- **Alt+0~9, 0~9** 保存和读取当前选中图块
- **W/A/S/D** 移动大地图
- **Ctrl+Z** 撤销上次绘图
- **Ctrl+Y** 重做上次绘图

File diff suppressed because it is too large Load Diff

View File

@ -1,142 +1,57 @@
# editor
[重构](refactoring.md)
直接使用游戏运行时(之后简称core)的代码来绘制游戏画面, 借助fs.js来实现浏览器编辑文件. 通过表格编辑数据, blockly图块编辑事件, code mirror编辑文本的可视化魔塔编辑器.
>! 以下均是v2.0时的说明, 未及时改动
![](img_md/view1.png)
本目录下所有文件,以及`../editor.html`和`../启动服务.exe`([源码](http://github.com/ckcz123/mota-js-server/))是地图编辑器的所有组件.
左侧数据区, 中间地图区, 右侧素材区
`editor.js`,`editor_file.js`和`editor_mode.js`耦合较强,`editor_blockly.js`和`editor_multi.js`和`fs.js`基本可以独立使用.
![](img_md/view2.png)
## 各组件功能
事件编辑器
### 总体上
![](img_md/view3.png)
以`display:none`的形式引入了`index.html`的`dom`,修改了原来的`.gameCanvas #ui #data`等的名字以避免冲突
脚本编辑器
通过`main.init('editor')`加载数据
> 此文件是editor的结构说明, 不是使用文档
`editor`模式关闭了部分动画
## 组成
`core.drawMap`中`editor`模式下不再画图,而是生成画图的函数提供给`editor`
本目录下所有文件,以及`../editor.html`,`../editor-mobile.html`和`../启动服务.exe`,`../server.py`是地图编辑器的所有组件.
`editor`模式下`GlobalAnimate`可以独立的选择是否播放
### 父目录
+ editor(-mobile).html
编辑器的[入口页面](http://127.0.0.1:1055/editor.html)
以`display:none`的形式引入了core的`index.html`的`dom`,修改了原来的`.gameCanvas #ui #data`等的名字以避免冲突
+ 启动服务.exe [源码](http://github.com/ckcz123/mota-js-server/)
为fs.js提供后端支持, 同时集成了一些实用工具
+ server.py
非windows平台中为fs.js提供后端支持
`core.playBgm`和`core.playSound`中非`play`模式不再播放声音
### core
`core.show`和`core.hide`中非`play`模式不再进行动画而是立刻完成并执行回调
游戏运行时中部分代码根据`main.mod=='editor'`进行了调整
`editor`模式不执行`core.resize`
+ 通过`main.init('editor')`加载数据
### editor.js
+ `editor`模式关闭了部分动画
``` js
editor.mapInit();//清空地图
editor.changeFloor('MT2')//切换地图
editor.util.guid()//产生一个可以作为id的长随机字符串
```
+ `core.drawMap`中`editor`模式下不再画图,而是生成画图的函数提+ 供给`editor`
`editor.updateMap`中画未定义快的报错
+ `editor`模式下`GlobalAnimate`可以独立的选择是否播放
### editor_file.js
+ `core.playBgm`和`core.playSound`中非`play`模式不再播放声音
提供了以下函数进行楼层`map`数组相关的操作
```javascript
editor.file.getFloorFileList
editor.file.loadFloorFile
editor.file.saveFloorFile
editor.file.saveFloorFileAs
```
+ `core.show`和`core.hide`中非`play`模式不再进行动画而是立刻+ 完成并执行回调
编辑模式有关的查询
```javascript
editor.file.editItem('redJewel',[],function(a){console.log(a)});
editor.file.editEnemy('redBat',[],function(a){console.log(a)});
editor.file.editLoc(2,0,[],function(a){console.log(a)});
editor.file.editFloor([],function(a){console.log(a)});
editor.file.editTower([],function(a){console.log(a)});
editor.file.editFunctions([],function(a){console.log(a)});
```
+ `editor`模式不执行`core.resize`
编辑模式有关的编辑
```javascript
editor.info={images: "terrains", y: 9};
editor.file.changeIdAndIdnum('yellowWall2',16,editor.info,function(a){console.log(a)});
editor.file.editItem('book',[["change","['items']['name']","怪物手册的新名字"]],function(a){console.log(a)});
editor.file.editEnemy('redBat',[['change',"['atk']",20]],function(a){console.log(a)});
editor.file.editLoc(2,6,[["change","['afterBattle']",null]],function(a){console.log(a)});
editor.file.editFloor([["change","['title']",'样板 33 层']],function(a){console.log(a)});
editor.file.editTower([["change","['values']['lavaDamage']",200]],function(a){console.log(a)});
editor.file.editFunctions(["change","['events']['afterChangeLight']","function(x,y){console.log(x,y)}"],function(a){console.log(a)});
```
### editor_mode.js
生成表格并绑定事件的函数
```javascript
editor.mode.loc();
editor.mode.enemyitem();
editor.mode.floor();
editor.mode.tower();
editor.mode.functions();
```
切换模式
```javascript
editor.mode.onmode('');//清空
editor.mode.onmode('save');//保存
editor.mode.onmode('nextChange');//下次onmode时前端进行切换
editor.mode.onmode('loc');
editor.mode.onmode('enemyitem');
editor.mode.onmode('floor');
editor.mode.onmode('tower');
editor.mode.onmode('functions');
editor.mode.onmode('map');
editor.mode.onmode('appendpic');
```
在`onmode('save')`时,改动才会保存到文件,涉及到图片的改动需要刷新页面使得`editor`能看到
表格的`onchange`的实现中,获得当前模式的方式.不注意的话,修改`index.html`中页面的结构,会被坑
```javascript
var node = thisTr.parentNode;
while (!editor_mode._ids.hasOwnProperty(node.getAttribute('id'))) {
node = node.parentNode;
}
editor_mode.onmode(editor_mode._ids[node.getAttribute('id')]);
```
`editor.mode.listen`中提供了追加素材的支持.
### editor_blockly.js
把选定`id_`的事件用blockly编辑
``` js
editor_blockly.import(id_,{type:'event'});
```
把文本区域的代码转换成图块
``` js
editor_blockly.parse();
```
### editor_multi.js
用[CodeMirror](https://github.com/codemirror/CodeMirror) 实现有高亮的多行文本编辑
编辑选定`id_`的文本域
``` js
editor_multi.import(id_,{lint:true})
```
编辑blockly方块的特定域
``` js
editor_multi.multiLineEdit(value,b,f,{lint:true},callback)
```
### fs.js
模仿node的fs模块提供如下api,与`启动服务.exe`配合为js提供文件读写功能
依照[issue#31](https://github.com/ckcz123/mota-js/issues/13)的约定, 模仿node的fs模块提供如下api,与`启动服务.exe`,`server.py`配合为js提供文件读写功能, 是编辑器成立的前提
``` js
fs.readFile('file.in','utf-8',callback)
//读文本文件
@ -164,3 +79,195 @@ fs.readdir(path, callback)
//所有参数不允许缺省
```
### editor_multi.js
用[CodeMirror](https://github.com/codemirror/CodeMirror) 实现有高亮的多行文本编辑
编辑选定`id_`的文本域
``` js
editor_multi.import(id_,{lint:true})
```
编辑blockly方块的特定域
``` js
editor_multi.multiLineEdit(value,b,f,{lint:true},callback)
```
配置表格
``` js
editor_multi.editCommentJs(mod)
```
### MotaAction.g4
通过[antlr-blockly](https://github.com/zhaouv/antlr-blockly)的语法定义core中各事件对应的方块.
借助google的[blockly](https://github.com/google/blockly)来实现事件的可视化编辑.
入口方块以`_m`结尾
一般语句写在`action`中, 以`_s`结尾
### editor_blockly.js
把选定`id_`的事件用blockly编辑
``` js
editor_blockly.import(id_,{type:'event'});
```
把文本区域的代码转换成图块
``` js
editor_blockly.parse();
```
`initscript中`的`toolboxObj`定义了侧边栏中显示的图块
自定义`Blockly.FieldColour.prototype.createWidget_`修改了颜色选择器的行为
自定义`Blockly.FieldTextInput.prototype.showInlineEditor_`添加了自动补全
### editor_mode.js
用于切换数据区
加载数据
```javascript
editor.mode.loc();
editor.mode.enemyitem();
editor.mode.floor();
editor.mode.tower();
editor.mode.functions();
```
切换模式
```javascript
editor.mode.onmode('');//清空
editor.mode.onmode('save');//保存
editor.mode.onmode('nextChange');//下次onmode时前端进行切换
editor.mode.onmode('loc');
editor.mode.onmode('enemyitem');
editor.mode.onmode('floor');
editor.mode.onmode('tower');
editor.mode.onmode('functions');
editor.mode.onmode('map');
editor.mode.onmode('appendpic');
```
在`onmode('save')`时,改动才会保存到文件,涉及到图片的改动需要刷新页面使得`editor`能看到
数据区一些通用的函数也定义在这里
### editor_table.js
处理表格的生成, 及其响应的事件
其接受来自../project/\*.js的数据`obj`和来自table/\*.comment.js的注释`commentObj`
commentObj的结构如示例
``` js
{
"_type": "object",
"_data": {
"events": {
"_type": "object",
"_data": {
"resetGame": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "重置整个游戏"
},
"setInitData": {
"_leaf": true,
"_type": "textarea",
"_lint": true,
"_data": "设置初始属性"
},
```
一层正常数据, 一层`_`开头的结构说明, 忽略`_`层的话与obj同结构
通过
``` js
editor.table.objToTable(obj, commentObj)
editor.table.objToTr
editor.table.objToTd
```
遍历这两个对象来生成表格, 叶节点根据`_type`渲染成对应的dom
表格的值变化`onchange`, 双击`dblclickfunc`, 删除`deletefunc`, 添加`addfunc`也定义在此文件
### editor_mappanel.js
与地图区相关的功能
+ 画地图 线/矩形/tileset
+ 通过地图选中事件或素材
+ 右键菜单
+ 切换楼层
+ 大地图移动可视窗口
### editor_materialpanel.js
与素材区相关的功能
+ 选中
+ 展开/折叠
### editor_datapanel.js
与数据区相关的功能 (且与表格无关的功能)
+ 地图编辑
- 创建新地图
- 批量创建
+ 地图选点
+ 图块属性
- 注册素材
- 修改id
+ 楼层属性
- 修改楼层id
+ 全塔属性
+ 脚本编辑
+ 追加素材
- 选择导入的区域
- 导入图片
- 改色相
- 选中图片中的格子
- 确认追加
+ 公共事件
+ 插件编写
### editor_ui.js
ui事件中没有具体到前三个区中的函数
+ 响应点击
+ 快捷键
+ 显示帮助
+ UI预览 & 地图选点相关
### editor_util.js
一些通用的函数
+ 生成id
+ HTML转义
+ 像素处理
+ base64的encode/decode
+ 检查值是否为空
### editor_listen.js
界面与功能的绑定
### editor_file.js
包装fs.js, 把数据读写到对应的文件
### editor_game.js
游戏数据的处理
此部分的重构未完成, 实际上是由editor_file.js和editor_file_unsorted.js来做的
### editor.js
初始化加整合各模块
现状是还放了一些游戏数据有关的函数未挪到editor_game, 以及部分和入口页面生成有关的函数

View File

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2014 Peter Dematté
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.

1
_server/config.json Normal file
View File

@ -0,0 +1 @@
{"lastUsed":[],"foldPerCol":50,"folded":false,"editorLastFloorId":null,"disableBlocklyReplace":false,"shortcut":{"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0}}

View File

@ -40,7 +40,7 @@ body {
width: 104px;
}
#left, #mid, #right {
#left, #mid, #mid2, #right {
border-radius: 2px;
box-sizing: border-box;
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 3px 1px -2px rgba(0, 0, 0, .2), 0 1px 5px 0 rgba(0, 0, 0, .12);
@ -130,6 +130,14 @@ body {
height: 630px;
}
#mid2 {
position: absolute;
left: 448px;
top: 650px;
width: 440px;
bottom: 10px;
}
#mapEdit {
overflow: hidden;
}
@ -142,6 +150,13 @@ body {
height: 416px;
}
#lastUsedDiv {
height: auto;
bottom: 0;
margin-top: 20px;
overflow: hidden;
}
#mid .tools {
position: absolute;
width: 425px;
@ -239,15 +254,15 @@ body {
position: absolute;
left: 900px;
top: 10px;
width: 440px;
height: 630px;
right: 0;
bottom: 0;
/* border: 1px solid rgb(238, 13, 13); */
}
#iconLib {
position: absolute;
width: 435px;
height: 620px;
right: 0;
bottom: 0;
left: 5px;
top: 5px;
overflow: auto;
@ -262,10 +277,6 @@ body {
position: absolute;
}
.egameCanvas {
position: absolute;
}
.gameCanvas {
position: absolute;
}
@ -287,6 +298,15 @@ body {
0 0 0 3px #000;
}
#iconExpandBtn {
position: absolute;
left: 20px;
bottom: 30px;
font-size: 15px;
padding: 6px;
display: none;
}
.warnText {
color: #D50000;
font-weight: 700;
@ -458,4 +478,88 @@ table.row td {
left: 6px;
top: 6px;
background-image:url('data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIGJhc2VQcm9maWxlPSJmdWxsIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWxuczpldj0iaHR0cDovL3d3dy53My5vcmcvMjAwMS94bWwtZXZlbnRzIj4KPGc%2BCgk8cG9seWdvbiBmaWxsPSIjNjY2IiBwb2ludHM9IjkuMjA3LDYuMTI2IDcuNzkzLDcuNTQxIDExLjc5MywxMS41NDEgMTMuMjA3LDEwLjEyNiIgLz4KCTxwYXRoIGZpbGw9IiM2NjYiIGQ9Ik01LjkxNywyYzEuNjA4LDAsMi45MTcsMS4zMDgsMi45MTcsMi45MTdTNy41MjUsNy44MzMsNS45MTcsNy44MzNTMyw2LjUyNSwzLDQuOTE3UzQuMzA4LDIsNS45MTcsMgoJCSBNNS45MTcsMEMzLjIwMSwwLDEsMi4yMDEsMSw0LjkxN3MyLjIwMSw0LjkxNyw0LjkxNyw0LjkxN3M0LjkxNy0yLjIwMSw0LjkxNy00LjkxN0MxMC44MzMsMi4yMDEsOC42MzIsMCw1LjkxNywwTDUuOTE3LDB6IiAvPgo8L2c%2BCjwvc3ZnPgo%3D');
}
#uieventDiv {
display: none;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background: rgba(127,127,127,0.6);
z-index: 2000
}
#uieventDialog {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -60%);
background: white;
width: 436px;
}
#uieventHead {
margin: 10px 20px;
}
#uieventTitle {
font-weight: bold;
}
#uieventNo {
float: right;
}
#uieventYes {
display: none;
float: right;
margin-right: 15px;
}
#uieventBody {
width: 416px;
height: 416px;
position: relative;
margin-left: 10px;
margin-bottom: 5px;
overflow: hidden;
}
#uievent {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
#selectPoint {
display: none;
margin-left: 10px;
margin-bottom: 10px;
}
#selectPointFloor {
margin-right: 10px;
}
#selectPointButtons {
display: inline;
}
#selectPointBox {
position: absolute;
z-index: 75;
width: 26px;
height: 26px;
margin: 3px 0 0 3px;
padding: 0;
/* display: none; */
box-sizing: border-box;
background-color: rgba(255, 255, 255, 0.0);
border: 1px solid #000;
box-shadow: 0 0 0 2px #fff,
0 0 0 3px #000;
}

View File

@ -110,6 +110,10 @@ body {
position: absolute;
}
#mid2 {
display: none;
}
#mapEdit {
overflow: hidden;
}
@ -247,10 +251,6 @@ body {
position: absolute;
}
.egameCanvas {
position: absolute;
}
.gameCanvas {
position: absolute;
}
@ -272,6 +272,15 @@ body {
0 0 0 3px #000;
}
#iconExpandBtn {
position: absolute;
left: 20px;
bottom: 30px;
font-size: 15px;
padding: 6px;
display: none;
}
.warnText {
color: #D50000;
font-weight: 700;
@ -433,7 +442,7 @@ div.row .rowtd .rowtext{
font: normal 2.5vw Arial, sans-serif;
list-style: none;
margin: 0;
padding: 4px 7em 4px 28px;
padding: 4px 7em 4px 4px;
white-space: nowrap;
/* padding-left: 12px; */
@ -482,4 +491,88 @@ div.row .rowtd .rowtext{
margin: 2px 0;
border-radius: 3px;
width: 90px;
}
#uieventDiv {
display: none;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background: rgba(127,127,127,0.6);
z-index: 2000
}
#uieventDialog {
position: fixed;
top: 50%;
left: 0;
transform: translateY(-50%);
background: white;
width: 100vw;
}
#uieventHead {
margin: 10px 20px;
}
#uieventTitle {
font-weight: bold;
}
#uieventNo {
float: right;
}
#uieventYes {
display: none;
float: right;
margin-right: 15px;
}
#uieventBody {
width: 100vw;
height: 100vw;
position: relative;
margin-left: 0;
margin-bottom: 5px;
overflow: hidden;
}
#uievent {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
}
#selectPoint {
display: none;
margin-left: 10px;
margin-bottom: 10px;
}
#selectPointFloor {
margin-right: 10px;
}
#selectPointButtons {
display: inline;
}
#selectPointBox {
position: absolute;
z-index: 75;
width: 26px;
height: 26px;
margin: 3px 0 0 3px;
padding: 0;
/* display: none; */
box-sizing: border-box;
background-color: rgba(255, 255, 255, 0.0);
border: 1px solid #000;
box-shadow: 0 0 0 2px #fff,
0 0 0 3px #000;
}

View File

@ -7,7 +7,7 @@
.leftTab {
overflow: auto;
position: absolute;
height: 630px;
bottom: 0;
}
.leftTab > * {
@ -121,6 +121,7 @@
display: block;
width: 100%;
overflow: auto;
word-break: break-all;
}
.etable table th {
@ -157,14 +158,19 @@
}
.etable tr > :nth-child(3) {
width: 60%
width: 35%;
}
.etable tr > :nth-child(4) {
width: 25%;
padding: 0;
}
.etable table {
overflow: visible;
}
.etable tr:not(:first-child) > :last-child:hover {
.etable tr:not(:first-child) > :nth-child(3):hover {
border: 1px solid rgb(87, 198, 232);
box-shadow: 0px 0px 3px rgb(87, 198, 232);
}
@ -175,14 +181,17 @@
box-shadow: 0px 0px 3px rgb(87, 232, 198);
}
.etable tr:not(:first-child) > :last-child {
.etable tr:not(:first-child) > :nth-child(3) {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
position: relative;
}
.etable tr > :nth-child(4) {
text-align: center;
}
div.etableInputDiv {
position: absolute;
padding: 5px 0 0 5px;

View File

@ -135,6 +135,7 @@
display: block;
width: 100%;
overflow: auto;
word-break: break-all;
}
.etable table th {
@ -171,14 +172,19 @@
}
.etable tr > :nth-child(3) {
width: 60%
width: 30%;
}
.etable tr > :nth-child(4) {
width: 30%;
text-align: center;
}
.etable table {
overflow: visible;
}
.etable tr:not(:first-child) > :last-child:hover {
.etable tr:not(:first-child) > :nth-child(3):hover {
border: 1px solid rgb(87, 198, 232);
box-shadow: 0px 0px 3px rgb(87, 198, 232);
}
@ -189,11 +195,10 @@
box-shadow: 0px 0px 3px rgb(87, 232, 198);
}
.etable tr:not(:first-child) > :last-child {
.etable tr:not(:first-child) > :nth-child(3) {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
position: relative;
}

View File

@ -4,6 +4,107 @@ function editor() {
this.layerMod = "map";//["fgmap","map","bgmap"]
this.isMobile = false;
this.dom={
body:document.body,
eui:document.getElementById('eui'),
euiCtx:document.getElementById('eui').getContext('2d'),
efgCtx:document.getElementById('efg').getContext('2d'),
mid:document.getElementById('mid'),
mapEdit:document.getElementById('mapEdit'),
selectFloor:document.getElementById('selectFloor'),
iconExpandBtn :document.getElementById('iconExpandBtn'),
dataSelection : document.getElementById('dataSelection'),
iconLib:document.getElementById('iconLib'),
midMenu:document.getElementById('midMenu'),
extraEvent: document.getElementById('extraEvent'),
chooseThis : document.getElementById('chooseThis'),
chooseInRight : document.getElementById('chooseInRight'),
copyLoc : document.getElementById('copyLoc'),
moveLoc : document.getElementById('moveLoc'),
clearEvent : document.getElementById('clearEvent'),
clearLoc : document.getElementById('clearLoc'),
brushMod:document.getElementById('brushMod'),
brushMod2:document.getElementById('brushMod2'),
brushMod3:document.getElementById('brushMod3'),
bgc : document.getElementById('bg'),
bgCtx : document.getElementById('bg').getContext('2d'),
fgc : document.getElementById('fg'),
fgCtx : document.getElementById('fg').getContext('2d'),
evc : document.getElementById('event'),
evCtx : document.getElementById('event').getContext('2d'),
ev2c : document.getElementById('event2'),
ev2Ctx : document.getElementById('event2').getContext('2d'),
layerMod:document.getElementById('layerMod'),
layerMod2:document.getElementById('layerMod2'),
layerMod3:document.getElementById('layerMod3'),
viewportButtons:document.getElementById('viewportButtons'),
appendPicCanvas : document.getElementById('appendPicCanvas'),
bg : document.getElementById('appendPicCanvas').children[0],
source : document.getElementById('appendPicCanvas').children[1],
picClick : document.getElementById('appendPicCanvas').children[2],
sprite : document.getElementById('appendPicCanvas').children[3],
sourceCtx:document.getElementById('appendPicCanvas').children[1].getContext('2d'),
spriteCtx:document.getElementById('appendPicCanvas').children[3].getContext('2d'),
appendPicSelection : document.getElementById('appendPicSelection'),
selectAppend : document.getElementById('selectAppend'),
selectFileBtn :document.getElementById('selectFileBtn'),
changeFloorId :document.getElementById('changeFloorId'),
left1 : document.getElementById('left1'),
editModeSelect :document.getElementById('editModeSelect'),
mid2 : document.getElementById('mid2'),
lastUsedDiv: document.getElementById('lastUsedDiv'),
lastUsed: document.getElementById('lastUsed'),
lastUsedCtx: document.getElementById('lastUsed').getContext('2d'),
lockMode: document.getElementById('lockMode'),
};
this.uivalues={
// 绘制区拖动有关
holdingPath : 0,
stepPostfix : null,//用于存放寻路检测的第一个点之后的后续移动
mouseOutCheck : 2,
startPos:null,
endPos:null,
// 撤销/恢复
preMapData : [],
preMapMax: 10,
postMapData: [],
//
shortcut:{},
copyedInfo : null,
// 折叠素材
scrollBarHeight :0,
folded:false,
foldPerCol: 50,
// 画图区菜单
lastRightButtonPos:[{x:0,y:0},{x:0,y:0}],
lastCopyedInfo : [null, null],
//
ratio : 1,
// blockly转义
disableBlocklyReplace: false,
// 绑定机关门事件相关
bindSpecialDoor: {
loc: null,
n: -1,
enemys: []
},
// 复制怪物或道具属性
copyEnemyItem : {
type: null,
data: {}
},
// tile
tileSize: [1,1],
lockMode: false,
// 最近使用的图块
lastUsed: [],
};
window.onerror = function (msg, url, lineNo, columnNo, error) {
var string = msg.toLowerCase();
var substring = "script error";
@ -30,6 +131,8 @@ function editor() {
};
}
editor.prototype.uifunctions={};
/*
editor.loc
editor.pos
@ -48,11 +151,20 @@ editor.prototype.init = function (callback) {
editor.airwallImg.src = './project/images/airwall.png';
main.init('editor', function () {
editor_util_wrapper(editor);
editor_game_wrapper(editor, main, core);
editor_table_wrapper(editor);
editor_unsorted_1_wrapper(editor);
afterMainInit();
editor.config = new editor_config();
editor.config.load(function() {
editor_util_wrapper(editor);
editor_game_wrapper(editor, main, core);
editor_file_wrapper(editor);
editor_table_wrapper(editor);
editor_ui_wrapper(editor);
editor_mappanel_wrapper(editor);
editor_datapanel_wrapper(editor);
editor_materialpanel_wrapper(editor);
editor_listen_wrapper(editor);
editor.printe=printe;
afterMainInit();
})
});
var afterMainInit = function () {
@ -63,10 +175,11 @@ editor.prototype.init = function (callback) {
editor_file = editor_file(editor, function () {
editor.file = editor_file;
editor_mode = editor_mode(editor);
editor_unsorted_2_wrapper(editor_mode);
editor.mode = editor_mode;
core.resetGame(core.firstData.hero, null, core.firstData.floorId, core.initStatus.maps);
core.changeFloor(core.status.floorId, null, core.firstData.hero.loc, null, function () {
core.resetGame(core.firstData.hero, null, core.firstData.floorId, core.clone(core.initStatus.maps));
var lastFloorId = editor.config.get('editorLastFloorId', core.status.floorId);
if (core.floorIds.indexOf(lastFloorId) < 0) lastFloorId = core.status.floorId;
core.changeFloor(lastFloorId, null, core.firstData.hero.loc, null, function () {
afterCoreReset();
}, true);
core.events.setInitData(null);
@ -96,6 +209,17 @@ editor.prototype.init = function (callback) {
editor_multi = editor_multi();
editor_blockly = editor_blockly();
// --- 所有用到的flags
editor.used_flags = {};
for (var floorId in editor.main.floors) {
editor.addUsedFlags(JSON.stringify(editor.main.floors[floorId]));
}
if (events_c12a15a8_c380_4b28_8144_256cba95f760.commonEvent) {
for (var name in events_c12a15a8_c380_4b28_8144_256cba95f760.commonEvent) {
editor.addUsedFlags(JSON.stringify(events_c12a15a8_c380_4b28_8144_256cba95f760.commonEvent[name]));
}
}
if (editor.useCompress == null) editor.useCompress = useCompress;
if (Boolean(callback)) callback();
@ -105,9 +229,9 @@ editor.prototype.init = function (callback) {
}
editor.prototype.mapInit = function () {
var ec = document.getElementById('event').getContext('2d');
var ec = editor.dom.evCtx;
ec.clearRect(0, 0, core.bigmap.width*32, core.bigmap.height*32);
document.getElementById('event2').getContext('2d').clearRect(0, 0, core.bigmap.width*32, core.bigmap.height*32);
editor.dom.ev2Ctx.clearRect(0, 0, core.bigmap.width*32, core.bigmap.height*32);
editor.map = [];
var sy=editor.currentFloorData.map.length,sx=editor.currentFloorData.map[0].length;
for (var y = 0; y < sy; y++) {
@ -140,53 +264,80 @@ editor.prototype.changeFloor = function (floorId, callback) {
});
editor.currentFloorData[name]=mapArray;
}
editor.preMapData = null;
editor.uivalues.preMapData = [];
editor.uivalues.postMapData = [];
editor.uifunctions._extraEvent_bindSpecialDoor_doAction(true);
core.changeFloor(floorId, null, {"x": 0, "y": 0, "direction": "up"}, null, function () {
core.bigmap.offsetX=0;
core.bigmap.offsetY=0;
editor.moveViewport(0,0);
editor.game.fetchMapFromCore();
editor.updateMap();
editor_mode.floor();
editor.drawEventBlock();
if (callback) callback();
editor.viewportLoc = editor.viewportLoc || {};
var loc = editor.viewportLoc[floorId] || [], x = loc[0] || 0, y = loc[1] || 0;
editor.setViewport(x, y);
editor.config.set('editorLastFloorId', floorId, function() {
if (callback) callback();
});
});
}
/////////// 游戏绘图相关 ///////////
editor.prototype.drawEventBlock = function () {
var fg=document.getElementById('efg').getContext('2d');
var fg=editor.dom.efgCtx;
fg.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__);
var firstData = editor.game.getFirstData();
for (var i=0;i<core.__SIZE__;i++) {
for (var j=0;j<core.__SIZE__;j++) {
var color=[];
var loc=(i+core.bigmap.offsetX/32)+","+(j+core.bigmap.offsetY/32);
if (editor.currentFloorId == firstData.floorId
&& loc == firstData.hero.loc.x + "," + firstData.hero.loc.y) {
fg.textAlign = 'center';
editor.game.doCoreFunc('fillBoldText', fg, 'S',
32 * i + 16, 32 * j + 28, '#FFFFFF', 'bold 30px Verdana');
}
if (editor.currentFloorData.events[loc])
color.push('#FF0000');
if (editor.currentFloorData.changeFloor[loc])
color.push('#00FF00');
if (editor.currentFloorData.autoEvent[loc]) {
var x = editor.currentFloorData.autoEvent[loc];
for (var index in x) {
if (x[index] && x[index].data) {
color.push('#FFA500');
break;
}
}
}
if (editor.currentFloorData.afterBattle[loc])
color.push('#FFFF00');
if (editor.currentFloorData.changeFloor[loc])
color.push('#00FF00');
if (editor.currentFloorData.afterGetItem[loc])
color.push('#00FFFF');
if (editor.currentFloorData.afterOpenDoor[loc])
color.push('#FF00FF');
if (editor.currentFloorData.cannotMove[loc])
color.push('#0000FF');
if (editor.currentFloorData.afterOpenDoor[loc])
color.push('#FF00FF');
for(var kk=0,cc;cc=color[kk];kk++){
fg.fillStyle = cc;
fg.fillRect(32*i+8*kk, 32*j+32-8, 8, 8);
}
var index = editor.uivalues.bindSpecialDoor.enemys.indexOf(loc);
if (index >= 0) {
fg.textAlign = 'right';
editor.game.doCoreFunc("fillBoldText", fg, index + 1,
32 * i + 28, 32 * j + 15, '#FF7F00', '14px Verdana');
}
}
}
}
editor.prototype.drawPosSelection = function () {
this.drawEventBlock();
var fg=document.getElementById('efg').getContext('2d');
var fg=editor.dom.efgCtx;
fg.strokeStyle = 'rgba(255,255,255,0.7)';
fg.lineWidth = 4;
fg.strokeRect(32*editor.pos.x - core.bigmap.offsetX + 4, 32*editor.pos.y - core.bigmap.offsetY + 4, 24, 24);
@ -238,30 +389,61 @@ editor.prototype.updateMap = function () {
//ctx.drawImage(core.material.images[tileInfo.images], 0, tileInfo.y*32, 32, 32, x*32, y*32, 32, 32);
}
// 绘制地图 start
var eventCtx = document.getElementById('event').getContext("2d");
var fgCtx = document.getElementById('fg').getContext("2d");
var bgCtx = document.getElementById('bg').getContext("2d");
for (var y = 0; y < editor.map.length; y++)
for (var y = 0; y < editor.map.length; y++) {
for (var x = 0; x < editor.map[0].length; x++) {
var tileInfo = editor.map[y][x];
drawTile(eventCtx, x, y, tileInfo);
drawTile(editor.dom.evCtx, x, y, tileInfo);
tileInfo = editor.fgmap[y][x];
drawTile(fgCtx, x, y, tileInfo);
drawTile(editor.dom.fgCtx, x, y, tileInfo);
tileInfo = editor.bgmap[y][x];
drawTile(bgCtx, x, y, tileInfo);
drawTile(editor.dom.bgCtx, x, y, tileInfo);
}
}
// 绘制地图 end
this.updateLastUsedMap();
}
editor.prototype.moveViewport=function(x,y){
core.bigmap.offsetX = core.clamp(core.bigmap.offsetX+32*x, 0, 32*core.bigmap.width-core.__PIXELS__);
core.bigmap.offsetY = core.clamp(core.bigmap.offsetY+32*y, 0, 32*core.bigmap.height-core.__PIXELS__);
editor.prototype.updateLastUsedMap = function () {
// 绘制最近使用事件
var ctx = editor.dom.lastUsedCtx;
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.strokeStyle = 'rgba(255,128,0,0.85)';
ctx.lineWidth = 4;
for (var i = 0; i < editor.uivalues.lastUsed.length; ++i) {
try {
var x = i % core.__SIZE__, y = parseInt(i / core.__SIZE__);
var info = editor.uivalues.lastUsed[i];
if (!info || !info.images) continue;
if (info.isTile && core.material.images.tilesets[info.images]) {
ctx.drawImage(core.material.images.tilesets[info.images], 32 * info.x, 32 * info.y, 32, 32, x*32, y*32, 32, 32);
} else if (info.images == 'autotile' && core.material.images.autotile[info.id]) {
ctx.drawImage(core.material.images.autotile[info.id], 0, 0, 32, 32, x * 32, y * 32, 32, 32);
} else {
var per_height = info.images.endsWith('48') ? 48 : 32;
ctx.drawImage(core.material.images[info.images], 0, info.y * per_height, 32, per_height, x * 32, y * 32, 32, 32);
}
if (selectBox.isSelected() && editor.info.id == info.id) {
ctx.strokeRect(32 * x + 2, 32 * y + 2, 28, 28);
}
} catch (e) {}
}
}
editor.prototype.setViewport=function (x, y) {
core.bigmap.offsetX = core.clamp(x, 0, 32*core.bigmap.width-core.__PIXELS__);
core.bigmap.offsetY = core.clamp(y, 0, 32*core.bigmap.height-core.__PIXELS__);
editor.viewportLoc = editor.viewportLoc || {};
editor.viewportLoc[editor.currentFloorId] = [core.bigmap.offsetX, core.bigmap.offsetY];
core.control.updateViewport();
editor.buildMark();
editor.drawPosSelection();
}
editor.prototype.moveViewport=function(x,y){
editor.setViewport(core.bigmap.offsetX+32*x, core.bigmap.offsetY+32*y);
}
/////////// 界面交互相关 ///////////
editor.prototype.drawInitData = function (icons) {
@ -270,7 +452,11 @@ editor.prototype.drawInitData = function (icons) {
var maxHeight = 700;
var sumWidth = 0;
editor.widthsX = {};
editor.uivalues.folded = editor.config.get('folded', false);
// editor.uivalues.folded = true;
editor.uivalues.foldPerCol = editor.config.get('foldPerCol', 50);
// var imgNames = Object.keys(images); //还是固定顺序吧;
editor.uivalues.lastUsed = editor.config.get("lastUsed", []);
var imgNames = ["terrains", "animates", "enemys", "enemy48", "items", "npcs", "npc48", "autotile"];
for (var ii = 0; ii < imgNames.length; ii++) {
@ -280,20 +466,21 @@ editor.prototype.drawInitData = function (icons) {
for (var im in autotiles) {
tempy += autotiles[im].height;
}
editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + 3 * 32) / 32, tempy];
sumWidth += 3 * 32;
var tempx = editor.uivalues.folded ? 32 : 3 * 32;
editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + tempx) / 32, tempy];
sumWidth += tempx;
maxHeight = Math.max(maxHeight, tempy);
continue;
}
if (img == 'terrains') {
editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + images[img].width) / 32, images[img].height + 32*2]
sumWidth += images[img].width;
maxHeight = Math.max(maxHeight, images[img].height + 32*2);
continue;
var width = images[img].width, height = images[img].height, mh = height;
if (editor.uivalues.folded) {
var per_height = (img == 'enemy48' || img == 'npc48' ? 48 : 32);
width = Math.ceil(height / per_height / editor.uivalues.foldPerCol) * 32;
if (width > 32) mh = per_height * editor.uivalues.foldPerCol;
}
editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + images[img].width) / 32, images[img].height];
sumWidth += images[img].width;
maxHeight = Math.max(maxHeight, images[img].height);
editor.widthsX[img] = [img, sumWidth / 32, (sumWidth + width) / 32, height];
sumWidth += width;
maxHeight = Math.max(maxHeight, mh + 64);
}
var tilesets = images.tilesets;
for (var ii in core.tilesets) {
@ -310,82 +497,75 @@ editor.prototype.drawInitData = function (icons) {
if (fullWidth > edata.width) edata.style.width = (edata.width = fullWidth) / ratio + 'px';
edata.style.height = (edata.height = fullHeight) / ratio + 'px';
*/
var iconImages = document.getElementById('iconImages');
iconImages.style.width = (iconImages.width = fullWidth) / ratio + 'px';
iconImages.style.height = (iconImages.height = fullHeight) / ratio + 'px';
var dc = {drawImage:function(){
var image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight;
var a=Array.prototype.slice.call(arguments)
if(arguments.length==3){
// [image, dx, dy]=arguments
// [sx, sy, sWidth, sHeight, dWidth, dHeight]=[0,0,image.width,image.height,image.width,image.height]
image=a[0]
a=[a[0],0,0,image.width,image.height,a[1],a[2],image.width,image.height]
}
if(arguments.length==5){
// [image, dx, dy, dWidth, dHeight]=arguments
// [sx, sy, sWidth, sHeight]=[0,0,image.width,image.height]
image=a[0]
a=[a[0],0,0,image.width,image.height,a[1],a[2],a[3],a[4]]
}
if(arguments.length==9){
// [image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight]=arguments
}
image=a[0];
sx=a[1];
sy=a[2];
sWidth=a[3];
sHeight=a[4];
dx=a[5];
dy=a[6];
dWidth=a[7];
dHeight=a[8];
//放弃对 dWidth, dHeight 的支持, 始终画一样大的
var dimg=new Image()
dimg.src = image.src;
dimg.style.clip=['rect(',sy,'px,',sx+sWidth,'px,',sy+sHeight,'px,',sx,'px)'].join('')
dimg.style.top=dy-sy+'px'
dimg.style.left=dx-sx+'px'
dimg.width=image.width/ratio
dimg.height=image.height/ratio
iconImages.appendChild(dimg)
}}
// var dc = edata.getContext('2d');
var nowx = 0;
var nowy = 0;
var drawImage = function (image, x, y) {
image.style.left = x + 'px';
image.style.top = y + 'px';
iconImages.appendChild(image);
}
var nowx = 0, nowy = 0;
for (var ii = 0; ii < imgNames.length; ii++) {
var img = imgNames[ii];
if (img == 'terrains') {
(function(image,dc,nowx){
(function(image,nowx){
if (image.complete) {
dc.drawImage(image, nowx, 32);
drawImage(image, nowx, 32);
core.material.images.airwall = image;
delete(editor.airwallImg);
} else image.onload = function () {
dc.drawImage(image, nowx, 32);
drawImage(image, nowx, 32);
core.material.images.airwall = image;
delete(editor.airwallImg);
editor.updateMap();
}
})(editor.airwallImg,dc,nowx);
dc.drawImage(images[img], nowx, 32*2);
nowx += images[img].width;
})(editor.airwallImg,nowx);
if (editor.uivalues.folded) {
// --- 单列 & 折行
var subimgs = core.splitImage(images[img], 32, editor.uivalues.foldPerCol * 32);
var frames = images[img].width / 32;
for (var i = 0; i < subimgs.length; i+=frames) {
drawImage(subimgs[i], nowx, i==0?2*32:0);
nowx += 32;
}
}
else {
drawImage(images[img], nowx, 32*2);
nowx += images[img].width;
}
continue;
}
if (img == 'autotile') {
var autotiles = images[img];
var tempx = editor.uivalues.folded ? 32 : 96;
for (var im in autotiles) {
dc.drawImage(autotiles[im], 0, 0, 96, 128, nowx, nowy, 96, 128);
var subimgs = core.splitImage(autotiles[im], tempx, autotiles[im].height);
drawImage(subimgs[0], nowx, nowy);
nowy += autotiles[im].height;
}
nowx += 3 * 32;
nowx += tempx;
continue;
}
dc.drawImage(images[img], nowx, 0)
nowx += images[img].width;
if (editor.uivalues.folded) {
// --- 单列 & 折行
var per_height = img.endsWith('48') ? 48 : 32;
var subimgs = core.splitImage(images[img], 32, editor.uivalues.foldPerCol * per_height);
var frames = images[img].width / 32;
for (var i = 0; i < subimgs.length; i+=frames) {
drawImage(subimgs[i], nowx, 0);
nowx += 32;
}
}
else {
drawImage(images[img], nowx, 0);
nowx += images[img].width;
}
}
for (var ii in core.tilesets) {
var img = core.tilesets[ii];
dc.drawImage(tilesets[img], nowx, 0)
drawImage(tilesets[img], nowx, 0);
nowx += tilesets[img].width;
}
//editor.mapInit();
@ -459,14 +639,20 @@ editor.prototype.setSelectBoxFromInfo=function(thisevent){
pos.x=editor.widthsX[thisevent.images][1];
pos.y=thisevent.y;
if(thisevent.x)pos.x+=thisevent.x;
if(thisevent.images=='terrains')pos.y+=2;
ysize = thisevent.images.endsWith('48') ? 48 : 32;
if (editor.uivalues.folded && core.tilesets.indexOf(thisevent.images)==-1) {
pos.x += Math.floor(pos.y / editor.uivalues.foldPerCol);
pos.y %= editor.uivalues.foldPerCol;
}
if(pos.x == 0) pos.y+=2;
}
var dataSelection = document.getElementById('dataSelection');
dataSelection.style.left = pos.x * 32 + 'px';
dataSelection.style.top = pos.y * ysize + 'px';
dataSelection.style.height = ysize - 6 + 'px';
setTimeout(function(){selectBox.isSelected(true);});
editor.dom.dataSelection.style.left = pos.x * 32 + 'px';
editor.dom.dataSelection.style.top = pos.y * ysize + 'px';
editor.dom.dataSelection.style.height = ysize - 6 + 'px';
setTimeout(function(){
selectBox.isSelected(true);
editor.updateLastUsedMap();
});
editor.info = JSON.parse(JSON.stringify(thisevent));
tip.infos(JSON.parse(JSON.stringify(thisevent)));
editor.pos=pos;
@ -474,12 +660,31 @@ editor.prototype.setSelectBoxFromInfo=function(thisevent){
editor_mode.onmode('enemyitem');
}
editor.prototype.addUsedFlags = function (s) {
s.replace(/flag:([a-zA-Z0-9_\u4E00-\u9FCC]+)/g, function (s0, s1) {
editor.used_flags[s1] = true; return s0;
});
s.replace(/flags\.([a-zA-Z_]\w*)/g, function (s0, s1) {
editor.used_flags[s1] = true; return s0;
});
if (window.flags) {
for (var s in editor.used_flags) {
if (!(s in window.flags)) {
window.flags[s] = null;
}
}
}
}
editor.prototype.listen = function () {
// 移动至 editor_unsorted_1.js
// 移动至 editor_listen.js
}//绑定事件
editor.prototype.mobile_listen=function(){
// 移动至 editor_unsorted_1.js
// 移动至 editor_listen.js
}
editor = new editor();

View File

@ -2,7 +2,11 @@ editor_blockly = function () {
var editor_blockly = {};
initscript = String.raw`
/////////////////initscript start/////////////////////////////
// do not use String.raw because of highlighting
// Comment tagged templates
// https://marketplace.visualstudio.com/items?itemName=bierner.comment-tagged-templates
initscript = /* js */`
(function(){
var getCategory = function(name,custom){
for(var node of document.getElementById('toolbox').children) {
@ -22,6 +26,16 @@ editor_blockly = function () {
"本事件触发一次后会消失",
{"type": "hide", "time": 500},
],'event'),
MotaActionFunctions.actionParser.parse({
"condition": "flag:__door__==2",
"currentFloor": true,
"priority": 0,
"delayExecute": false,
"multiExecute": false,
"data": [
{"type": "openDoor", "loc": [10,5]}
],
},'autoEvent'),
MotaActionBlocks['changeFloor_m'].xmlText(),
MotaActionFunctions.actionParser.parse([{
"id": "moneyShop1",
@ -30,12 +44,17 @@ editor_blockly = function () {
"textInList": "1F金币商店",
"use": "money",
"need": "20+10*times*(times+1)",
"text": "勇敢的武士啊,给我\${need}金币就可以:",
"text": "勇敢的武士啊,给我\\\${need}金币就可以:",
"choices": [
{"text": "生命+800", "effect": "status:hp+=800"},
{"text": "攻击+4", "effect": "status:atk+=4"},
{"text": "防御+4", "effect": "status:def+=4"},
{"text": "魔防+10", "effect": "status:mdef+=10"}
]
},{
"id": "itemShop",
"item": true,
"textInList": "道具商店",
"choices": [
{"id": "yellowKey", "number": 10, "money": 10}
]
},{
"id": "keyShop1",
@ -50,6 +69,7 @@ editor_blockly = function () {
MotaActionBlocks['eachArrive_m'].xmlText(),
MotaActionBlocks['level_m'].xmlText(),
MotaActionBlocks['commonEvent_m'].xmlText(),
MotaActionBlocks['item_m'].xmlText(),
],
'显示文字':[
MotaActionBlocks['text_0_s'].xmlText(),
@ -72,20 +92,21 @@ editor_blockly = function () {
MotaActionBlocks['confirm_s'].xmlText(),
MotaActionBlocks['choices_s'].xmlText([
'选择剑或者盾','流浪者','man',MotaActionBlocks['choicesContext'].xmlText([
'剑','','',null,MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]),
'剑','','',null,'',MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [3,3]}]),
MotaActionBlocks['choicesContext'].xmlText([
'盾','','',null,MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [9,3]}]),
'盾','','',null,'',MotaActionFunctions.actionParser.parseList([{"type": "openDoor", "loc": [9,3]}]),
])
])
]),
],
'数据相关':[
MotaActionBlocks['setValue_s'].xmlText([
MotaActionBlocks['idString_1_e'].xmlText(['status','hp'])
]),
MotaActionBlocks['addValue_s'].xmlText([
MotaActionBlocks['idString_1_e'].xmlText(['status','hp'])
MotaActionBlocks['idString_1_e'].xmlText(['status','生命']), '', false
]),
MotaActionBlocks['setValue_s'].xmlText([
MotaActionBlocks['idString_1_e'].xmlText(['status','生命']), '', false
]),
MotaActionBlocks['setEnemy_s'].xmlText(),
MotaActionBlocks['setFloor_s'].xmlText(),
MotaActionBlocks['setGlobalAttribute_s'].xmlText(),
MotaActionBlocks['setGlobalValue_s'].xmlText(),
@ -93,7 +114,6 @@ editor_blockly = function () {
MotaActionBlocks['input_s'].xmlText(),
MotaActionBlocks['input2_s'].xmlText(),
MotaActionBlocks['update_s'].xmlText(),
MotaActionBlocks['updateEnemys_s'].xmlText(),
MotaActionBlocks['moveHero_s'].xmlText(),
MotaActionBlocks['jumpHero_s'].xmlText(),
MotaActionBlocks['changeFloor_s'].xmlText(),
@ -101,6 +121,8 @@ editor_blockly = function () {
MotaActionBlocks['changePos_1_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(),
@ -108,6 +130,7 @@ editor_blockly = function () {
MotaActionBlocks['unfollow_s'].xmlText(),
],
'地图处理':[
MotaActionBlocks['battle_1_s'].xmlText(),
MotaActionBlocks['openDoor_s'].xmlText(),
MotaActionBlocks['closeDoor_s'].xmlText(),
MotaActionBlocks['show_s'].xmlText(),
@ -122,8 +145,8 @@ editor_blockly = function () {
MotaActionBlocks['hideFloorImg_s'].xmlText(),
],
'事件控制':[
MotaActionBlocks['if_s'].xmlText(),
MotaActionBlocks['if_1_s'].xmlText(),
MotaActionBlocks['if_s'].xmlText(),
MotaActionFunctions.actionParser.parseList({"type": "switch", "condition": "判别值", "caseList": [
{"action": [{"type": "comment", "text": "当判别值是值的场合执行此事件"}]},
{"action": [], "nobreak": true},
@ -141,12 +164,19 @@ editor_blockly = function () {
],
'特效/声音':[
MotaActionBlocks['sleep_s'].xmlText(),
MotaActionBlocks['wait_s'].xmlText(),
MotaActionFunctions.actionParser.parseList({"type": "wait", "data": [
{"case": "keyboard", "keycode": 13, "action": [{"type": "comment", "text": "当按下回车(keycode=13)时执行此事件"}]},
{"case": "mouse", "px": [0,32], "py": [0,32], "action": [{"type": "comment", "text": "当点击地图左上角时执行此事件"}]},
]}),
MotaActionBlocks['waitAsync_s'].xmlText(),
MotaActionBlocks['vibrate_s'].xmlText(),
MotaActionBlocks['animate_s'].xmlText(),
MotaActionBlocks['setViewport_s'].xmlText(),
MotaActionBlocks['moveViewport_s'].xmlText(),
MotaActionBlocks['showStatusBar_s'].xmlText(),
MotaActionBlocks['hideStatusBar_s'].xmlText(),
MotaActionBlocks['showHero_s'].xmlText(),
MotaActionBlocks['hideHero_s'].xmlText(),
MotaActionBlocks['setCurtain_0_s'].xmlText(),
MotaActionBlocks['setCurtain_1_s'].xmlText(),
MotaActionBlocks['screenFlash_s'].xmlText(),
@ -164,16 +194,39 @@ editor_blockly = function () {
MotaActionBlocks['autoSave_s'].xmlText(),
MotaActionBlocks['callLoad_s'].xmlText(),
],
'UI绘制':[
MotaActionBlocks['previewUI_s'].xmlText(),
MotaActionBlocks['clearMap_s'].xmlText(),
MotaActionBlocks['clearMap_1_s'].xmlText(),
MotaActionBlocks['setAttribute_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['fillCircle_s'].xmlText(),
MotaActionBlocks['strokeCircle_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['idString_1_e'].xmlText(['status','hp'])
]),
MotaActionBlocks['addValue_s'].xmlText([
MotaActionBlocks['idString_1_e'].xmlText(['status','hp'])
MotaActionBlocks['idString_1_e'].xmlText(['status','生命']), '', false
]),
MotaActionBlocks['setValue_s'].xmlText([
MotaActionBlocks['idString_1_e'].xmlText(['status','生命']), '', false
]),
MotaActionBlocks['expression_arithmetic_0'].xmlText(),
MotaActionBlocks['evFlag_e'].xmlText(),
@ -182,33 +235,37 @@ editor_blockly = function () {
MotaActionBlocks['idString_e'].xmlText(),
MotaActionBlocks['idString_1_e'].xmlText(),
MotaActionBlocks['idString_2_e'].xmlText(),
MotaActionBlocks['idString_3_e'].xmlText(),
MotaActionBlocks['idString_4_e'].xmlText(),
MotaActionBlocks['idString_5_e'].xmlText(),
MotaActionBlocks['idString_6_e'].xmlText(),
MotaActionBlocks['evalString_e'].xmlText(),
],
'常见事件模板':[
'<label text="检测音乐如果没有开启则系统提示开启"></label>',
MotaActionFunctions.actionParser.parseList({"type": "if", "condition": "!core.musicStatus.bgmStatus",
"true": [
"\t[系统提示]你当前音乐处于关闭状态,本塔开音乐游戏效果更佳"
"\\t[系统提示]你当前音乐处于关闭状态,本塔开音乐游戏效果更佳"
],
"false": []
}),
'<label text="商店购买属性/钥匙"></label>',
MotaActionFunctions.actionParser.parse([
{"type": "choices", "text": "\t[老人,man]少年,你需要钥匙吗?\n我这里有大把的",
{"type": "choices", "text": "\\t[老人,man]少年,你需要钥匙吗?\\n我这里有大把的",
"choices": [
{"text": "黄钥匙(\${9+flag:shop_times}金币)", "color": [255,255,0,1], "action": [
{"text": "黄钥匙(\\\${9+flag:shop_times}金币)", "color": [255,255,0,1], "action": [
{"type": "if", "condition": "status:money>=9+flag:shop_times",
"true": [
{"type": "addValue", "name": "status:money", "value": "-(9+flag:shop_times)"},
{"type": "addValue", "name": "item:yellowKey", "value": "1"},
],
"false": [
"\t[老人,man]你的金钱不足!",
"\\t[老人,man]你的金钱不足!",
{"type": "revisit"}
]
}
]},
{"text": "蓝钥匙(\${18+2*flag:shop_times}金币)", "color": [0,0,255,1], "action": [
{"text": "蓝钥匙(\\\${18+2*flag:shop_times}金币)", "color": [0,0,255,1], "action": [
]},
{"text": "离开", "action": [
{"type": "exit"}
@ -361,7 +418,7 @@ function omitedcheckUpdateFunction(event) {
}
}
try {
var code = Blockly.JavaScript.workspaceToCode(workspace).replace(/\\i/g, '\\\\i');
var code = Blockly.JavaScript.workspaceToCode(workspace).replace(/\\\\(i|c|d|e)/g, '\\\\\\\\$1');
codeAreaHL.setValue(code);
} catch (error) {
codeAreaHL.setValue(String(error));
@ -433,6 +490,18 @@ function omitedcheckUpdateFunction(event) {
}
})();
`;
/////////////////initscript end /////////////////////////////
editor.uivalues.disableBlocklyReplace = editor.config.get("disableBlocklyReplace", false);
var replaceCheckbox = document.getElementById('blocklyReplace');
replaceCheckbox.checked = !editor.uivalues.disableBlocklyReplace;
editor_blockly.triggerReplace = function () {
editor.uivalues.disableBlocklyReplace = !replaceCheckbox.checked;
editor.config.set("disableBlocklyReplace", !replaceCheckbox.checked);
if (MotaActionFunctions) MotaActionFunctions.disableReplace = !replaceCheckbox.checked;
alert("已" + (replaceCheckbox.checked ? "开启" : "关闭") + "中文变量名替换!\n关闭并重开事件编辑器以生效。");
}
var input_ = '';
editor_blockly.runOne = function () {
@ -463,6 +532,7 @@ function omitedcheckUpdateFunction(event) {
}
input_ = xhr.responseText;
editor_blockly.runOne();
MotaActionFunctions.disableReplace = editor.uivalues.disableBlocklyReplace;
}
xhr.open('GET', '_server/MotaAction.g4', true);
xhr.send(null);
@ -503,8 +573,7 @@ function omitedcheckUpdateFunction(event) {
MotaActionFunctions.parse(
eval('obj=' + codeAreaHL.getValue().replace(/[<>&]/g, function (c) {
return {'<': '&lt;', '>': '&gt;', '&': '&amp;'}[c];
}).replace(/\\r/g, '\\\\r').replace(/\\f/g, '\\\\f')
.replace(/\\i/,'\\\\i')),
}).replace(/\\(r|f|i|c|d|e)/g,'\\\\$1')),
document.getElementById('entryType').value
);
}
@ -578,14 +647,86 @@ function omitedcheckUpdateFunction(event) {
return;
}
var code = Blockly.JavaScript.workspaceToCode(editor_blockly.workspace);
code = code.replace(/\\i/g, '\\\\i');
code = code.replace(/\\(i|c|d|e)/g, '\\\\$1');
eval('var obj=' + code);
if (this.checkAsync(obj) && confirm("警告!存在不等待执行完毕的事件但却没有用【等待所有异步事件处理完毕】来等待" +
"它们执行完毕,这样可能会导致录像检测系统出问题。\n你要返回修改么")) return;
setvalue(JSON.stringify(obj));
}
// 检查"不等待处理完毕"
editor_blockly.checkAsync = function (obj) {
if (!(obj instanceof Array)) return false;
var hasAsync = false;
for (var i = 0; i < obj.length; ++i) {
var one = obj[i];
if (one.type == 'if' && (this.checkAsync(one['true']) || this.checkAsync(one['false'])))
return true;
if ((one.type == 'while' || one.type == 'dowhile') && this.checkAsync(one.data))
return true;
if (one.type == 'if' && (this.checkAsync(one.yes) || this.checkAsync(one.no)))
return true;
if (one.type == 'choices') {
var list = one.choices;
if (list instanceof Array) {
for (var j = 0; j < list.length; j++) {
if (this.checkAsync(list[j].action)) return true;
}
}
}
if (one.type == 'switch') {
var list = one.caseList;
if (list instanceof Array) {
for (var j = 0; j < list.length; j++) {
if (this.checkAsync(list[j].action)) return true;
}
}
}
if (one.async && one.type != 'animate') hasAsync = true;
if (one.type == 'waitAsync') hasAsync = false;
}
return hasAsync;
}
var previewBlock = function (b) {
var types = [
"previewUI_s", "clearMap_s", "clearMap_1_s", "setAttribute_s", "fillText_s",
"fillBoldText_s", "fillRect_s", "strokeRect_s", "drawLine_s",
"drawArrow_s", "fillPolygon_s", "strokePolygon_s", "fillCircle_s", "strokeCircle_s",
"drawImage_s", "drawImage_1_s", "drawIcon_s", "drawBackground_s", "drawSelector_s", "drawSelector_1_s",
"waitContext_2"
];
if (b && types.indexOf(b.type)>=0) {
try {
var code = "[" + Blockly.JavaScript.blockToCode(b).replace(/\\(i|c|d|e)/g, '\\\\$1') + "]";
eval("var obj="+code);
if (obj.length > 0 && b.type == 'waitContext_2') {
var dt = obj[0];
editor.uievent.previewUI([{"type": "fillRect", "x": dt.px[0], "y": dt.py[0],
"width": "(" + dt.px[1] + ")-(" + dt.px[0] + ")", "height": "(" + dt.py[1] + ")-(" + dt.py[0] + ")",
"style": "rgba(255,0,0,0.5)"}])
}
else if (obj.length > 0 && b.type.startsWith(obj[0].type)) {
if (b.type == 'previewUI_s')
editor.uievent.previewUI(obj[0].action);
else editor.uievent.previewUI([obj[0]]);
}
} catch (e) {main.log(e);}
return true;
}
return false;
}
editor_blockly.doubleClickBlock = function (blockId) {
var b = editor_blockly.workspace.getBlockById(blockId);
//console.log(b);
if (previewBlock(b)) return;
if (b && b.type in selectPointBlocks) { // selectPoint
this.selectPoint();
return;
}
var textStringDict = {
'text_0_s': 'EvalString_0',
'text_1_s': 'EvalString_2',
@ -597,6 +738,7 @@ function omitedcheckUpdateFunction(event) {
'function_s': 'RawEvalString_0',
'shopsub': 'EvalString_3',
'confirm_s': 'EvalString_0',
'drawTextContent_s': 'EvalString_0',
}
var f = b ? textStringDict[b.type] : null;
if (f) {
@ -615,7 +757,7 @@ function omitedcheckUpdateFunction(event) {
'comment_s',
'show_s',
'hide_s',
'setValue_s',
'addValue_s',
'if_s',
'battle_s',
'openDoor_s',
@ -644,40 +786,26 @@ function omitedcheckUpdateFunction(event) {
// Index from 1 - 9
editor_blockly.openToolbox = function(index) {
// var element = document.getElementById(':'+index);
// if (element == null || element.getAttribute("aria-selected")=="true") return;
// element.click();
editor_blockly.workspace.toolbox_.tree_.setSelectedItem(editor_blockly.workspace.toolbox_.tree_.children_[index-1]);
if (index < 0) index += editor_blockly.workspace.toolbox_.tree_.children_.length;
editor_blockly.workspace.toolbox_.tree_.setSelectedItem(editor_blockly.workspace.toolbox_.tree_.children_[index]);
}
editor_blockly.reopenToolbox = function(index) {
// var element = document.getElementById(':'+index);
// if (element == null) return;
// if (element.getAttribute("aria-selected")=="true") element.click();
// element.click();
editor_blockly.workspace.toolbox_.tree_.setSelectedItem(editor_blockly.workspace.toolbox_.tree_.children_[index-1]);
editor_blockly.workspace.getFlyout_().show(editor_blockly.workspace.toolbox_.tree_.children_[index-1].blocks);
if (index < 0) index += editor_blockly.workspace.toolbox_.tree_.children_.length;
editor_blockly.workspace.toolbox_.tree_.setSelectedItem(editor_blockly.workspace.toolbox_.tree_.children_[index]);
editor_blockly.workspace.getFlyout_().show(editor_blockly.workspace.toolbox_.tree_.children_[index].blocks);
}
editor_blockly.closeToolbox = function() {
/*
for (var i=1; i<=10; i++) {
var element = document.getElementById(':'+i);
if (element && element.getAttribute("aria-selected")=="true") {
element.click();
return;
}
}
*/
editor_blockly.workspace.toolbox_.clearSelection();
}
var searchInput = document.getElementById("searchBlock");
searchInput.onfocus = function () {
editor_blockly.reopenToolbox(10);
editor_blockly.reopenToolbox(-1);
}
searchInput.oninput = function () {
editor_blockly.reopenToolbox(10);
editor_blockly.reopenToolbox(-1);
}
editor_blockly.searchBlock = function (value) {
@ -702,6 +830,342 @@ function omitedcheckUpdateFunction(event) {
return results.length == 0 ? editor_blockly.lastUsedType : results;
}
// ------ select point ------
// id: [x, y, floorId, forceFloor]
var selectPointBlocks = {
"changeFloor_m": ["Number_0", "Number_1", "IdString_0", true],
"jumpHero_s": ["PosString_0", "PosString_1"],
"changeFloor_s": ["PosString_0", "PosString_1", "IdString_0", true],
"changePos_0_s": ["PosString_0", "PosString_1"],
"battle_1_s": ["PosString_0", "PosString_1"],
"openDoor_s": ["PosString_0", "PosString_1", "IdString_0"],
"closeDoor_s": ["PosString_0", "PosString_1"],
"show_s": ["EvalString_0", "EvalString_1", "IdString_0"],
"hide_s": ["EvalString_0", "EvalString_1", "IdString_0"],
"setBlock_s": ["EvalString_1", "EvalString_2", "IdString_0"],
"move_s": ["PosString_0", "PosString_1"],
"jump_s": ["PosString_2", "PosString_3"], // 跳跃暂时只考虑终点
"showBgFgMap_s": ["EvalString_0", "EvalString_1", "IdString_0"],
"hideBgFgMap_s": ["EvalString_0", "EvalString_1", "IdString_0"],
"setBgFgBlock_s": ["EvalString_1", "EvalString_2", "IdString_0"],
"showFloorImg_s": ["EvalString_0", "EvalString_1", "IdString_0"],
"hideFloorImg_s": ["EvalString_0", "EvalString_1", "IdString_0"],
"trigger_s": ["PosString_0", "PosString_1"],
"insert_2_s": ["PosString_0", "PosString_1", "IdString_0"],
"animate_s": ["EvalString_0", "EvalString_0"],
"setViewport_s": ["PosString_0", "PosString_1"]
}
editor_blockly.selectPoint = function () {
var block = Blockly.selected, arr = null;
var floorId = editor.currentFloorId, pos = editor.pos, x = pos.x, y = pos.y;
if (block != null && block.type in selectPointBlocks) {
arr = selectPointBlocks[block.type];
var xv = parseInt(block.getFieldValue(arr[0])), yv = parseInt(block.getFieldValue(arr[1]));
if (block.type == 'animate_s') {
var v = block.getFieldValue(arr[0]).split(",");
xv = parseInt(v[0]); yv = parseInt(v[1]);
}
if (!isNaN(xv)) x = xv;
if (!isNaN(yv)) y = yv;
if (arr[2] != null) floorId = block.getFieldValue(arr[2]) || floorId;
}
editor.uievent.selectPoint(floorId, x, y, arr && arr[2] == null, function (fv, xv, yv) {
if (!arr) return;
if (arr[2] != null) {
if (fv != editor.currentFloorId) block.setFieldValue(fv, arr[2]);
else block.setFieldValue(arr[3] ? fv : "", arr[2]);
}
if (block.type == 'animate_s') {
block.setFieldValue(xv+","+yv, arr[0]);
}
else {
block.setFieldValue(xv+"", arr[0]);
block.setFieldValue(yv+"", arr[1]);
}
if (block.type == 'changeFloor_m') {
block.setFieldValue("floorId", "Floor_List_0");
block.setFieldValue("loc", "Stair_List_0");
}
});
}
editor_blockly.getAutoCompletions = function (content) {
// --- content为当前框中输入内容将返回一个列表为后续所有可补全内容
// 检查 status:xxxitem:xxx和flag:xxx
var index = Math.max(content.lastIndexOf(":"), content.lastIndexOf(""));
if (index >= 0) {
var ch = content.charAt(index);
var before = content.substring(0, index), token = content.substring(index+1);
if (/^[a-zA-Z0-9_\u4E00-\u9FCC]*$/.test(token)) {
if (before.endsWith("状态") || (ch == ':' && before.endsWith("status"))) {
var list = Object.keys(core.status.hero);
if (before.endsWith("状态") && MotaActionFunctions) {
list = MotaActionFunctions.pattern.replaceStatusList.map(function (v) {
return v[1];
}).concat(list);
}
return list.filter(function (one) {
return one != token && one.startsWith(token);
}).sort();
}
else if (before.endsWith("物品") || (ch == ':' && before.endsWith("item"))) {
var list = Object.keys(core.material.items);
if (before.endsWith("物品") && MotaActionFunctions) {
list = MotaActionFunctions.pattern.replaceItemList.map(function (v) {
return v[1];
}).concat(list);
}
return list.filter(function (one) {
return one != token && one.startsWith(token);
}).sort();
}
else if (before.endsWith("变量") || (ch == ':' && before.endsWith("flag"))) {
return Object.keys(editor.used_flags || {}).filter(function (one) {
return one != token && one.startsWith(token);
}).sort();
} else if (before.endsWith("怪物") || (ch == ':' && before.endsWith("enemy"))) {
return Object.keys(core.material.enemys).filter(function (one) {
return one != token && one.startsWith(token);
})
} else {
var index2 = Math.max(content.lastIndexOf(":", index-1), content.lastIndexOf("", index-1));
var ch2 = content.charAt(index2);
if (index2 >= 0) {
before = content.substring(0, index2);
if (before.endsWith("怪物") || (ch == ':' && ch2 == ':' && before.endsWith("enemy"))) {
var list = ["name", "hp", "atk", "def", "money", "experience", "point", "special"];
if (before.endsWith("怪物") && MotaActionFunctions) {
list = MotaActionFunctions.pattern.replaceEnemyList.map(function (v) {
return v[1];
}).concat(list);
}
return list.filter(function (one) {
return one != token && one.startsWith(token);
})
}
}
}
}
}
// 提供 core.xxx 的补全
index = content.lastIndexOf("core.");
if (index >= 0) {
var s = content.substring(index + 5);
if (/^[\w.]*$/.test(s)) {
var tokens = s.split(".");
var now = core, prefix = tokens[tokens.length - 1];
for (var i = 0; i < tokens.length - 1; ++i) {
now = now[tokens[i]];
if (now == null) break;
}
if (now != null) {
var candidates = [];
for (var i in now) {
candidates.push(i);
}
return candidates.filter(function (one) {
return one != prefix && one.startsWith(prefix);
}).sort();
}
}
}
// 提供 flags.xxx 补全
index = content.lastIndexOf("flags.");
if (index >= 0) {
var token = content.substring(index+6);
return Object.keys(editor.used_flags || {}).filter(function (one) {
return one != token && one.startsWith(token)
&& /^[a-zA-Z_]\w*$/.test(one);
}).sort();
}
return [];
}
editor_blockly.completeItems = [];
return editor_blockly;
}
//editor_blockly=editor_blockly();
// --- modify Blockly
Blockly.FieldColour.prototype.createWidget_ = function() {
Blockly.WidgetDiv.hide();
// console.log('here')
var self=this;
var pb=self.sourceBlock_
var args = MotaActionBlocks[pb.type].args
var targetf=args[args.indexOf(self.name)-1]
var getValue=function(){
// return self.getValue() // css颜色
var f = pb.getFieldValue(targetf);
if (/^(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d),(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(,0(\.\d+)?|,1)?$/.test(f)) {
return f;
}
return "";
// 也可以用 pb.getFieldValue(targetf) 获得颜色块左边的域的内容
}
var setValue=function(newValue){ // css颜色
self.setValue(newValue)
var c=new Colors();
c.setColor(newValue)
var rgbatext = [c.colors.webSmart.r,c.colors.webSmart.g,c.colors.webSmart.b,c.colors.alpha].join(",");
pb.setFieldValue(rgbatext, targetf) // 放在颜色块左边的域中
}
setTimeout(function () {
document.getElementById("colorPicker").value = getValue();
window.jsColorPicker.confirm = setValue;
// 设置位置
triggerColorPicker(Blockly.WidgetDiv.DIV.style.left, Blockly.WidgetDiv.DIV.style.top);
});
return document.createElement('table');
};
Blockly.FieldTextInput.prototype.showInlineEditor_ = function(quietInput) {
Blockly.WidgetDiv.show(this, this.sourceBlock_.RTL, this.widgetDispose_());
var div = Blockly.WidgetDiv.DIV;
// Create the input.
var htmlInput =
goog.dom.createDom(goog.dom.TagName.INPUT, 'blocklyHtmlInput');
htmlInput.setAttribute('spellcheck', this.spellcheck_);
var fontSize =
(Blockly.FieldTextInput.FONTSIZE * this.workspace_.scale) + 'pt';
div.style.fontSize = fontSize;
htmlInput.style.fontSize = fontSize;
Blockly.FieldTextInput.htmlInput_ = htmlInput;
div.appendChild(htmlInput);
htmlInput.value = htmlInput.defaultValue = this.text_;
htmlInput.oldValue_ = null;
// console.log('here')
var self=this;
var pb=self.sourceBlock_
var args = MotaActionBlocks[pb.type].args
var targetf=args[args.indexOf(self.name)+1]
// ------ colour
if(targetf && targetf.slice(0,7)==='Colour_'){
var inputDom = htmlInput;
// var getValue=function(){ // 获得自己的字符串
// return pb.getFieldValue(self.name);
// }
var setValue = function(newValue){ // 设置右边颜色块的css颜色
pb.setFieldValue(newValue, targetf)
}
// 给inputDom绑事件
inputDom.oninput=function(){
var value=inputDom.value
if(/[0-9 ]+,[0-9 ]+,[0-9 ]+(,[0-9. ]+)?/.test(value)){
setValue('rgba('+value+')')
}
}
}
else {
htmlInput.onkeydown = function (e) {
if (e.keyCode == 13 && awesomplete.opened && awesomplete.selected) {
e.stopPropagation();
e.stopImmediatePropagation();
e.preventDefault();
awesomplete.select();
return false;
}
}
// --- awesomplete
var awesomplete = new Awesomplete(htmlInput, {
minChars: pb.type == "idString_3_e" ? 1 : 2,
maxItems: 12,
autoFirst: true,
replace: function (text) {
text = text.toString();
var value = this.input.value, index = this.input.selectionEnd;
if (index == null) index = value.length;
if (index < awesomplete.prefix.length) index = awesomplete.prefix.length;
var str = value.substring(0, index - awesomplete.prefix.length) + text + value.substring(index);
this.input.value = str;
pb.setFieldValue(str, self.name);
index += text.length - awesomplete.prefix.length;
this.input.setSelectionRange(index, index);
editor_blockly.completeItems = editor_blockly.completeItems.filter(function (x) {
return x != text;
});
editor_blockly.completeItems.unshift(text);
},
filter: function () {return true;},
item: function (text, input) {
var li = document.createElement("li");
li.setAttribute("role", "option");
li.setAttribute("aria-selected", "false");
input = awesomplete.prefix.trim();
if (input != "") text = text.replace(new RegExp("^"+input, "i"), "<mark>$&</mark>");
li.innerHTML = text;
return li;
},
sort: function (a, b) {
a = a.toString(); b = b.toString();
var ia = editor_blockly.completeItems.indexOf(a), ib = editor_blockly.completeItems.indexOf(b);
if (ia < 0) ia = editor_blockly.completeItems.length;
if (ib < 0) ib = editor_blockly.completeItems.length;
if (ia != ib) return ia - ib;
if (a.length != b.length) return a.length - b.length;
return a < b ? -1 : 1;
}
});
htmlInput.oninput = function () {
var value = htmlInput.value, index = htmlInput.selectionEnd;
if (index == null) index = value.length;
value = value.substring(0, index);
// cal prefix
awesomplete.prefix = "";
for (var i = index - 1; i>=0; i--) {
var c = value.charAt(i);
if (!/^[a-zA-Z0-9_\u4E00-\u9FCC]$/.test(c)) {
awesomplete.prefix = value.substring(i+1);
break;
}
}
var list = editor_blockly.getAutoCompletions(value);
if (pb.type == "idString_3_e") {
list = list.concat(Object.keys(core.material.enemys).filter(function (one) {
return one != value && one.startsWith(value);
}));
list.sort();
}
awesomplete.list = list;
awesomplete.ul.style.marginLeft = getCaretCoordinates(htmlInput, htmlInput.selectionStart).left -
htmlInput.scrollLeft - 20 + "px";
awesomplete.evaluate();
}
awesomplete.container.style.width = "100%";
window.awesomplete = awesomplete;
}
if (!quietInput) {
htmlInput.focus();
htmlInput.select();
}
this.validate_();
this.resizeEditor_();
this.bindEvents_(htmlInput);
};

34
_server/editor_config.js Normal file
View File

@ -0,0 +1,34 @@
function editor_config() {
this.address = "_server/config.json";
}
editor_config.prototype.load = function(callback) {
var _this = this;
fs.readFile(this.address, "utf-8", function(e, d) {
if (e) {
console.warn("无法读取配置文件, 已重新生成");
_this.config = {};
_this.save(callback);
} else {
_this.config = JSON.parse(d);
if (callback) 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) {
fs.writeFile(this.address, JSON.stringify(this.config) ,'utf-8', function(e) {
if (e) alert("写入配置文件失败");
if (callback instanceof Function) callback();
})
}

809
_server/editor_datapanel.js Normal file
View File

@ -0,0 +1,809 @@
editor_datapanel_wrapper = function (editor) {
// 此文件内的内容仅做了分类, 未仔细整理函数
///////////////////////////////////////////////////////////////////////
//////////////////// 地图编辑 //////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
editor.uifunctions.newMap_func = function () {
var newMap = document.getElementById('newMap');
var newFileName = document.getElementById('newFileName');
newMap.onclick = function () {
if (!newFileName.value) return;
if (core.floorIds.indexOf(newFileName.value) >= 0) {
printe("该楼层已存在!");
return;
}
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(newFileName.value)) {
printe("楼层名不合法!请使用字母、数字、下划线,且不能以数字开头!");
return;
}
var width = parseInt(document.getElementById('newMapWidth').value);
var height = parseInt(document.getElementById('newMapHeight').value);
if (!core.isset(width) || !core.isset(height) || width < core.__SIZE__ || height < core.__SIZE__ || width * height > 1000) {
printe("新建地图的宽高都不得小于" + core.__SIZE__ + "且宽高之积不能超过1000");
return;
}
editor_mode.onmode('');
editor.file.saveNewFile(newFileName.value, function (err) {
if (err) {
printe(err);
throw (err)
}
core.floorIds.push(newFileName.value);
editor.file.editTower([['change', "['main']['floorIds']", core.floorIds]], function (objs_) {//console.log(objs_);
if (objs_.slice(-1)[0] != null) {
printe(objs_.slice(-1)[0]);
throw (objs_.slice(-1)[0])
}
; printe('新建成功,请F5刷新编辑器生效');
});
});
}
}
editor.uifunctions.createNewMaps_func = function () {
var newMaps = document.getElementById('newMaps');
var newFloors = document.getElementById('newFloors');
newMaps.onclick = function () {
if (newFloors.style.display == 'none') newFloors.style.display = 'block';
else newFloors.style.display = 'none';
}
var createNewMaps = document.getElementById('createNewMaps');
createNewMaps.onclick = function () {
var floorIds = document.getElementById('newFloorIds').value;
if (!floorIds) return;
var from = parseInt(document.getElementById('newMapsFrom').value),
to = parseInt(document.getElementById('newMapsTo').value);
if (!core.isset(from) || !core.isset(to) || from > to || from < 0 || to < 0) {
printe("请输入有效的起始和终止楼层");
return;
}
if (to - from >= 100) {
printe("一次最多创建99个楼层");
return;
}
var floorIdList = [];
for (var i = from; i <= to; i++) {
var floorId = floorIds.replace(/\${(.*?)}/g, function (word, value) {
return eval(value);
});
if (core.floorIds.indexOf(floorId) >= 0) {
printe("要创建的楼层 " + floorId + " 已存在!");
return;
}
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(floorId)) {
printe("楼层名 " + floorId + " 不合法!请使用字母、数字、下划线,且不能以数字开头!");
return;
}
if (floorIdList.indexOf(floorId) >= 0) {
printe("尝试重复创建楼层 " + floorId + " ");
return;
}
floorIdList.push(floorId);
}
var width = parseInt(document.getElementById('newMapsWidth').value);
var height = parseInt(document.getElementById('newMapsHeight').value);
if (!core.isset(width) || !core.isset(height) || width < core.__SIZE__ || height < core.__SIZE__ || width * height > 1000) {
printe("新建地图的宽高都不得小于" + core.__SIZE__ + "且宽高之积不能超过1000");
return;
}
editor_mode.onmode('');
editor.file.saveNewFiles(floorIdList, from, to, function (err) {
if (err) {
printe(err);
throw (err)
}
core.floorIds = core.floorIds.concat(floorIdList);
editor.file.editTower([['change', "['main']['floorIds']", core.floorIds]], function (objs_) {//console.log(objs_);
if (objs_.slice(-1)[0] != null) {
printe(objs_.slice(-1)[0]);
throw (objs_.slice(-1)[0])
}
; printe('批量创建 ' + floorIdList[0] + '~' + floorIdList[floorIdList.length - 1] + ' 成功,请F5刷新编辑器生效');
});
});
}
}
///////////////////////////////////////////////////////////////////////
//////////////////// 地图选点 //////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// 添加自动事件页,无需双击
editor.uifunctions.addAutoEvent = function () {
if (editor_mode.mode != 'loc') return false;
var newid = '2';
var ae = editor.currentFloorData.autoEvent[editor_mode.pos.x + ',' + editor_mode.pos.y];
if (ae != null) {
var testid;
for (testid = 2; Object.hasOwnProperty.call(ae, testid); testid++);
newid = testid + '';
}
editor_mode.addAction(['add', "['autoEvent']['" + newid + "']", null]);
editor_mode.onmode('save');
}
///////////////////////////////////////////////////////////////////////
//////////////////// 图块属性 //////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
editor.uifunctions.newIdIdnum_func = function () {
var newIdIdnum = document.getElementById('newIdIdnum');
newIdIdnum.children[2].onclick = function () {
if (newIdIdnum.children[0].value && newIdIdnum.children[1].value) {
var id = newIdIdnum.children[0].value;
var idnum = parseInt(newIdIdnum.children[1].value);
if (!core.isset(idnum)) {
printe('不合法的idnum');
return;
}
if (!/^[0-9a-zA-Z_]+$/.test(id)) {
printe('不合法的id请使用字母、数字或下划线')
return;
}
editor.file.changeIdAndIdnum(id, idnum, editor_mode.info, function (err) {
if (err) {
printe(err);
throw (err)
}
printe('添加id和idnum成功,请F5刷新编辑器');
});
} else {
printe('请输入id和idnum');
}
}
newIdIdnum.children[4].onclick = function () {
editor.file.autoRegister(editor_mode.info, function (err) {
if (err) {
printe(err);
throw (err)
}
printe('该列所有剩余项全部自动注册成功,请F5刷新编辑器');
})
}
}
editor.uifunctions.changeId_func = function () {
var changeId = document.getElementById('changeId');
changeId.children[1].onclick = function () {
var id = changeId.children[0].value;
if (id) {
if (!/^[0-9a-zA-Z_]+$/.test(id)) {
printe('不合法的id请使用字母、数字或下划线')
return;
}
editor.file.changeIdAndIdnum(id, null, editor_mode.info, function (err) {
if (err) {
printe(err);
throw (err);
}
printe('修改id成功,请F5刷新编辑器');
});
} else {
printe('请输入要修改到的ID');
}
}
}
editor.uifunctions.copyPasteEnemyItem_func = function () {
var copyEnemyItem = document.getElementById('copyEnemyItem');
var pasteEnemyItem = document.getElementById('pasteEnemyItem');
copyEnemyItem.onclick = function () {
var cls = (editor_mode.info || {}).images;
if (editor_mode.mode != 'enemyitem' || (cls != 'enemys' && cls != 'enemy48' && cls != 'items')) return;
editor.uivalues.copyEnemyItem.type = cls;
var id = editor_mode.info.id;
if (cls == 'enemys' || cls == 'enemy48') {
editor.uivalues.copyEnemyItem.data = core.clone(enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80[id]);
printf("怪物属性复制成功");
} else {
editor.uivalues.copyEnemyItem.data = {};
for (var x in items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a) {
if (items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a[x][id] != null) {
editor.uivalues.copyEnemyItem.data[x] = core.clone(items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a[x][id]);
}
}
printf("道具属性复制成功");
}
}
pasteEnemyItem.onclick = function () {
var cls = (editor_mode.info || {}).images;
if (editor_mode.mode != 'enemyitem' || !cls || cls != editor.uivalues.copyEnemyItem.type) return;
var id = editor_mode.info.id;
if (cls == 'enemys' || cls == 'enemy48') {
if (confirm("你确定要覆盖此怪物的全部属性么?这是个不可逆操作!")) {
enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80[id] = core.clone(editor.uivalues.copyEnemyItem.data);
editor.file.saveSetting('enemys', [], function (err) {
if (err) printe(err);
else printf("怪物属性粘贴成功\n请再重新选中该怪物方可查看更新后的表格。");
})
}
} else {
if (confirm("你确定要覆盖此道具的全部属性么?这是个不可逆操作!")) {
for (var x in editor.uivalues.copyEnemyItem.data) {
items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a[x][id] = core.clone(editor.uivalues.copyEnemyItem.data[x]);
}
editor.file.saveSetting('items', [], function (err) {
if (err) printe(err);
else printf("道具属性粘贴成功\n请再重新选中该道具方可查看更新后的表格。");
})
}
}
}
}
///////////////////////////////////////////////////////////////////////
//////////////////// 楼层属性 //////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
editor.uifunctions.changeFloorId_func = function () {
editor.dom.changeFloorId.children[1].onclick = function () {
var floorId = editor.dom.changeFloorId.children[0].value;
if (floorId) {
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(floorId)) {
printe("楼层名 " + floorId + " 不合法!请使用字母、数字、下划线,且不能以数字开头!");
return;
}
if (main.floorIds.indexOf(floorId) >= 0) {
printe("楼层名 " + floorId + " 已存在!");
return;
}
var currentFloorId = editor.currentFloorId;
editor.currentFloorId = floorId;
editor.currentFloorData.floorId = floorId;
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw (err);
}
core.floorIds[core.floorIds.indexOf(currentFloorId)] = floorId;
editor.file.editTower([['change', "['main']['floorIds']", core.floorIds]], function (objs_) {//console.log(objs_);
if (objs_.slice(-1)[0] != null) {
printe(objs_.slice(-1)[0]);
throw (objs_.slice(-1)[0])
}
alert("修改floorId成功需要刷新编辑器生效。\n请注意原始的楼层文件没有删除请根据需要手动删除。");
window.location.reload();
});
});
} else {
printe('请输入要修改到的floorId');
}
}
}
///////////////////////////////////////////////////////////////////////
//////////////////// 全塔属性 //////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//////////////////// 脚本编辑 //////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//////////////////// 追加素材 //////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
editor.uifunctions.fixCtx_func = function () {
[editor.dom.sourceCtx, editor.dom.spriteCtx].forEach(function (ctx) {
ctx.mozImageSmoothingEnabled = false;
ctx.webkitImageSmoothingEnabled = false;
ctx.msImageSmoothingEnabled = false;
ctx.imageSmoothingEnabled = false;
})
}
editor.uifunctions.selectAppend_func = function () {
var selectAppend_str = [];
["terrains", "animates", "enemys", "enemy48", "items", "npcs", "npc48", "autotile"].forEach(function (image) {
selectAppend_str.push(["<option value='", image, "'>", image, '</option>\n'].join(''));
});
editor.dom.selectAppend.innerHTML = selectAppend_str.join('');
editor.dom.selectAppend.onchange = function () {
var value = editor.dom.selectAppend.value;
if (value == 'autotile') {
editor_mode.appendPic.imageName = 'autotile';
for (var jj = 0; jj < 4; jj++) editor.dom.appendPicSelection.children[jj].style = 'display:none';
if (editor_mode.appendPic.img) {
editor.dom.sprite.style.width = (editor.dom.sprite.width = editor_mode.appendPic.img.width) / editor.uivalues.ratio + 'px';
editor.dom.sprite.style.height = (editor.dom.sprite.height = editor_mode.appendPic.img.height) / editor.uivalues.ratio + 'px';
editor.dom.spriteCtx.clearRect(0, 0, editor.dom.sprite.width, editor.dom.sprite.height);
editor.dom.spriteCtx.drawImage(editor_mode.appendPic.img, 0, 0);
}
return;
}
var ysize = editor.dom.selectAppend.value.endsWith('48') ? 48 : 32;
editor_mode.appendPic.imageName = value;
var img = core.material.images[value];
editor_mode.appendPic.toImg = img;
var num = ~~img.width / 32;
editor_mode.appendPic.num = num;
editor_mode.appendPic.index = 0;
var selectStr = '';
for (var ii = 0; ii < num; ii++) {
editor.dom.appendPicSelection.children[ii].style = 'left:0;top:0;height:' + (ysize - 6) + 'px';
selectStr += '{"x":0,"y":0},'
}
editor_mode.appendPic.selectPos = eval('[' + selectStr + ']');
for (var jj = num; jj < 4; jj++) {
editor.dom.appendPicSelection.children[jj].style = 'display:none';
}
editor.dom.sprite.style.width = (editor.dom.sprite.width = img.width) / editor.uivalues.ratio + 'px';
editor.dom.sprite.style.height = (editor.dom.sprite.height = img.height + ysize) / editor.uivalues.ratio + 'px';
editor.dom.spriteCtx.drawImage(img, 0, 0);
}
editor.dom.selectAppend.onchange();
}
editor.uifunctions.selectFileBtn_func = function () {
var autoAdjust = function (image, callback) {
var changed = false;
// Step 1: 检测白底
var tempCanvas = document.createElement('canvas').getContext('2d');
tempCanvas.canvas.width = image.width;
tempCanvas.canvas.height = image.height;
tempCanvas.mozImageSmoothingEnabled = false;
tempCanvas.webkitImageSmoothingEnabled = false;
tempCanvas.msImageSmoothingEnabled = false;
tempCanvas.imageSmoothingEnabled = false;
tempCanvas.drawImage(image, 0, 0);
var imgData = tempCanvas.getImageData(0, 0, image.width, image.height);
var trans = 0, white = 0, black = 0;
for (var i = 0; i < image.width; i++) {
for (var j = 0; j < image.height; j++) {
var pixel = editor.util.getPixel(imgData, i, j);
if (pixel[3] == 0) trans++;
if (pixel[0] == 255 && pixel[1] == 255 && pixel[2] == 255 && pixel[3] == 255) white++;
// if (pixel[0]==0 && pixel[1]==0 && pixel[2]==0 && pixel[3]==255) black++;
}
}
if (white > black && white > trans * 10 && confirm("看起来这张图片是以纯白为底色,是否自动调整为透明底色?")) {
for (var i = 0; i < image.width; i++) {
for (var j = 0; j < image.height; j++) {
var pixel = editor.util.getPixel(imgData, i, j);
if (pixel[0] == 255 && pixel[1] == 255 && pixel[2] == 255 && pixel[3] == 255) {
editor.util.setPixel(imgData, i, j, [0, 0, 0, 0]);
}
}
}
tempCanvas.clearRect(0, 0, image.width, image.height);
tempCanvas.putImageData(imgData, 0, 0);
changed = true;
}
/*
if (black>white && black>trans*10 && confirm("看起来这张图片是以纯黑为底色,是否自动调整为透明底色?")) {
for (var i=0;i<image.width;i++) {
for (var j=0;j<image.height;j++) {
var pixel = editor.util.getPixel(imgData, i, j);
if (pixel[0]==0 && pixel[1]==0 && pixel[2]==0 && pixel[3]==255) {
editor.util.setPixel(imgData, i, j, [0,0,0,0]);
}
}
}
tempCanvas.clearRect(0, 0, image.width, image.height);
tempCanvas.putImageData(imgData, 0, 0);
changed = true;
}
*/
// Step 2: 检测长宽比
var ysize = editor.dom.selectAppend.value.endsWith('48') ? 48 : 32;
if ((image.width % 32 != 0 || image.height % ysize != 0) && (image.width <= 128 && image.height <= ysize * 4)
&& confirm("目标长宽不符合条件,是否自动进行调整?")) {
var ncanvas = document.createElement('canvas').getContext('2d');
ncanvas.canvas.width = 128;
ncanvas.canvas.height = 4 * ysize;
ncanvas.mozImageSmoothingEnabled = false;
ncanvas.webkitImageSmoothingEnabled = false;
ncanvas.msImageSmoothingEnabled = false;
ncanvas.imageSmoothingEnabled = false;
var w = image.width / 4, h = image.height / 4;
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
ncanvas.drawImage(tempCanvas.canvas, i * w, j * h, w, h, i * 32 + (32 - w) / 2, j * ysize + (ysize - h) / 2, w, h);
}
}
tempCanvas = ncanvas;
changed = true;
}
if (!changed) {
callback(image);
}
else {
var nimg = new Image();
nimg.onload = function () {
callback(nimg);
};
nimg.src = tempCanvas.canvas.toDataURL();
}
}
editor.dom.selectFileBtn.onclick = function () {
var loadImage = function (content, callback) {
var image = new Image();
try {
image.onload = function () {
callback(image);
}
image.src = content;
}
catch (e) {
printe(e);
}
}
core.readFile(function (content) {
loadImage(content, function (image) {
autoAdjust(image, function (image) {
editor_mode.appendPic.img = image;
editor_mode.appendPic.width = image.width;
editor_mode.appendPic.height = image.height;
if (editor.dom.selectAppend.value == 'autotile') {
for (var ii = 0; ii < 3; ii++) {
var newsprite = editor.dom.appendPicCanvas.children[ii];
newsprite.style.width = (newsprite.width = image.width) / editor.uivalues.ratio + 'px';
newsprite.style.height = (newsprite.height = image.height) / editor.uivalues.ratio + 'px';
}
editor.dom.spriteCtx.clearRect(0, 0, editor.dom.sprite.width, editor.dom.sprite.height);
editor.dom.spriteCtx.drawImage(image, 0, 0);
}
else {
var ysize = editor.dom.selectAppend.value.endsWith('48') ? 48 : 32;
for (var ii = 0; ii < 3; ii++) {
var newsprite = editor.dom.appendPicCanvas.children[ii];
newsprite.style.width = (newsprite.width = Math.floor(image.width / 32) * 32) / editor.uivalues.ratio + 'px';
newsprite.style.height = (newsprite.height = Math.floor(image.height / ysize) * ysize) / editor.uivalues.ratio + 'px';
}
}
//画灰白相间的格子
var bgc = editor.dom.bgCtx;
var colorA = ["#f8f8f8", "#cccccc"];
var colorIndex;
var sratio = 4;
for (var ii = 0; ii < image.width / 32 * sratio; ii++) {
colorIndex = 1 - ii % 2;
for (var jj = 0; jj < image.height / 32 * sratio; jj++) {
bgc.fillStyle = colorA[colorIndex];
colorIndex = 1 - colorIndex;
bgc.fillRect(ii * 32 / sratio, jj * 32 / sratio, 32 / sratio, 32 / sratio);
}
}
//把导入的图片画出
editor.dom.sourceCtx.drawImage(image, 0, 0);
editor_mode.appendPic.sourceImageData = editor.dom.sourceCtx.getImageData(0, 0, image.width, image.height);
//重置临时变量
editor.dom.selectAppend.onchange();
});
});
}, null, 'image/*', 'img');
return;
}
}
editor.uifunctions.changeColorInput_func = function () {
var changeColorInput = document.getElementById('changeColorInput')
changeColorInput.oninput = function () {
var delta = (~~changeColorInput.value) * 30;
var imgData = editor_mode.appendPic.sourceImageData;
var nimgData = new ImageData(imgData.width, imgData.height);
// ImageData .data 形如一维数组,依次排着每个点的 R(0~255) G(0~255) B(0~255) A(0~255)
var convert = function (rgba, delta) {
var rgbToHsl = editor.util.rgbToHsl
var hue2rgb = editor.util.hue2rgb
var hslToRgb = editor.util.hslToRgb
//
var hsl = rgbToHsl(rgba)
hsl[0] = (hsl[0] + delta) % 360
var nrgb = hslToRgb(hsl)
nrgb.push(rgba[3])
return nrgb
}
for (var x = 0; x < imgData.width; x++) {
for (var y = 0; y < imgData.height; y++) {
editor.util.setPixel(nimgData, x, y, convert(editor.util.getPixel(imgData, x, y), delta))
}
}
editor.dom.sourceCtx.clearRect(0, 0, imgData.width, imgData.height);
editor.dom.sourceCtx.putImageData(nimgData, 0, 0);
}
}
editor.uifunctions.picClick_func = function () {
var eToLoc = function (e) {
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop
var loc = {
'x': scrollLeft + e.clientX + editor.dom.appendPicCanvas.scrollLeft - editor.dom.left1.offsetLeft - editor.dom.appendPicCanvas.offsetLeft,
'y': scrollTop + e.clientY + editor.dom.appendPicCanvas.scrollTop - editor.dom.left1.offsetTop - editor.dom.appendPicCanvas.offsetTop,
'size': 32,
'ysize': editor.dom.selectAppend.value.endsWith('48') ? 48 : 32
};
return loc;
}//返回可用的组件内坐标
var locToPos = function (loc) {
var pos = { 'x': ~~(loc.x / loc.size), 'y': ~~(loc.y / loc.ysize), 'ysize': loc.ysize }
return pos;
}
editor.dom.picClick.onclick = function (e) {
var loc = eToLoc(e);
var pos = locToPos(loc);
//console.log(e,loc,pos);
var num = editor_mode.appendPic.num;
var ii = editor_mode.appendPic.index;
if (ii + 1 >= num) editor_mode.appendPic.index = ii + 1 - num;
else editor_mode.appendPic.index++;
editor_mode.appendPic.selectPos[ii] = pos;
editor.dom.appendPicSelection.children[ii].style = [
'left:', pos.x * 32, 'px;',
'top:', pos.y * pos.ysize, 'px;',
'height:', pos.ysize - 6, 'px;'
].join('');
}
}
editor.uifunctions.appendConfirm_func = function () {
var appendRegister = document.getElementById('appendRegister');
var appendConfirm = document.getElementById('appendConfirm');
appendConfirm.onclick = function () {
var confirmAutotile = function () {
var image = editor_mode.appendPic.img;
if (image.width % 96 != 0 || image.height != 128) {
printe("不合法的Autotile图片");
return;
}
var imgData = editor.dom.sourceCtx.getImageData(0, 0, image.width, image.height);
editor.dom.spriteCtx.putImageData(imgData, 0, 0);
var imgbase64 = editor.dom.sprite.toDataURL().split(',')[1];
// Step 1: List文件名
fs.readdir('./project/images', function (err, data) {
if (err) {
printe(err);
throw (err);
}
// Step 2: 选择Autotile文件名
var filename;
for (var i = 1; ; ++i) {
filename = 'autotile' + i;
if (data.indexOf(filename + ".png") == -1) break;
}
// Step 3: 写入文件
fs.writeFile('./project/images/' + filename + ".png", imgbase64, 'base64', function (err, data) {
if (err) {
printe(err);
throw (err);
}
// Step 4: 自动注册
editor.file.registerAutotile(filename, function (err) {
if (err) {
printe(err);
throw (err);
}
printe('自动元件' + filename + '注册成功,请F5刷新编辑器');
})
})
})
}
if (editor.dom.selectAppend.value == 'autotile') {
confirmAutotile();
return;
}
var ysize = editor.dom.selectAppend.value.endsWith('48') ? 48 : 32;
for (var ii = 0, v; v = editor_mode.appendPic.selectPos[ii]; ii++) {
// var imgData = editor.dom.sourceCtx.getImageData(v.x * 32, v.y * ysize, 32, ysize);
// editor.dom.spriteCtx.putImageData(imgData, ii * 32, editor.dom.sprite.height - ysize);
// editor.dom.spriteCtx.drawImage(editor_mode.appendPic.img, v.x * 32, v.y * ysize, 32, ysize, ii * 32, height, 32, ysize)
editor.dom.spriteCtx.drawImage(editor.dom.sourceCtx.canvas, v.x * 32, v.y * ysize, 32, ysize, 32 * ii, editor.dom.sprite.height - ysize, 32, ysize);
}
var dt = editor.dom.spriteCtx.getImageData(0, 0, editor.dom.sprite.width, editor.dom.sprite.height);
var imgbase64 = editor.dom.sprite.toDataURL('image/png');
var imgName = editor_mode.appendPic.imageName;
fs.writeFile('./project/images/' + imgName + '.png', imgbase64.split(',')[1], 'base64', function (err, data) {
if (err) {
printe(err);
throw (err)
}
var currHeight = editor.dom.sprite.height;
editor.dom.sprite.style.height = (editor.dom.sprite.height = (currHeight + ysize)) + "px";
editor.dom.spriteCtx.putImageData(dt, 0, 0);
core.material.images[imgName].src = imgbase64;
editor.widthsX[imgName][3] = currHeight;
if (appendRegister && appendRegister.checked) {
editor.file.autoRegister({images: imgName}, function (e) {
if (e) {
printe(e);
throw e;
}
printf('追加素材并自动注册成功!你可以继续追加其他素材,最后再刷新以使用。');
});
} else {
printf('追加素材成功!你可以继续追加其他素材,最后再刷新以使用。');
}
});
}
var quickAppendConfirm = document.getElementById('quickAppendConfirm');
quickAppendConfirm.onclick = function () {
var value = editor.dom.selectAppend.value;
if (value != 'enemys' && value != 'enemy48' && value != 'npcs' && value != 'npc48')
return printe("只有怪物或NPC才能快速导入");
var ysize = value.endsWith('48') ? 48 : 32;
if (editor.dom.sourceCtx.canvas.width != 128 || editor.dom.sourceCtx.canvas.height != 4 * ysize)
return printe("只有 4*4 的素材图片才可以快速导入!");
var dt = editor.dom.spriteCtx.getImageData(0, 0, editor.dom.sprite.width, editor.dom.sprite.height);
editor.dom.sprite.style.height = (editor.dom.sprite.height = (editor.dom.sprite.height + 3 * ysize)) + "px";
editor.dom.spriteCtx.putImageData(dt, 0, 0);
if (editor.dom.sprite.width == 64) { // 两帧
editor.dom.spriteCtx.drawImage(editor.dom.sourceCtx.canvas, 32, 0, 64, 4 * ysize, 0, editor.dom.sprite.height - 4 * ysize, 64, 4 * ysize);
} else { // 四帧
editor.dom.spriteCtx.drawImage(editor.dom.sourceCtx.canvas, 0, 0, 128, 4 * ysize, 0, editor.dom.sprite.height - 4 * ysize, 128, 4 * ysize);
}
dt = editor.dom.spriteCtx.getImageData(0, 0, editor.dom.sprite.width, editor.dom.sprite.height);
var imgbase64 = editor.dom.sprite.toDataURL('image/png');
var imgName = editor_mode.appendPic.imageName;
fs.writeFile('./project/images/' + imgName + '.png', imgbase64.split(',')[1], 'base64', function (err, data) {
if (err) {
printe(err);
throw (err)
}
var currHeight = editor.dom.sprite.height;
editor.dom.sprite.style.height = (editor.dom.sprite.height = (currHeight + ysize)) + "px";
editor.dom.spriteCtx.putImageData(dt, 0, 0);
core.material.images[imgName].src = imgbase64;
editor.widthsX[imgName][3] = currHeight;
if (appendRegister && appendRegister.checked) {
editor.file.autoRegister({images: imgName}, function (e) {
if (e) {
printe(e);
throw e;
}
printf('快速追加素材并自动注册成功!你可以继续追加其他素材,最后再刷新以使用。');
})
} else {
printf('快速追加素材成功!你可以继续追加其他素材,最后再刷新以使用。');
}
});
}
}
///////////////////////////////////////////////////////////////////////
//////////////////// 公共事件 //////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//////////////////// 插件编写 //////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,904 @@
editor_file = function (editor, callback) {
var editor_file = new editor_file_proto();
editor.file=editor_file;
editor.file.loadCommentjs(callback);
editor.file.saveFloorFile = function (callback) {
//callback(err:String)
checkCallback(callback);
/* if (!isset(editor.currentFloorId) || !isset(editor.currentFloorData)) {
callback('未选中文件或无数据');
} */
var filename = 'project/floors/' + editor.currentFloorId + '.js';
var datastr = ['main.floors.', editor.currentFloorId, '=\n'];
if (core.floorIds.indexOf(editor.currentFloorId) >= 0) {
for(var ii=0,name;name=['map','bgmap','fgmap'][ii];ii++){
var mapArray=editor[name].map(function (v) {
return v.map(function (v) {
return v.idnum || v || 0
})
});
editor.currentFloorData[name]=mapArray;
}
}
editor.file.saveFloor(editor.currentFloorData, callback)
}
///////////////////////////////////////////////////////////////////////////
editor.file.saveNewFile = function (saveFilename, callback) {
//saveAsFilename不含'/'不含'.js'
checkCallback(callback);
var currData=editor.currentFloorData;
var saveStatus = document.getElementById('newMapStatus').checked;
var title = saveStatus?currData.title:"新建楼层";
var name = saveStatus?currData.name:"0";
if (/^mt\d+$/i.test(saveFilename)) {
name = saveFilename.substring(2);
title = "主塔 "+name+" 层";
}
var width = parseInt(document.getElementById('newMapWidth').value);
var height = parseInt(document.getElementById('newMapHeight').value);
var row = [], map = [];
for (var i=0;i<width;i++) row.push(0);
for (var i=0;i<height;i++) map.push(row);
editor.currentFloorData = Object.assign(JSON.parse(JSON.stringify(editor.file.comment._data.floors_template)), {
floorId: saveFilename,
title: title,
name: name,
width: width,
height: height,
map: map,
},saveStatus?{
canFlyTo: currData.canFlyTo,
canUseQuickShop: currData.canUseQuickShop,
cannotViewMap: currData.cannotViewMap,
cannotMoveDirectly: currData.cannotMoveDirectly,
item_ratio: currData.item_ratio,
defaultGround: currData.defaultGround,
bgm: currData.bgm,
color: currData.color,
weather: currData.weather,
}:{});
Object.keys(editor.currentFloorData).forEach(function (t) {
if (editor.currentFloorData[t] == null)
delete editor.currentFloorData[t];
})
editor.currentFloorId = saveFilename;
editor.file.saveFloorFile(callback);
}
editor.file.saveNewFiles = function (floorIdList, from, to, callback) {
checkCallback(callback);
var currData=editor.currentFloorData;
var saveStatus = document.getElementById('newMapsStatus').checked;
var calValue = function (text, i) {
return text.replace(/\${(.*?)}/g, function (word, value) {
return eval(value);
});
}
var width = parseInt(document.getElementById('newMapsWidth').value);
var height = parseInt(document.getElementById('newMapsHeight').value);
var row = [], map = [];
for (var i=0;i<width;i++) row.push(0);
for (var i=0;i<height;i++) map.push(row);
var filenames = floorIdList.map(function (v) {return "project/floors/"+v+".js";});
var datas = [];
for (var i=from;i<=to;i++) {
var datastr = ['main.floors.', floorIdList[i-from], '=\n{'];
var data = Object.assign(JSON.parse(JSON.stringify(editor.file.comment._data.floors_template)), {
floorId: floorIdList[i-from],
title: calValue(document.getElementById('newFloorTitles').value, i),
name: calValue(document.getElementById('newFloorNames').value, i),
width: width,
height: height,
map: map,
},saveStatus?{
canFlyTo: currData.canFlyTo,
canUseQuickShop: currData.canUseQuickShop,
cannotViewMap: currData.cannotViewMap,
cannotMoveDirectly: currData.cannotMoveDirectly,
item_ratio: currData.item_ratio,
defaultGround: currData.defaultGround,
bgm: currData.bgm,
color: currData.color,
weather: currData.weather,
}:{});
Object.keys(data).forEach(function (t) {
if (data[t] == null)
delete data[t];
else {
if (t=='map') {
datastr = datastr.concat(['\n"', t, '": [\n', editor.file.formatMap(data[t]), '\n],']);
}
else {
datastr = datastr.concat(['\n"', t, '": ', JSON.stringify(data[t], null, 4), ',']);
}
}
});
datastr = datastr.concat(['\n}']);
datastr = datastr.join('');
datas.push(encode(datastr));
}
editor.file.alertWhenCompress();
fs.writeMultiFiles(filenames, datas, function (err, data) {
callback(err);
});
}
//callback(err:String)
////////////////////////////////////////////////////////////////////
editor.file.autoRegister = function (info, callback) {
var iconActions = [];
var mapActions = [];
var templateActions = [];
var image = info.images;
var bindFaceIds = false;
if (image=='autotile') {
callback('不能对自动元件进行自动注册!');
return;
}
if (image=='npc48' && confirm("你想绑定npc48的朝向么\n如果是则会连续四个一组的对npc48的faceIds进行自动绑定。")) {
bindFaceIds = true;
}
var c=image.toUpperCase().charAt(0);
// terrains id
var terrainsId = [];
Object.keys(core.material.icons.terrains).forEach(function (id) {
terrainsId[core.material.icons.terrains[id]]=id;
})
var allIds = [];
editor.ids.forEach(function (v) {
if (v.images==image) {
allIds[v.y]=v;
}
})
var per_height = image.endsWith('48')?48:32;
var faceIds = []; // down, left, right, up
var idnum=300;
for (var y=0; y<editor.widthsX[image][3]/per_height;y++) {
if (allIds[y] != null) {
faceIds.push(allIds[y]);
continue;
}
while (editor.core.maps.blocksInfo[idnum]) idnum++;
// get id num
var id = c+idnum;
if (image=='terrains' && terrainsId[y] != null) {
id=terrainsId[y];
}
else {
iconActions.push(["add", "['" + image + "']['" + id + "']", y])
}
mapActions.push(["add", "['" + idnum + "']", {'cls': image, 'id': id}]);
faceIds.push({idnum: idnum, id: id});
if (image=='items')
templateActions.push(["add", "['items']['" + id + "']", editor.file.comment._data.items_template]);
else if (image.indexOf('enemy')==0)
templateActions.push(["add", "['" + id + "']", editor.file.comment._data.enemys_template]);
idnum++;
}
if (bindFaceIds) {
for (var i = 0; i < faceIds.length - 3; i+=4) {
var down = faceIds[i], left = faceIds[i+1], right = faceIds[i+2], up = faceIds[i+3];
var obj = {down: down.id, left: left.id, right: right.id, up: up.id};
mapActions.push(["add", "['" + down.idnum + "']['faceIds']", obj]);
mapActions.push(["add", "['" + left.idnum + "']['faceIds']", obj]);
mapActions.push(["add", "['" + right.idnum + "']['faceIds']", obj]);
mapActions.push(["add", "['" + up.idnum + "']['faceIds']", obj]);
}
}
if (mapActions.length==0) {
callback("没有要注册的项!");
return;
}
var templist = [];
var tempcallback = function (err) {
templist.push(err);
if (templist.length == 3) {
if (templist[0] != null || templist[1] != null || templist[2] != null)
callback((templist[0] || '') + '\n' + (templist[1] || '') + '\n' + (templist[2] || ''));
//这里如果一个成功一个失败会出严重bug
else
callback(null);
}
}
if (iconActions.length>0)
saveSetting('icons', iconActions, tempcallback);
else tempcallback(null);
saveSetting('maps', mapActions, tempcallback);
if (image=='items')
saveSetting('items', templateActions, tempcallback);
else if (image.indexOf('enemy')==0)
saveSetting('enemys', templateActions, tempcallback);
else tempcallback(null);
}
editor.file.registerAutotile = function (filename, callback) {
var idnum = 140;
while (editor.core.maps.blocksInfo[idnum]) idnum++;
var iconActions = [];
var mapActions = [];
iconActions.push(["add", "['autotile']['" + filename + "']", 0]);
mapActions.push(["add", "['" + idnum + "']", {'cls': 'autotile', 'id': filename, 'noPass': true}]);
var templist = [];
var tempcallback = function (err) {
templist.push(err);
if (templist.length == 2) {
if (templist[0] != null || templist[1] != null)
callback((templist[0] || '') + '\n' + (templist[1] || ''));
//这里如果一个成功一个失败会出严重bug
else
callback(null);
}
}
saveSetting('icons', iconActions, tempcallback);
saveSetting('maps', mapActions, tempcallback);
}
editor.file.changeIdAndIdnum = function (id, idnum, info, callback) {
checkCallback(callback);
var changeOrNew=core.isset(editor_mode.info.id)?'change':'new'
if(changeOrNew=='new'){
//检查maps中是否有重复的idnum或id
for (var ii in editor.core.maps.blocksInfo) {
if (ii == idnum) {
callback('idnum重复了');
return;
}
if (editor.core.maps.blocksInfo[ii].id == id) {
callback('id重复了');
return;
}
}
var templist = [];
var tempcallback = function (err) {
templist.push(err);
if (templist.length == 2) {
if (templist[0] != null || templist[1] != null)
callback((templist[0] || '') + '\n' + (templist[1] || ''));
//这里如果一个成功一个失败会出严重bug
else
callback(null);
}
}
saveSetting('maps', [["add", "['" + idnum + "']", {'cls': info.images, 'id': id}]], tempcallback);
saveSetting('icons', [["add", "['" + info.images + "']['" + id + "']", info.y]], tempcallback);
if (info.images === 'items') {
saveSetting('items', [["add", "['items']['" + id + "']", editor.file.comment._data.items_template]], function (err) {
if (err) {
printe(err);
throw(err)
}
});
}
if (info.images === 'enemys' || info.images === 'enemy48') {
saveSetting('enemys', [["add", "['" + id + "']", editor.file.comment._data.enemys_template]], function (err) {
if (err) {
printe(err);
throw(err)
}
});
}
callback(null);
}else{
//检查maps中是否有重复的idnum或id
for (var ii in editor.core.maps.blocksInfo) {
if (editor.core.maps.blocksInfo[ii].id == id) {
callback('id重复了');
return;
}
}
idnum = info.idnum;
maps_90f36752_8815_4be8_b32b_d7fad1d0542e[idnum].id = id;
var arr=[icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1,items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a,{enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80:enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80}]
arr.forEach(function (obj) {
for(var jj in obj){
var ii=obj[jj]
if (ii.hasOwnProperty(info.id)){
ii[id]=ii[info.id];
delete(ii[info.id]);
}
}
});
editor.file.save_icons_maps_items_enemys(callback)
}
}
//callback(err:String)
editor.file.editItem = function (id, actionList, callback) {
/*actionList:[
["change","['items']['name']","红宝石的新名字"],
["add","['items']['新的和name同级的属性']",123],
["change","['itemEffectTip']","',攻击力+'+editor.core.values.redJewel"],
]
[]时只查询不修改
*/
checkCallback(callback);
if (isset(actionList) && actionList.length > 0) {
actionList.forEach(function (value) {
var tempindex = value[1].indexOf(']') + 1;
value[1] = [value[1].slice(0, tempindex), "['" + id + "']", value[1].slice(tempindex)].join('');
});
saveSetting('items', actionList, function (err) {
callback([err]);
});
} else {
callback([
(function () {
var locObj_ = {};
Object.keys(editor.file.comment._data.items._data).forEach(function (v) {
if (isset(editor.core.items[v][id]) && v !== 'items')
locObj_[v] = editor.core.items[v][id];
else
locObj_[v] = null;
});
locObj_['items'] = (function () {
var locObj = Object.assign({}, editor.core.items.items[id]);
Object.keys(editor.file.comment._data.items._data.items._data).forEach(function (v) {
if (!isset(editor.core.items.items[id][v]))
locObj[v] = null;
});
return locObj;
})();
return locObj_;
})(),
editor.file.comment._data.items,
null]);
}
//只有items.cls是items的才有itemEffect和itemEffectTip,keys和constants和tools只有items
}
//callback([obj,commentObj,err:String])
editor.file.editEnemy = function (id, actionList, callback) {
/*actionList:[
["change","['name']","初级巫师的新名字"],
["add","['新的和name同级的属性']",123],
["change","['bomb']",null],
]
[]时只查询不修改
*/
checkCallback(callback);
if (isset(actionList) && actionList.length > 0) {
actionList.forEach(function (value) {
value[1] = "['" + id + "']" + value[1];
});
saveSetting('enemys', actionList, function (err) {
callback([err]);
});
} else {
callback([
(function () {
var locObj = Object.assign({}, editor.core.enemys.enemys[id]);
Object.keys(editor.file.comment._data.enemys._data).forEach(function (v) {
if (!isset(editor.core.enemys.enemys[id][v]))
/* locObj[v]=editor.core.enemys.enemys[id][v];
else */
locObj[v] = null;
});
return locObj;
})(),
editor.file.comment._data.enemys,
null]);
}
}
//callback([obj,commentObj,err:String])
editor.file.editMapBlocksInfo = function (idnum, actionList, callback) {
/*actionList:[
["change","['events']",["\t[老人,magician]领域、夹击。\n请注意领域怪需要设置value为伤害数值可参见样板中初级巫师的写法。"]],
["change","['afterBattle']",null],
]
[]时只查询不修改
*/
checkCallback(callback);
if (isset(actionList) && actionList.length > 0) {
var tempmap=[];
for(var ii=0;ii<actionList.length;ii++){
var value=actionList[ii];
// 是tilesets 且未定义 且在这里是第一次定义
if(idnum>=editor.core.icons.tilesetStartOffset && !isset(editor.core.maps.blocksInfo[idnum]) && tempmap.indexOf(idnum)===-1){
actionList.splice(ii,0,["add","['" + idnum + "']",{"cls": "tileset", "id": "X"+idnum, "noPass": true}]);
tempmap.push(idnum);
ii++;
}
value[1] = "['" + idnum + "']" + value[1];
}
saveSetting('maps', actionList, function (err) {
callback([err]);
});
} else {
callback([
(function () {
var sourceobj=editor.core.maps.blocksInfo[idnum];
if(!isset(sourceobj) && idnum>=editor.core.icons.tilesetStartOffset)sourceobj={"cls": "tileset", "id": "X"+idnum, "noPass": true}
var locObj = Object.assign({}, sourceobj);
Object.keys(editor.file.comment._data.maps._data).forEach(function (v) {
if (!isset(sourceobj[v]))
locObj[v] = null;
});
locObj.idnum = idnum;
return locObj;
})(),
editor.file.comment._data.maps,
null]);
}
}
//callback([obj,commentObj,err:String])
////////////////////////////////////////////////////////////////////
editor.file.editLoc = function (x, y, actionList, callback) {
/*actionList:[
["change","['events']",["\t[老人,magician]领域、夹击。\n请注意领域怪需要设置value为伤害数值可参见样板中初级巫师的写法。"]],
["change","['afterBattle']",null],
]
[]时只查询不修改
*/
checkCallback(callback);
if (isset(actionList) && actionList.length > 0) {
actionList.forEach(function (value) {
if(/\['autoEvent'\]\['\d+'\]$/.test(value[1]))value[1]=value[1].replace(/\['\d+'\]$/,function(v){return "['" + x + "," + y + "']"+v})
else value[1] = value[1] + "['" + x + "," + y + "']";
});
saveSetting('floorloc', actionList, function (err) {
callback([err]);
});
} else {
callback([
(function () {
var locObj = {};
Object.keys(editor.file.comment._data.floors._data.loc._data).forEach(function (v) {
if (isset(editor.currentFloorData[v][x + ',' + y]))
locObj[v] = editor.currentFloorData[v][x + ',' + y];
else
locObj[v] = null;
});
return locObj;
})(),
editor.file.comment._data.floors._data.loc,
null]);
}
}
//callback([obj,commentObj,err:String])
////////////////////////////////////////////////////////////////////
editor.file.editFloor = function (actionList, callback) {
/*actionList:[
["change","['title']",'样板 3 层'],
["change","['color']",null],
]
[]时只查询不修改
*/
checkCallback(callback);
if (isset(actionList) && actionList.length > 0) {
saveSetting('floors', actionList, function (err) {
callback([err]);
});
} else {
callback([
(function () {
var locObj = Object.assign({}, editor.currentFloorData);
Object.keys(editor.file.comment._data.floors._data.floor._data).forEach(function (v) {
if (!isset(editor.currentFloorData[v]))
/* locObj[v]=editor.currentFloorData[v];
else */
locObj[v] = null;
});
Object.keys(editor.file.comment._data.floors._data.loc._data).forEach(function (v) {
delete(locObj[v]);
});
delete(locObj.map);
delete(locObj.bgmap);
delete(locObj.fgmap);
return locObj;
})(),
editor.file.comment._data.floors._data.floor,
null]);
}
}
//callback([obj,commentObj,err:String])
////////////////////////////////////////////////////////////////////
editor.file.editTower = function (actionList, callback) {
/*actionList:[
["change","['firstData']['version']",'Ver 1.0.1 (Beta)'],
["change","['values']['lavaDamage']",200],
]
[]时只查询不修改
*/
var data_obj = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d;
checkCallback(callback);
if (isset(actionList) && actionList.length > 0) {
saveSetting('data', actionList, function (err) {
callback([err]);
});
} else {
callback([
(function () {
//var locObj=Object.assign({'main':{}},editor.core.data);
var locObj = Object.assign({}, data_obj, {'main': {}});
Object.keys(editor.file.dataComment._data.main._data).forEach(function (v) {
if (isset(editor.main[v]))
locObj.main[v] = data_obj.main[v];
else
locObj.main[v] = null;
});
return locObj;
})(),
editor.file.dataComment,
null]);
}
}
//callback([obj,commentObj,err:String])
////////////////////////////////////////////////////////////////////
var fmap = {};
var fjson = JSON.stringify(functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a, function (k, v) {
if (v instanceof Function) {
var id_ = editor.util.guid();
fmap[id_] = v.toString();
return id_;
} else return v
}, 4);
var fobj = JSON.parse(fjson);
editor.file.functionsMap = fmap;
editor.file.functionsJSON = fjson;
var buildlocobj = function (locObj) {
for (var key in locObj) {
if (typeof(locObj[key]) !== typeof('')) buildlocobj(locObj[key]);
else locObj[key] = fmap[locObj[key]];
}
};
editor.file.editFunctions = function (actionList, callback) {
/*actionList:[
["change","['events']['afterChangeLight']","function(x,y){console.log(x,y)}"],
["change","['ui']['drawAbout']","function(){...}"],
]
[]时只查询不修改
*/
checkCallback(callback);
if (isset(actionList) && actionList.length > 0) {
saveSetting('functions', actionList, function (err) {
callback([err]);
});
} else {
callback([
(function () {
var locObj = JSON.parse(fjson);
buildlocobj(locObj);
return locObj;
})(),
editor.file.functionsComment,
null]);
}
}
//callback([obj,commentObj,err:String])
////////////////////////////////////////////////////////////////////
editor.file.editCommonEvent = function (actionList, callback) {
/*actionList:[
["change","['test']",['123']],
]
[]时只查询不修改
*/
var data_obj = events_c12a15a8_c380_4b28_8144_256cba95f760.commonEvent;
checkCallback(callback);
if (isset(actionList) && actionList.length > 0) {
actionList.forEach(function (value) {
value[1] = "['commonEvent']" + value[1];
});
saveSetting('events', actionList, function (err) {
callback([err]);
});
} else {
callback([
Object.assign({},data_obj),
editor.file.eventsComment._data.commonEvent,
null]);
}
}
//callback([obj,commentObj,err:String])
////////////////////////////////////////////////////////////////////
var plmap = {};
var pljson = JSON.stringify(plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1, function (k, v) {
if (v instanceof Function) {
var id_ = editor.util.guid();
plmap[id_] = v.toString();
return id_;
} else if(v===null){
var id_ = editor.util.guid();
plmap[id_] = null;
return id_;
} return v
}, 4);
var plobj = JSON.parse(pljson);
editor.file.pluginsMap = plmap;
editor.file.pluginsObj = plobj;
var buildpllocobj = function (locObj) {
for (var key in locObj) {
if (typeof(locObj[key]) !== typeof('')) buildpllocobj(locObj[key]);
else locObj[key] = plmap[locObj[key]];
}
};
editor.file.editPlugins = function (actionList, callback) {
/*actionList:[
["change","['test']","function(x,y){console.log(x,y)}"],
]
[]时只查询不修改
*/
checkCallback(callback);
if (isset(actionList) && actionList.length > 0) {
saveSetting('plugins', actionList, function (err) {
callback([err]);
});
} else {
callback([
(function () {
var locObj = JSON.parse(JSON.stringify(plobj));
buildpllocobj(locObj);
return locObj;
})(),
editor.file.pluginsComment,
null]);
}
}
//callback([obj,commentObj,err:String])
////////////////////////////////////////////////////////////////////
var isset = function (val) {
if (val == undefined || val == null) {
return false;
}
return true
}
var checkCallback=function(callback){
if (!isset(callback)) {
printe('未设置callback');
throw('未设置callback')
}
}
var encode = editor.util.encode64;
var alertWhenCompress = function(){
if(editor.useCompress===true){
editor.useCompress='alerted';
setTimeout("alert('当前游戏使用的是压缩文件,修改完成后请使用启动服务.exe->Js代码压缩工具重新压缩,或者把main.js的useCompress改成false来使用原始文件')",1000)
}
}
editor.file.save_icons_maps_items_enemys=function(callback){
var check=[]
saveSetting('icons',[],function(err){
if(err){callback(err);return;}
check.push('icons')
if(check.length==4)callback(null);
})
saveSetting('maps',[],function(err){
if(err){callback(err);return;}
check.push('maps')
if(check.length==4)callback(null);
})
saveSetting('items',[],function(err){
if(err){callback(err);return;}
check.push('items')
if(check.length==4)callback(null);
})
saveSetting('enemys',[],function(err){
if(err){callback(err);return;}
check.push('enemys')
if(check.length==4)callback(null);
})
}
var saveSetting = function (file, actionList, callback) {
//console.log(file);
//console.log(actionList);
editor.file.alertWhenCompress();
if (file == 'icons') {
actionList.forEach(function (value) {
eval("icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1" + value[1] + '=' + JSON.stringify(value[2]));
});
var datastr = 'var icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1 = \n';
datastr += JSON.stringify(icons_4665ee12_3a1f_44a4_bea3_0fccba634dc1, null, '\t');
fs.writeFile('project/icons.js', encode(datastr), 'base64', function (err, data) {
callback(err);
});
return;
}
if (file == 'maps') {
actionList.forEach(function (value) {
eval("maps_90f36752_8815_4be8_b32b_d7fad1d0542e" + value[1] + '=' + JSON.stringify(value[2]));
});
var datastr = 'var maps_90f36752_8815_4be8_b32b_d7fad1d0542e = \n';
//datastr+=JSON.stringify(maps_90f36752_8815_4be8_b32b_d7fad1d0542e,null,4);
var emap = {};
var estr = JSON.stringify(maps_90f36752_8815_4be8_b32b_d7fad1d0542e, function (k, v) {
if (v.id != null) {
var id_ = editor.util.guid();
emap[id_] = JSON.stringify(v);
return id_;
} else return v
}, '\t');
for (var id_ in emap) {
estr = estr.replace('"' + id_ + '"', emap[id_])
}
datastr += estr;
fs.writeFile('project/maps.js', encode(datastr), 'base64', function (err, data) {
callback(err);
});
return;
}
if (file == 'items') {
actionList.forEach(function (value) {
eval("items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a" + value[1] + '=' + JSON.stringify(value[2]));
});
var datastr = 'var items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a = \n';
datastr += JSON.stringify(items_296f5d02_12fd_4166_a7c1_b5e830c9ee3a, null, '\t');
fs.writeFile('project/items.js', encode(datastr), 'base64', function (err, data) {
callback(err);
});
return;
}
if (file == 'enemys') {
actionList.forEach(function (value) {
eval("enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80" + value[1] + '=' + JSON.stringify(value[2]));
});
var datastr = 'var enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80 = \n';
var emap = {};
var estr = JSON.stringify(enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80, function (k, v) {
if (v.hp != null) {
var id_ = editor.util.guid();
emap[id_] = JSON.stringify(v);
return id_;
} else return v
}, '\t');
for (var id_ in emap) {
estr = estr.replace('"' + id_ + '"', emap[id_])
}
datastr += estr;
fs.writeFile('project/enemys.js', encode(datastr), 'base64', function (err, data) {
callback(err);
});
return;
}
if (file == 'data') {
actionList.forEach(function (value) {
eval("data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d" + value[1] + '=' + JSON.stringify(value[2]));
});
if (data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main.floorIds.indexOf(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.floorId) < 0)
data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.floorId = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main.floorIds[0];
var datastr = 'var data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = \n';
datastr += JSON.stringify(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d, null, '\t');
fs.writeFile('project/data.js', encode(datastr), 'base64', function (err, data) {
callback(err);
});
return;
}
if (file == 'functions') {
actionList.forEach(function (value) {
eval("fmap[fobj" + value[1] + ']=' + JSON.stringify(value[2]));
});
var fraw = fjson;
for (var id_ in fmap) {
fraw = fraw.replace('"' + id_ + '"', fmap[id_])
}
var datastr = 'var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = \n';
datastr += fraw;
fs.writeFile('project/functions.js', encode(datastr), 'base64', function (err, data) {
callback(err);
});
return;
}
if (file == 'floorloc') {
actionList.forEach(function (value) {
// 检测null/undefined
if(/\['autoEvent'\]\['\d+,\d+'\]\['\d+'\]$/.test(value[1])){
var tempvalue=value[1].replace(/\['\d+'\]$/,'')
tempvalue="editor.currentFloorData" +tempvalue
tempvalue=tempvalue+'='+tempvalue+'||{}'
eval(tempvalue)
}
if (value[2]==null && value[0]!=='add')
eval("delete editor.currentFloorData" + value[1]);
else
eval("editor.currentFloorData" + value[1] + '=' + JSON.stringify(value[2]));
});
editor.file.saveFloorFile(callback);
return;
}
if (file == 'floors') {
actionList.forEach(function (value) {
eval("editor.currentFloorData" + value[1] + '=' + JSON.stringify(value[2]));
});
editor.file.saveFloorFile(callback);
return;
}
if (file == 'events') {
actionList.forEach(function (value) {
eval("events_c12a15a8_c380_4b28_8144_256cba95f760" + value[1] + '=' + JSON.stringify(value[2]));
});
var datastr = 'var events_c12a15a8_c380_4b28_8144_256cba95f760 = \n';
datastr += JSON.stringify(events_c12a15a8_c380_4b28_8144_256cba95f760, null, '\t');
fs.writeFile('project/events.js', encode(datastr), 'base64', function (err, data) {
callback(err);
});
return;
}
if (file == 'plugins') {
actionList.forEach(function (value) {
if(value[0]==='add'){
eval("plobj" + value[1] + '=' + JSON.stringify(value[2]));
} else {
eval("plmap[plobj" + value[1] + ']=' + JSON.stringify(value[2]));
}
});
var plraw = JSON.stringify(plobj,null,4);
for (var id_ in plmap) {
plraw = plraw.replace('"' + id_ + '"', plmap[id_])
}
var datastr = 'var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = \n';
datastr += plraw;
fs.writeFile('project/plugins.js', encode(datastr), 'base64', function (err, data) {
callback(err);
});
return;
}
callback('出错了,要设置的文件名不识别');
}
editor.file.saveSetting = saveSetting;
return editor_file;
}
//editor_file = editor_file(editor);

View File

@ -1,37 +1,83 @@
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 () {
core.floors = JSON.parse(JSON.stringify(core.floors, function (_k, v) {
if (v instanceof Function) {
return v.toString()
} else return v
}));
core.data = JSON.parse(JSON.stringify(core.data, function (_k, v) {
if (v instanceof Function) {
return v.toString()
} else return v
}));
data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d = JSON.parse(JSON.stringify(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d, function (_k, v) {
if (v instanceof Function) {
return v.toString()
} else return v
}));
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;
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;
editor.MAX_NUM = MAX_NUM;
var getInfoById = function (id) {
var block = maps.initBlock(0, 0, id);
if (Object.prototype.hasOwnProperty.call(block, 'event')) {
@ -46,15 +92,15 @@ editor_game_wrapper = function (editor, main, core) {
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'});
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]});
editor.ids.push({ 'idnum': indexId, 'id': id, 'images': allCls[j], 'y': icons[allCls[j]][id] });
point++;
editor.indexs[i].push(point);
}
@ -62,36 +108,39 @@ editor_game_wrapper = function (editor, main, core) {
}
}
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的整数倍, 请修改后刷新页面');
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请修改后刷新页面');
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);
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});
editor.ids.push({ 'idnum': id, 'id': indexBlock.event.id, 'images': imgName, "x": x, "y": y, isTile: true });
point++;
editor.indexs[id]=[point];
editor.indexs[id] = [point];
}
startOffset += core.icons.tilesetStartOffset;
}
}
editor_game.prototype.fetchMapFromCore = function(){
// 获取当前地图
editor_game.prototype.fetchMapFromCore = function () {
var mapArray = core.maps.saveMap(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");
printe("素材数字" + x + "未定义。是不是忘了注册或者接档时没有覆盖icons.js和maps.js");
y = [0];
}
return editor.ids[y[0]]
@ -99,17 +148,20 @@ editor_game_wrapper = function (editor, main, core) {
});
editor.currentFloorId = core.status.floorId;
editor.currentFloorData = core.floors[core.status.floorId];
for(var ii=0,name;name=['bgmap','fgmap'][ii];ii++){
// 补出缺省的数据
editor.currentFloorData.autoEvent = editor.currentFloorData.autoEvent || {};
//
for (var ii = 0, name; name = ['bgmap', 'fgmap'][ii]; ii++) {
var mapArray = editor.currentFloorData[name];
if(!mapArray || JSON.stringify(mapArray)==JSON.stringify([])){//未设置或空数组
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 = eval('[' + Array(editor.map.length + 1).join('[' + Array(editor.map[0].length + 1).join('0,') + '],') + ']');
}
editor[name]=mapArray.map(function (v) {
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");
printe("素材数字" + x + "未定义。是不是忘了注册或者接档时没有覆盖icons.js和maps.js");
y = [0];
}
return editor.ids[y[0]]
@ -118,6 +170,27 @@ editor_game_wrapper = function (editor, main, core) {
}
}
// 获取地图列表
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();
}

View File

@ -1,4 +1,6 @@
// 由于历史遗留原因, 以下变量作为全局变量使用
// exportMap mapEditArea pout mapEditArea copyMap clearMapButton deleteMap printf printe tip selectBox
// 除对这些量的功能修改外, 误在此文件中增加新变量或函数
exportMap = document.getElementById('exportMap')
exportMap.isExport=false
exportMap.onclick=function(){
@ -206,13 +208,21 @@ printf = function (str_, type) {
printe = function (str_) {
printf(str_, 'error')
}
tip_in_showMode = [
'涉及图片的更改需要F5刷新浏览器来生效',
'文本域可以通过双击,在文本编辑器或事件编辑器中编辑',
'事件编辑器中的显示文本和自定义脚本的方块也可以双击',
"画出的地图要点击\"保存地图\"才会写入到文件中",
];
tip=document.getElementById('tip')
tip.showHelp = function(value) {
var tips = [
'表格的文本域可以双击进行编辑',
'双击地图可以选中素材,右键可以弹出菜单',
'双击事件编辑器的图块可以进行长文本编辑/脚本编辑/地图选点/UI绘制预览等操作',
'ESC或点击空白处可以自动保存当前修改',
'H键可以打开操作帮助哦',
'tileset贴图模式可以在地图上拖动来一次绘制一个区域右键额外素材也可以绑定宽高',
'可以拖动地图上的图块和事件或按Ctrl+C, Ctrl+X和Ctrl+V进行复制剪切和粘贴Delete删除',
'Alt+数字键保存图块,数字键读取保存的图块',
];
if (value == null) value = Math.floor(Math.random() * tips.length);
printf('tips: ' + tips[value])
}
tip._infos= {}
tip.infos=function(value){
if(value!=null){
@ -354,7 +364,6 @@ tip.whichShow=function(value){
return tip._whichShow
}
selectBox=document.getElementById('selectBox')
dataSelection=document.getElementById('dataSelection')
selectBox._isSelected=false
selectBox.isSelected=function(value){
if(value!=null){
@ -362,8 +371,9 @@ selectBox.isSelected=function(value){
tip.isSelectedBlock(value);
tip.whichShow(0);
clearTimeout(tip.timer);
dataSelection.style.display=value?'':'none'
editor.dom.dataSelection.style.display=value?'':'none'
}
return selectBox._isSelected
}
// 修改此文件前先看文件开头的说明

164
_server/editor_listen.js Normal file
View File

@ -0,0 +1,164 @@
editor_listen_wrapper = function (editor) {
editor.constructor.prototype.listen = function () {
editor.dom.body.onmousedown = editor.uifunctions.body_click;
editor.dom.eui.oncontextmenu = function (e) { e.preventDefault() } // 自定义了右键菜单, 阻止默认行为
editor.dom.midMenu.oncontextmenu = function (e) { e.preventDefault() }
editor.dom.eui.ondblclick = editor.uifunctions.map_doubleClick
editor.dom.eui.onmousedown = editor.uifunctions.map_ondown
editor.dom.eui.onmousemove = editor.uifunctions.map_onmove
editor.dom.eui.onmouseup = editor.uifunctions.map_onup
editor.dom.mid.onmousewheel = editor.uifunctions.map_mousewheel
editor.uivalues.shortcut = 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.oncontextmenu = function (e) { e.preventDefault() }
editor.dom.extraEvent.onmousedown = editor.uifunctions.extraEvent_click
editor.dom.chooseThis.onmousedown = editor.uifunctions.chooseThis_click
editor.dom.chooseInRight.onmousedown = editor.uifunctions.chooseInRight_click
editor.dom.copyLoc.onmousedown = editor.uifunctions.copyLoc_click
editor.dom.moveLoc.onmousedown = editor.uifunctions.moveLoc_click
editor.dom.clearEvent.onmousedown = editor.uifunctions.clearEvent_click
editor.dom.clearLoc.onmousedown = editor.uifunctions.clearLoc_click
editor.dom.lastUsed.onmousedown = editor.uifunctions.lastUsed_click;
editor.dom.lockMode.onchange = editor.uifunctions.lockMode_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;
editor.dom.layerMod.onchange = editor.uifunctions.layerMod_onchange
if (editor.dom.layerMod2) editor.dom.layerMod2.onchange = editor.uifunctions.layerMod2_onchange;
if (editor.dom.layerMod3) editor.dom.layerMod3.onchange = editor.uifunctions.layerMod3_onchange;
editor.uifunctions.viewportButtons_func()
}
editor.constructor.prototype.mobile_listen = function () {
if (!editor.isMobile) return;
var mobileview = document.getElementById('mobileview');
var mid = document.getElementById('mid');
var right = document.getElementById('right');
// var mobileeditdata = document.getElementById('mobileeditdata');
editor.showdataarea = function (callShowMode) {
mid.style = 'z-index:-1;opacity: 0;';
right.style = 'z-index:-1;opacity: 0;';
// mobileeditdata.style = '';
if (callShowMode) editor.mode.showMode(editor.dom.editModeSelect.value);
editor.uifunctions.hideMidMenu();
}
mobileview.children[0].onclick = function () {
editor.showdataarea(true)
}
mobileview.children[1].onclick = function () {
mid.style = '';
right.style = 'z-index:-1;opacity: 0;';
// mobileeditdata.style = 'z-index:-1;opacity: 0;';
editor.lastClickId = '';
}
mobileview.children[3].onclick = function () {
mid.style = 'z-index:-1;opacity: 0;';
right.style = '';
// mobileeditdata.style = 'z-index:-1;opacity: 0;';
editor.lastClickId = '';
}
/*
var gettrbyid = function () {
if (!editor.lastClickId) return false;
thisTr = document.getElementById(editor.lastClickId);
input = thisTr.children[2].children[0].children[0];
field = thisTr.children[0].getAttribute('title');
cobj = JSON.parse(thisTr.children[1].getAttribute('cobj'));
return [thisTr, input, field, cobj];
}
mobileeditdata.children[0].onclick = function () {
var info = gettrbyid()
if (!info) return;
info[1].ondblclick()
}
mobileeditdata.children[1].onclick = function () {
var info = gettrbyid()
if (!info) return;
printf(info[2])
}
mobileeditdata.children[2].onclick = function () {
var info = gettrbyid()
if (!info) return;
printf(info[0].children[1].getAttribute('title'))
}
*/
//=====
document.body.ontouchstart = document.body.onmousedown;
document.body.onmousedown = null;
editor.dom.eui.ontouchstart = editor.dom.eui.onmousedown
editor.dom.eui.onmousedown = null
editor.dom.eui.ontouchmove = editor.dom.eui.onmousemove
editor.dom.eui.onmousemove = null
editor.dom.eui.ontouchend = editor.dom.eui.onmouseup
editor.dom.eui.onmouseup = null
editor.dom.chooseThis.ontouchstart = editor.dom.chooseThis.onmousedown
editor.dom.chooseThis.onmousedown = null
editor.dom.chooseInRight.ontouchstart = editor.dom.chooseInRight.onmousedown
editor.dom.chooseInRight.onmousedown = null
editor.dom.copyLoc.ontouchstart = editor.dom.copyLoc.onmousedown
editor.dom.copyLoc.onmousedown = null
editor.dom.moveLoc.ontouchstart = editor.dom.moveLoc.onmousedown
editor.dom.moveLoc.onmousedown = null
editor.dom.clearLoc.ontouchstart = editor.dom.clearLoc.onmousedown
editor.dom.clearLoc.onmousedown = null
}
editor.constructor.prototype.mode_listen = function (callback) {
// 这里的函数还没有写jsdoc, 通过_func()的方式先完成分类
editor.uifunctions.newIdIdnum_func()
editor.uifunctions.changeId_func()
editor.uifunctions.copyPasteEnemyItem_func();
editor.uifunctions.selectFloor_func()
editor.uifunctions.saveFloor_func()
editor.uifunctions.newMap_func()
editor.uifunctions.createNewMaps_func()
editor.uifunctions.changeFloorId_func()
editor.uifunctions.fixCtx_func()
editor.uifunctions.selectAppend_func()
editor.uifunctions.selectFileBtn_func()
editor.uifunctions.changeColorInput_func()
editor.uifunctions.picClick_func()
editor.uifunctions.appendConfirm_func()
editor.dom.editModeSelect.onchange = editor.mode.editModeSelect_onchange
if (Boolean(callback)) callback();
}
}

898
_server/editor_mappanel.js Normal file
View File

@ -0,0 +1,898 @@
editor_mappanel_wrapper = function (editor) {
// 暂时先 注释+分类 内部函数未完成重构
/**
* 在绘图区格子内画一个随机色块
*/
editor.uifunctions.fillPos = function (pos) {
editor.dom.euiCtx.fillStyle = '#' + ~~(Math.random() * 8) + ~~(Math.random() * 8) + ~~(Math.random() * 8);
editor.dom.euiCtx.fillRect(pos.x * 32 + 12 - core.bigmap.offsetX, pos.y * 32 + 12 - core.bigmap.offsetY, 8, 8);
}
/**
* 从鼠标点击返回可用的组件内坐标
*/
editor.uifunctions.eToLoc = function (e) {
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop
var xx = e.clientX, yy = e.clientY
if (editor.isMobile) { xx = e.touches[0].clientX, yy = e.touches[0].clientY }
editor.loc = {
'x': scrollLeft + xx - editor.dom.mid.offsetLeft - editor.dom.mapEdit.offsetLeft,
'y': scrollTop + yy - editor.dom.mid.offsetTop - editor.dom.mapEdit.offsetTop,
'size': editor.isMobile ? (32 * innerWidth * 0.96 / core.__PIXELS__) : 32
};
return editor.loc;
}
/**
* 组件内坐标转地图位置
* @param {Boolean} addViewportOffset 是否加上大地图的偏置
*/
editor.uifunctions.locToPos = function (loc, addViewportOffset) {
var offsetX = 0, offsetY = 0;
if (addViewportOffset) {
offsetX = core.bigmap.offsetX / 32;
offsetY = core.bigmap.offsetY / 32;
}
editor.pos = { 'x': ~~(loc.x / loc.size) + offsetX, 'y': ~~(loc.y / loc.size) + offsetY }
return editor.pos;
}
/**
* editor.dom.eui.ondblclick
* 双击地图可以选中素材
*/
editor.uifunctions.map_doubleClick = function (e) {
if (editor.uivalues.bindSpecialDoor.loc != null) return;
var loc = editor.uifunctions.eToLoc(e);
var pos = editor.uifunctions.locToPos(loc, true);
editor.setSelectBoxFromInfo(editor[editor.layerMod][pos.y][pos.x]);
return;
}
/**
* 用于鼠标移出map后清除状态
*/
editor.uifunctions.clearMapStepStatus = function () {
if (editor.uivalues.mouseOutCheck > 1) {
editor.uivalues.mouseOutCheck--;
setTimeout(editor.uifunctions.clearMapStepStatus, 1000);
return;
}
editor.uivalues.holdingPath = 0;
editor.uivalues.stepPostfix = [];
editor.dom.euiCtx.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__);
editor.uivalues.startPos = editor.uivalues.endPos = null;
}
/**
* editor.dom.eui.onmousedown
* + 绑定机关门事件的选择怪物
* + 右键进入菜单
* + 非绘图时选中
* + 绘图时画个矩形在那个位置
*/
editor.uifunctions.map_ondown = function (e) {
var loc = editor.uifunctions.eToLoc(e);
var pos = editor.uifunctions.locToPos(loc, true);
if (editor.uivalues.bindSpecialDoor.loc != null) {
var x = editor.pos.x, y = editor.pos.y, id = (editor.map[y][x] || {}).id;
// 检测是否是怪物
if (id && editor.game.getEnemy(id)) {
var locstr = x + "," + y, index = editor.uivalues.bindSpecialDoor.enemys.indexOf(locstr);
if (index >= 0) editor.uivalues.bindSpecialDoor.enemys.splice(index, 1);
else editor.uivalues.bindSpecialDoor.enemys.push(locstr);
editor.drawEventBlock();
editor.uifunctions._extraEvent_bindSpecialDoor_doAction();
}
return false;
}
if (e.button == 2) {
editor.uifunctions.showMidMenu(e.clientX, e.clientY);
return false;
}
if (!selectBox.isSelected()) {
editor_mode.onmode('nextChange');
editor_mode.onmode('loc');
//editor_mode.loc();
//tip.whichShow(1);
tip.showHelp(6);
editor.uivalues.startPos = pos;
editor.dom.euiCtx.strokeStyle = '#FF0000';
editor.dom.euiCtx.lineWidth = 3;
if (editor.isMobile) editor.uifunctions.showMidMenu(e.clientX, e.clientY);
return false;
}
editor.uivalues.holdingPath = 1;
editor.uivalues.mouseOutCheck = 2;
setTimeout(editor.uifunctions.clearMapStepStatus);
editor.dom.euiCtx.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__);
editor.uivalues.stepPostfix = [];
editor.uivalues.stepPostfix.push(pos);
if (editor.brushMod == 'line') editor.uifunctions.fillPos(pos);
return false;
}
/**
* editor.dom.eui.onmousemove
* + 非绘图模式时维护起止位置并画箭头
* + 绘图模式时找到与队列尾相邻的鼠标方向的点画个矩形
*/
editor.uifunctions.map_onmove = function (e) {
if (!selectBox.isSelected()) {
if (editor.uivalues.startPos == null) return;
//tip.whichShow(1);
var loc = editor.uifunctions.eToLoc(e);
var pos = editor.uifunctions.locToPos(loc, true);
if (editor.uivalues.endPos != null && editor.uivalues.endPos.x == pos.x && editor.uivalues.endPos.y == pos.y) return;
if (editor.uivalues.endPos != null) {
editor.dom.euiCtx.clearRect(Math.min(32 * editor.uivalues.startPos.x - core.bigmap.offsetX, 32 * editor.uivalues.endPos.x - core.bigmap.offsetX),
Math.min(32 * editor.uivalues.startPos.y - core.bigmap.offsetY, 32 * editor.uivalues.endPos.y - core.bigmap.offsetY),
(Math.abs(editor.uivalues.startPos.x - editor.uivalues.endPos.x) + 1) * 32, (Math.abs(editor.uivalues.startPos.y - editor.uivalues.endPos.y) + 1) * 32)
}
editor.uivalues.endPos = pos;
if (editor.uivalues.startPos != null) {
if (editor.uivalues.startPos.x != editor.uivalues.endPos.x || editor.uivalues.startPos.y != editor.uivalues.endPos.y) {
core.drawArrow('eui',
32 * editor.uivalues.startPos.x + 16 - core.bigmap.offsetX, 32 * editor.uivalues.startPos.y + 16 - core.bigmap.offsetY,
32 * editor.uivalues.endPos.x + 16 - core.bigmap.offsetX, 32 * editor.uivalues.endPos.y + 16 - core.bigmap.offsetY);
}
}
// editor_mode.onmode('nextChange');
// editor_mode.onmode('loc');
//editor_mode.loc();
//tip.whichShow(1);
// tip.showHelp(6);
return false;
}
if (editor.uivalues.holdingPath == 0) {
return false;
}
editor.uivalues.mouseOutCheck = 2;
var loc = editor.uifunctions.eToLoc(e);
var pos = editor.uifunctions.locToPos(loc, true);
var pos0 = editor.uivalues.stepPostfix[editor.uivalues.stepPostfix.length - 1]
var directionDistance = [pos.y - pos0.y, pos0.x - pos.x, pos0.y - pos.y, pos.x - pos0.x]
var max = 0, index = 4;
for (var i = 0; i < 4; i++) {
if (directionDistance[i] > max) {
index = i;
max = directionDistance[i];
}
}
var pos = [{ 'x': 0, 'y': 1 }, { 'x': -1, 'y': 0 }, { 'x': 0, 'y': -1 }, { 'x': 1, 'y': 0 }, false][index]
if (pos) {
pos.x += pos0.x;
pos.y += pos0.y;
if (editor.brushMod == 'line') editor.uifunctions.fillPos(pos);
else {
var x0 = editor.uivalues.stepPostfix[0].x;
var y0 = editor.uivalues.stepPostfix[0].y;
var x1 = pos.x;
var y1 = pos.y;
if (x0 > x1) { x0 ^= x1; x1 ^= x0; x0 ^= x1; }//swap
if (y0 > y1) { y0 ^= y1; y1 ^= y0; y0 ^= y1; }//swap
// draw rect
editor.dom.euiCtx.clearRect(0, 0, editor.dom.euiCtx.canvas.width, editor.dom.euiCtx.canvas.height);
editor.dom.euiCtx.fillStyle = 'rgba(0, 127, 255, 0.4)';
editor.dom.euiCtx.fillRect(32 * x0 - core.bigmap.offsetX, 32 * y0 - core.bigmap.offsetY,
32 * (x1 - x0) + 32, 32 * (y1 - y0) + 32);
}
editor.uivalues.stepPostfix.push(pos);
}
return false;
}
/**
* editor.dom.eui.onmouseup
* + 非绘图模式时, 交换首末点的内容
* + 绘图模式时, 根据画线/画矩形/画tileset 做对应的绘制
*/
editor.uifunctions.map_onup = function (e) {
if (!selectBox.isSelected()) {
//tip.whichShow(1);
// editor.movePos(editor.uivalues.startPos, editor.uivalues.endPos);
if (editor.layerMod == 'map')
editor.exchangePos(editor.uivalues.startPos, editor.uivalues.endPos);
else
editor.exchangeBgFg(editor.uivalues.startPos, editor.uivalues.endPos, editor.layerMod);
editor.uivalues.startPos = editor.uivalues.endPos = null;
editor.dom.euiCtx.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__);
return false;
}
editor.uivalues.holdingPath = 0;
if (editor.uivalues.stepPostfix && editor.uivalues.stepPostfix.length) {
editor.savePreMap();
if (editor.brushMod !== 'line') {
var x0 = editor.uivalues.stepPostfix[0].x;
var y0 = editor.uivalues.stepPostfix[0].y;
var x1 = editor.uivalues.stepPostfix[editor.uivalues.stepPostfix.length - 1].x;
var y1 = editor.uivalues.stepPostfix[editor.uivalues.stepPostfix.length - 1].y;
if (x0 > x1) { x0 ^= x1; x1 ^= x0; x0 ^= x1; }//swap
if (y0 > y1) { y0 ^= y1; y1 ^= y0; y0 ^= y1; }//swap
editor.uivalues.stepPostfix = [];
for (var jj = y0; jj <= y1; jj++) {
for (var ii = x0; ii <= x1; ii++) {
editor.uivalues.stepPostfix.push({ x: ii, y: jj })
}
}
}
var useBrushMode = editor.brushMod == 'tileset';
if (editor.uivalues.stepPostfix.length == 1 && (editor.uivalues.tileSize[0] > 1 || editor.uivalues.tileSize[1] > 1)) {
useBrushMode = true;
var x0 = editor.uivalues.stepPostfix[0].x;
var y0 = editor.uivalues.stepPostfix[0].y;
editor.uivalues.stepPostfix = [];
for (var jj = y0; jj < y0 + editor.uivalues.tileSize[1]; ++jj) {
for (var ii = x0; ii < x0 + editor.uivalues.tileSize[0]; ++ii) {
if (jj >= editor[editor.layerMod].length || ii >= editor[editor.layerMod][0].length) continue;
editor.uivalues.stepPostfix.push({ x: ii, y: jj });
}
}
}
if (useBrushMode && core.tilesets.indexOf(editor.info.images) !== -1) {
var imgWidth = ~~(core.material.images.tilesets[editor.info.images].width / 32);
var x0 = editor.uivalues.stepPostfix[0].x;
var y0 = editor.uivalues.stepPostfix[0].y;
var idnum = editor.info.idnum;
for (var ii = 0; ii < editor.uivalues.stepPostfix.length; ii++) {
if (editor.uivalues.stepPostfix[ii].y != y0) {
y0++;
idnum += imgWidth;
}
editor[editor.layerMod][editor.uivalues.stepPostfix[ii].y][editor.uivalues.stepPostfix[ii].x] = editor.ids[editor.indexs[idnum + editor.uivalues.stepPostfix[ii].x - x0]];
}
} else {
for (var ii = 0; ii < editor.uivalues.stepPostfix.length; ii++)
editor[editor.layerMod][editor.uivalues.stepPostfix[ii].y][editor.uivalues.stepPostfix[ii].x] = editor.info;
}
// console.log(editor.map);
if (editor.info.y != null) {
editor.uivalues.lastUsed = [editor.info].concat(editor.uivalues.lastUsed.filter(function (e) { return e.id != editor.info.id}));
editor.config.set("lastUsed", editor.uivalues.lastUsed);
}
editor.updateMap();
editor.uivalues.holdingPath = 0;
editor.uivalues.stepPostfix = [];
editor.dom.euiCtx.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__);
}
return false;
}
/**
* editor.dom.mid.onmousewheel
* 在地图编辑区域滚轮切换楼层
*/
editor.uifunctions.map_mousewheel = function (e) {
var wheel = function (direct) {
var index = editor.core.floorIds.indexOf(editor.currentFloorId);
var toId = editor.currentFloorId;
if (direct > 0 && index < editor.core.floorIds.length - 1)
toId = editor.core.floorIds[index + 1];
else if (direct < 0 && index > 0)
toId = editor.core.floorIds[index - 1];
else return;
editor_mode.onmode('nextChange');
editor_mode.onmode('floor');
editor.dom.selectFloor.value = toId;
editor.changeFloor(toId);
}
try {
if (e.wheelDelta)
wheel(Math.sign(e.wheelDelta))
else if (e.detail)
wheel(Math.sign(e.detail));
}
catch (ee) {
console.log(ee);
}
return false;
}
/**
* 显示右键菜单
*/
editor.uifunctions.showMidMenu = function (x, y) {
editor.uivalues.lastRightButtonPos = JSON.parse(JSON.stringify(
[editor.pos, editor.uivalues.lastRightButtonPos[0]]
));
// --- copy
editor.uivalues.lastCopyedInfo = [editor.copyFromPos(), editor.uivalues.lastCopyedInfo[0]];
var locStr = '(' + editor.uivalues.lastRightButtonPos[1].x + ',' + editor.uivalues.lastRightButtonPos[1].y + ')';
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
// 检测是否是上下楼
var thisevent = editor.map[editor.pos.y][editor.pos.x];
var extraEvent = editor.dom.extraEvent, parent = extraEvent.parentElement;
if (thisevent == 0) {
parent.removeChild(extraEvent);
parent.appendChild(extraEvent);
editor.dom.extraEvent.style.display = 'block';
editor.dom.extraEvent.children[0].innerHTML = '绑定出生点为此点';
} else if (thisevent.id == 'upFloor') {
parent.removeChild(extraEvent);
parent.insertBefore(extraEvent, parent.firstChild);
editor.dom.extraEvent.style.display = 'block';
editor.dom.extraEvent.children[0].innerHTML = '绑定上楼事件';
}
else if (thisevent.id == 'downFloor') {
parent.removeChild(extraEvent);
parent.insertBefore(extraEvent, parent.firstChild);
editor.dom.extraEvent.style.display = 'block';
editor.dom.extraEvent.children[0].innerHTML = '绑定下楼事件';
}
else if (['leftPortal', 'rightPortal', 'downPortal', 'upPortal'].indexOf(thisevent.id) >= 0) {
parent.removeChild(extraEvent);
parent.insertBefore(extraEvent, parent.firstChild);
editor.dom.extraEvent.style.display = 'block';
editor.dom.extraEvent.children[0].innerHTML = '绑定楼传事件';
}
else if (thisevent.id == 'specialDoor') {
parent.removeChild(extraEvent);
parent.insertBefore(extraEvent, parent.firstChild);
editor.dom.extraEvent.style.display = 'block';
editor.dom.extraEvent.children[0].innerHTML = '绑定机关门事件';
}
else editor.dom.extraEvent.style.display = 'none';
editor.dom.chooseThis.children[0].innerHTML = '选中此点' + '(' + editor.pos.x + ',' + editor.pos.y + ')'
editor.dom.copyLoc.children[0].innerHTML = '复制事件' + locStr + '到此处';
editor.dom.moveLoc.children[0].innerHTML = '交换事件' + locStr + '与此事件的位置';
editor.dom.midMenu.style = 'top:' + (y + scrollTop) + 'px;left:' + (x + scrollLeft) + 'px;';
}
/**
* 隐藏右键菜单
*/
editor.uifunctions.hideMidMenu = function () {
if (editor.isMobile) {
setTimeout(function () {
editor.dom.midMenu.style = 'display:none';
}, 200)
} else {
editor.dom.midMenu.style = 'display:none';
}
}
/**
* editor.dom.extraEvent.onmousedown
* 菜单 附加点操作
*/
editor.uifunctions.extraEvent_click = function (e) {
editor.uifunctions.hideMidMenu();
e.stopPropagation();
var thisevent = editor.map[editor.pos.y][editor.pos.x];
return editor.uifunctions._extraEvent_bindStartPoint(thisevent)
|| editor.uifunctions._extraEvent_bindStair(thisevent)
|| editor.uifunctions._extraEvent_bindSpecialDoor(thisevent);
}
/**
* 绑定该空地点为起始点
*/
editor.uifunctions._extraEvent_bindStartPoint = function (thisevent) {
if (thisevent != 0) return false;
editor.mode.onmode('tower');
editor.mode.addAction(["change", "['firstData']['floorId']", editor.currentFloorId]);
editor.mode.addAction(["change", "['firstData']['hero']['loc']['x']", editor.pos.x]);
editor.mode.addAction(["change", "['firstData']['hero']['loc']['y']", editor.pos.y]);
editor.mode.onmode('save', function () {
core.firstData.floorId = editor.currentFloorId;
core.firstData.hero.loc.x = editor.pos.x;
core.firstData.hero.loc.y = editor.pos.y;
editor.drawPosSelection();
editor.drawEventBlock();
editor.mode.tower();
printf('绑定初始点成功');
});
}
/**
* 绑定该楼梯的楼传事件
*/
editor.uifunctions._extraEvent_bindStair = function (thisevent) {
if (['upFloor', 'downFloor', 'leftPortal', 'rightPortal', 'upPortal', 'downPortal'].indexOf(thisevent.id) < 0)
return false;
var loc = editor.pos.x + "," + editor.pos.y;
if (thisevent.id == 'upFloor') {
editor.currentFloorData.changeFloor[loc] = { "floorId": ":next", "stair": "downFloor" };
}
else if (thisevent.id == 'downFloor') {
editor.currentFloorData.changeFloor[loc] = { "floorId": ":before", "stair": "upFloor" };
}
else if (thisevent.id == 'leftPortal' || thisevent.id == 'rightPortal') {
editor.currentFloorData.changeFloor[loc] = { "floorId": ":next", "stair": ":symmetry_x" }
}
else if (thisevent.id == 'upPortal' || thisevent.id == 'downPortal') {
editor.currentFloorData.changeFloor[loc] = { "floorId": ":next", "stair": ":symmetry_y" }
}
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw (err)
}
editor.drawPosSelection();
editor.drawEventBlock();
editor_mode.showMode('loc');
printf('添加楼梯事件成功');
});
return true;
}
/**
* 绑定该机关门的事件
*/
editor.uifunctions._extraEvent_bindSpecialDoor = function (thisevent) {
if (thisevent.id != 'specialDoor') return false;
var number = parseInt(prompt("请输入该机关门的怪物数量", "0"))|| 0;
if (number <= 0) return true;
editor.uivalues.bindSpecialDoor.n = number;
editor.uivalues.bindSpecialDoor.loc = editor.pos.x + ',' + editor.pos.y;
editor.uivalues.bindSpecialDoor.enemys = [];
printf("请点击选择" + number + "个怪物;切换楼层或刷新页面取消操作。");
}
/**
* 确定绑定该机关门的事件
* cancel是否取消此模式
*/
editor.uifunctions._extraEvent_bindSpecialDoor_doAction = function (cancel) {
var bindSpecialDoor = editor.uivalues.bindSpecialDoor;
if (cancel) {
bindSpecialDoor.loc = null;
bindSpecialDoor.enemys = [];
bindSpecialDoor.n = 0;
editor.drawEventBlock();
printf("");
return;
}
if (bindSpecialDoor.loc == null || bindSpecialDoor.enemys.length != bindSpecialDoor.n) return;
// 添加机关门自动事件
var doorFlag = "flag:door_" + editor.currentFloorId + "_" + bindSpecialDoor.loc.replace(',', '_');
editor.currentFloorData.autoEvent[bindSpecialDoor.loc] = {
'0': {
"condition": doorFlag + "==" + bindSpecialDoor.n,
"currentFloor": true,
"priority": 0,
"delayExecute": false,
"multiExecute": false,
"data": [
{"type": "openDoor"}
]
}
};
bindSpecialDoor.enemys.forEach(function (loc) {
editor.currentFloorData.afterBattle[loc] = [
{"type": "addValue", "name": doorFlag, "value": "1"}
]
});
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw (err)
}
editor.drawEventBlock();
editor.drawPosSelection();
editor_mode.showMode('loc');
printf('绑定机关门事件成功');
});
bindSpecialDoor.loc = null;
bindSpecialDoor.enemys = [];
bindSpecialDoor.n = 0;
}
/**
* editor.dom.chooseThis.onmousedown
* 菜单 选中此点
*/
editor.uifunctions.chooseThis_click = function (e) {
editor.uifunctions.hideMidMenu();
e.stopPropagation();
selectBox.isSelected(false);
editor_mode.onmode('nextChange');
editor_mode.onmode('loc');
//editor_mode.loc();
//tip.whichShow(1);
if (editor.isMobile) editor.showdataarea(false);
}
/**
* editor.dom.chooseInRight.onmousedown
* 菜单 在素材区选中此图块
*/
editor.uifunctions.chooseInRight_click = function (e) {
editor.uifunctions.hideMidMenu();
e.stopPropagation();
var thisevent = editor[editor.layerMod][editor.pos.y][editor.pos.x];
editor.setSelectBoxFromInfo(thisevent);
}
/**
* editor.dom.copyLoc.onmousedown
* 菜单 复制此事件
*/
editor.uifunctions.copyLoc_click = function (e) {
editor.uifunctions.hideMidMenu();
e.stopPropagation();
editor.savePreMap();
editor_mode.onmode('');
var now = editor.pos, last = editor.uivalues.lastRightButtonPos[1];
if (now.x == last.x && now.y == last.y) return;
editor.pasteToPos(editor.uivalues.lastCopyedInfo[1]);
editor.updateMap();
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw (err)
}
; printf('复制事件成功');
editor.drawPosSelection();
});
}
/**
* editor.dom.moveLoc.onmousedown
* 菜单 移动此事件
*/
editor.uifunctions.moveLoc_click = function (e) {
editor.uifunctions.hideMidMenu();
e.stopPropagation();
editor.savePreMap();
editor_mode.onmode('');
editor.exchangePos(editor.pos, editor.uivalues.lastRightButtonPos[1]);
}
/**
* editor.dom.clearEvent.onmousedown
* 菜单 仅清空此点事件
*/
editor.uifunctions.clearEvent_click = function (e) {
e.stopPropagation();
editor.clearPos(false);
}
/**
* editor.dom.clearLoc.onmousedown
* 菜单 清空此点及事件
*/
editor.uifunctions.clearLoc_click = function (e) {
e.stopPropagation();
editor.clearPos(true);
}
/**
* editor.dom.lockMode.onchange
* 点击
*/
editor.uifunctions.lockMode_onchange = function () {
tip.msgs[11] = String('锁定模式开启下将不再点击空白处自动保存,请谨慎操作。');
tip.whichShow(12);
editor.uivalues.lockMode = editor.dom.lockMode.checked;
}
/**
* editor.dom.brushMod.onchange
* 切换画笔模式
*/
editor.uifunctions.brushMod_onchange = function () {
editor.brushMod = editor.dom.brushMod.value;
}
/**
* editor.dom.brushMod2.onchange
* 切换画笔模式
*/
editor.uifunctions.brushMod2_onchange = function () {
editor.brushMod = editor.dom.brushMod2.value;
}
/**
* editor.dom.brushMod3.onchange
* 切换画笔模式
*/
editor.uifunctions.brushMod3_onchange = function () {
if (!editor.config.get('alertTileMode') &&
!confirm("从V2.6.6开始tileset贴图模式已被废弃。\n请右键额外素材并输入所需要绘制的宽高然后单击地图以绘制一个区域。\n\n点取消将不再显示此提示。")) {
editor.config.set('alertTileMode', true);
}
// tip.showHelp(5)
tip.isSelectedBlock(false)
tip.msgs[11] = String('tileset贴图模式下可以按选中tileset素材并在地图上拖动来一次绘制一个区域');
tip.whichShow(12);
editor.brushMod = editor.dom.brushMod3.value;
}
/**
* editor.dom.layerMod.onchange
* 切换编辑的层
*/
editor.uifunctions.layerMod_onchange = function () {
editor.layerMod = editor.dom.layerMod.value;
[editor.dom.bgc, editor.dom.fgc, editor.dom.evc, editor.dom.ev2c].forEach(function (x) {
x.style.opacity = 1;
});
// 手机端....
if (editor.isMobile) {
if (editor.dom.layerMod.value == 'bgmap') {
[editor.dom.fgc, editor.dom.evc, editor.dom.ev2c].forEach(function (x) {
x.style.opacity = 0.3;
});
}
if (editor.dom.layerMod.value == 'fgmap') {
[editor.dom.bgc, editor.dom.evc, editor.dom.ev2c].forEach(function (x) {
x.style.opacity = 0.3;
});
}
}
}
/**
* editor.dom.layerMod2.onchange
* 切换编辑的层
*/
editor.uifunctions.layerMod2_onchange = function () {
editor.layerMod = editor.dom.layerMod2.value;
[editor.dom.fgc, editor.dom.evc, editor.dom.ev2c].forEach(function (x) {
x.style.opacity = 0.3;
});
editor.dom.bgc.style.opacity = 1;
}
/**
* editor.dom.layerMod3.onchange
* 切换编辑的层
*/
editor.uifunctions.layerMod3_onchange = function () {
editor.layerMod = editor.dom.layerMod3.value;
[editor.dom.bgc, editor.dom.evc, editor.dom.ev2c].forEach(function (x) {
x.style.opacity = 0.3;
});
editor.dom.fgc.style.opacity = 1;
}
/**
* 移动大地图可视窗口的绑定
*/
editor.uifunctions.viewportButtons_func = function () {
var pressTimer = null;
for (var ii = 0, node; node = editor.dom.viewportButtons.children[ii]; ii++) {
(function (x, y) {
var move = function () {
editor.moveViewport(x, y);
}
node.onmousedown = function () {
clearTimeout(pressTimer);
pressTimer = setTimeout(function () {
pressTimer = -1;
var f = function () {
if (pressTimer != null) {
move();
setTimeout(f, 150);
}
}
f();
}, 500);
};
node.onmouseup = function () {
if (pressTimer > 0) {
clearTimeout(pressTimer);
move();
}
pressTimer = null;
}
})([-1, 0, 0, 1][ii], [0, -1, 1, 0][ii]);
}
}
editor.uifunctions.selectFloor_func = function () {
var selectFloor = document.getElementById('selectFloor');
editor.game.getFloorFileList(function (floors) {
var outstr = [];
floors[0].forEach(function (floor) {
outstr.push(["<option value='", floor, "'>", floor, '</option>\n'].join(''));
});
selectFloor.innerHTML = outstr.join('');
selectFloor.value = core.status.floorId;
selectFloor.onchange = function () {
editor_mode.onmode('nextChange');
editor_mode.onmode('floor');
editor.changeFloor(selectFloor.value);
}
});
}
editor.uifunctions.saveFloor_func = function () {
var saveFloor = document.getElementById('saveFloor');
editor_mode.saveFloor = function () {
editor_mode.onmode('');
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw (err)
}
; printf('保存成功');
});
}
saveFloor.onclick = editor_mode.saveFloor;
}
editor.uifunctions.lastUsed_click = function (e) {
if (editor.isMobile) return;
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop
var px = scrollLeft + e.clientX - editor.dom.mid2.offsetLeft - editor.dom.lastUsedDiv.offsetLeft,
py = scrollTop + e.clientY - editor.dom.mid2.offsetTop - editor.dom.lastUsedDiv.offsetTop;
var x = parseInt(px / 32), y = parseInt(py / 32);
var index = x + core.__SIZE__ * y;
if (index >= editor.uivalues.lastUsed.length) return;
editor.setSelectBoxFromInfo(editor.uivalues.lastUsed[index]);
return;
}
/////////////////////////////////////////////////////////////////////////////
editor.constructor.prototype.copyFromPos = function (pos) {
var fields = Object.keys(editor.file.comment._data.floors._data.loc._data);
pos = pos || editor.pos;
var map = core.clone(editor.map[pos.y][pos.x]);
var events = {};
fields.forEach(function(v){
events[v] = core.clone(editor.currentFloorData[v][pos.x+','+pos.y]);
})
return {map: map, events: events};
}
editor.constructor.prototype.pasteToPos = function (info, pos) {
if (info == null) return;
var fields = Object.keys(editor.file.comment._data.floors._data.loc._data);
pos = pos || editor.pos;
editor.map[pos.y][pos.x] = core.clone(info.map);
fields.forEach(function(v){
if (info.events[v] == null) delete editor.currentFloorData[v][pos.x+","+pos.y];
else editor.currentFloorData[v][pos.x+","+pos.y] = core.clone(info.events[v]);
});
}
editor.constructor.prototype.movePos = function (startPos, endPos, callback) {
if (!startPos || !endPos) return;
if (startPos.x == endPos.x && startPos.y == endPos.y) return;
var copyed = editor.copyFromPos(startPos);
editor.pasteToPos({map:0, events: {}}, startPos);
editor.pasteToPos(copyed, endPos);
editor.updateMap();
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw(err)
}
;printf('移动事件成功');
editor.drawPosSelection();
if (callback) callback();
});
}
editor.constructor.prototype.exchangePos = function (startPos, endPos, callback) {
if (!startPos || !endPos) return;
if (startPos.x == endPos.x && startPos.y == endPos.y) return;
var startInfo = editor.copyFromPos(startPos);
var endInfo = editor.copyFromPos(endPos);
editor.pasteToPos(startInfo, endPos);
editor.pasteToPos(endInfo, startPos);
editor.updateMap();
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw(err)
}
;printf('交换事件成功');
editor.drawPosSelection();
if (callback) callback();
});
}
editor.constructor.prototype.savePreMap = function () {
var dt = {
map: editor.map,
fgmap: editor.fgmap,
bgmap: editor.bgmap,
};
if (editor.uivalues.preMapData.length == 0
|| !core.same(editor.uivalues.preMapData[editor.uivalues.preMapData.length - 1], dt)) {
editor.uivalues.preMapData.push(core.clone(dt));
if (editor.uivalues.preMapData.length > editor.uivalues.preMapMax) {
editor.uivalues.preMapData.shift();
}
}
}
editor.constructor.prototype.moveBgFg = function (startPos, endPos, name, callback) {
if (!startPos || !endPos || ["bgmap","fgmap"].indexOf(name)<0) return;
if (startPos.x == endPos.x && startPos.y == endPos.y) return;
editor[name][endPos.y][endPos.x] = editor[name][startPos.y][startPos.x];
editor[name][startPos.y][startPos.x] = 0;
editor.updateMap();
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw(err)
}
;printf('移动图块成功');
editor.drawPosSelection();
if (callback) callback();
});
}
editor.constructor.prototype.exchangeBgFg = function (startPos, endPos, name, callback) {
if (!startPos || !endPos || ["bgmap","fgmap"].indexOf(name)<0) return;
if (startPos.x == endPos.x && startPos.y == endPos.y) return;
var value = editor[name][endPos.y][endPos.x];
editor[name][endPos.y][endPos.x] = editor[name][startPos.y][startPos.x];
editor[name][startPos.y][startPos.x] = value;
editor.updateMap();
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw(err)
}
;printf('交换图块成功');
editor.drawPosSelection();
if (callback) callback();
});
}
editor.constructor.prototype.clearPos = function (clearPos, pos, callback) {
var fields = Object.keys(editor.file.comment._data.floors._data.loc._data);
pos = pos || editor.pos;
editor.uifunctions.hideMidMenu();
editor.savePreMap();
editor.info = 0;
editor_mode.onmode('');
if (clearPos)
editor.map[pos.y][pos.x]=editor.info;
editor.updateMap();
fields.forEach(function(v){
delete editor.currentFloorData[v][pos.x+','+pos.y];
})
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw(err)
}
;printf(clearPos?'清空该点和事件成功':'只清空该点事件成功');
editor.drawPosSelection();
if (callback) callback();
});
}
}

View File

@ -0,0 +1,158 @@
editor_materialpanel_wrapper = function (editor) {
editor.uifunctions.getScrollBarHeight = function () {
var outer = document.createElement("div");
outer.style.visibility = "hidden";
outer.style.width = "100px";
outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps
document.body.appendChild(outer);
var widthNoScroll = outer.offsetWidth;
// force scrollbars
outer.style.overflow = "scroll";
// add innerdiv
var inner = document.createElement("div");
inner.style.width = "100%";
outer.appendChild(inner);
var widthWithScroll = inner.offsetWidth;
// remove divs
outer.parentNode.removeChild(outer);
return widthNoScroll - widthWithScroll;
}
/**
* editor.dom.iconExpandBtn.onclick
*/
editor.uifunctions.fold_material_click = function () {
if (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();
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 pos = editor.uifunctions.locToPos(loc);
for (var spriter in editor.widthsX) {
if (pos.x >= editor.widthsX[spriter][1] && pos.x < editor.widthsX[spriter][2]) {
var ysize = spriter.endsWith('48') ? 48 : 32;
loc.ysize = ysize;
pos.images = editor.widthsX[spriter][0];
pos.y = ~~(loc.y / loc.ysize);
if (!editor.uivalues.folded && core.tilesets.indexOf(pos.images) == -1) pos.x = editor.widthsX[spriter][1];
var autotiles = core.material.images['autotile'];
if (pos.images == 'autotile') {
var imNames = Object.keys(autotiles);
if ((pos.y + 1) * ysize > editor.widthsX[spriter][3])
pos.y = ~~(editor.widthsX[spriter][3] / ysize) - 4;
else {
for (var i = 0; i < imNames.length; i++) {
if (pos.y >= 4 * i && pos.y < 4 * (i + 1)) {
pos.images = imNames[i];
pos.y = 4 * i;
}
}
}
}
else {
var height = editor.widthsX[spriter][3], col = height / ysize;
if (editor.uivalues.folded && core.tilesets.indexOf(pos.images) == -1) {
col = (pos.x == editor.widthsX[spriter][2] - 1) ? ((col - 1) % editor.uivalues.foldPerCol + 1) : editor.uivalues.foldPerCol;
}
if (spriter == 'terrains' && pos.x == editor.widthsX[spriter][1]) col += 2;
pos.y = Math.min(pos.y, col - 1);
}
selectBox.isSelected(true);
// console.log(pos,core.material.images[pos.images].height)
editor.dom.dataSelection.style.left = pos.x * 32 + 'px';
editor.dom.dataSelection.style.top = pos.y * ysize + 'px';
editor.dom.dataSelection.style.height = ysize - 6 + 'px';
if (pos.x == 0 && pos.y == 0) {
// editor.info={idnum:0, id:'empty','images':'清除块', 'y':0};
editor.info = 0;
} else if (pos.x == 0 && pos.y == 1) {
editor.info = editor.ids[editor.indexs[17]];
} else {
if (autotiles[pos.images]) editor.info = { 'images': pos.images, 'y': 0 };
else if (core.tilesets.indexOf(pos.images) != -1) editor.info = { 'images': pos.images, 'y': pos.y, 'x': pos.x - editor.widthsX[spriter][1] };
else {
var y = pos.y;
if (editor.uivalues.folded) {
y += editor.uivalues.foldPerCol * (pos.x - editor.widthsX[spriter][1]);
}
if (pos.images == 'terrains' && pos.x == 0) y -= 2;
editor.info = { 'images': pos.images, 'y': y }
}
for (var ii = 0; ii < editor.ids.length; ii++) {
if ((core.tilesets.indexOf(pos.images) != -1 && editor.info.images == editor.ids[ii].images
&& editor.info.y == editor.ids[ii].y && editor.info.x == editor.ids[ii].x)
|| (Object.prototype.hasOwnProperty.call(autotiles, pos.images) && editor.info.images == editor.ids[ii].id
&& editor.info.y == editor.ids[ii].y)
|| (core.tilesets.indexOf(pos.images) == -1 && editor.info.images == editor.ids[ii].images
&& editor.info.y == editor.ids[ii].y)
) {
editor.info = editor.ids[ii];
break;
}
}
if (editor.info.isTile && 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];
}
}
}
}
tip.infos(JSON.parse(JSON.stringify(editor.info)));
editor_mode.onmode('nextChange');
editor_mode.onmode('enemyitem');
editor.updateLastUsedMap();
//editor_mode.enemyitem();
}
}
}
}

View File

@ -21,7 +21,7 @@ editor_mode = function (editor) {
this.mode = '';
this.info = {};
this.appendPic = {};
this.doubleClickMode='change';
this.doubleClickMode = 'change';
}
editor_mode.prototype.init = function (callback) {
@ -49,15 +49,16 @@ editor_mode = function (editor) {
editor_mode.actionList.push(action);
}
editor_mode.prototype.doActionList = function (mode, actionList) {
editor_mode.prototype.doActionList = function (mode, actionList, callback) {
if (actionList.length == 0) return;
printf('修改中...');
var cb=function(objs_){
var cb = function (objs_) {
if (objs_.slice(-1)[0] != null) {
printe(objs_.slice(-1)[0]);
throw(objs_.slice(-1)[0])
throw (objs_.slice(-1)[0])
}
;printf('修改成功');
; printf('修改成功' + (data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.name == 'template' ? '\n\n请注意全塔属性的name尚未修改请及时予以设置' : ''));
if (callback) callback();
}
switch (mode) {
case 'loc':
@ -95,9 +96,9 @@ editor_mode = function (editor) {
}
}
editor_mode.prototype.onmode = function (mode) {
editor_mode.prototype.onmode = function (mode, callback) {
if (editor_mode.mode != mode) {
if (mode === 'save') editor_mode.doActionList(editor_mode.mode, editor_mode.actionList);
if (mode === 'save') editor_mode.doActionList(editor_mode.mode, editor_mode.actionList, callback);
if (editor_mode.mode === 'nextChange' && mode) editor_mode.showMode(mode);
if (mode !== 'save') editor_mode.mode = mode;
editor_mode.actionList = [];
@ -109,15 +110,78 @@ editor_mode = function (editor) {
editor_mode.dom[name].style = 'z-index:-1;opacity: 0;';
}
editor_mode.dom[mode].style = '';
editor_mode.doubleClickMode='change';
editor_mode.doubleClickMode = 'change';
// clear
editor.drawEventBlock();
if (editor_mode[mode]) editor_mode[mode]();
document.getElementById('editModeSelect').value = mode;
var tips = tip_in_showMode;
if (!selectBox.isSelected()) printf('tips: ' + tips[~~(tips.length * Math.random())]);
editor.dom.editModeSelect.value = mode;
if (!selectBox.isSelected()) tip.showHelp();
}
editor_mode.prototype.change = function (value) {
editor_mode.onmode('nextChange');
editor_mode.onmode(value);
if (editor.isMobile) editor.showdataarea(false);
}
editor_mode.prototype.checkUnique = function (thiseval) {
if (!(thiseval instanceof Array)) return false;
var map = {};
for (var i = 0; i < thiseval.length; ++i) {
if (map[thiseval[i]]) {
alert("警告:存在重复定义!");
return false;
}
map[thiseval[i]] = true;
}
return true;
}
editor_mode.prototype.checkFloorIds = function (thiseval) {
if (!editor_mode.checkUnique(thiseval)) return false;
var oldvalue = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.main.floorIds;
fs.readdir('project/floors', function (err, data) {
if (err) {
printe(err);
throw Error(err);
}
var newfiles = thiseval.map(function (v) { return v + '.js' });
var notExist = '';
for (var name, ii = 0; name = newfiles[ii]; ii++) {
if (data.indexOf(name) === -1) notExist = name;
}
if (notExist) {
var discard = confirm('文件' + notExist + '不存在, 保存会导致工程无法打开, 是否放弃更改');
if (discard) {
editor.file.editTower([['change', "['main']['floorIds']", oldvalue]], function (objs_) {//console.log(objs_);
if (objs_.slice(-1)[0] != null) {
printe(objs_.slice(-1)[0]);
throw (objs_.slice(-1)[0])
}
; printe('已放弃floorIds的修改请F5进行刷新');
});
}
}
});
return true
}
editor_mode.prototype.changeDoubleClickModeByButton = function (mode) {
({
delete: function () {
printf('下一次双击表格的项删除,切换下拉菜单可取消;编辑后需刷新浏览器生效。');
editor_mode.doubleClickMode = mode;
},
add: function () {
printf('下一次双击表格的项则在同级添加新项,切换下拉菜单可取消;编辑后需刷新浏览器生效。');
editor_mode.doubleClickMode = mode;
}
}[mode])();
}
/////////////////////////////////////////////////////////////////////////////
editor_mode.prototype.loc = function (callback) {
//editor.pos={x: 0, y: 0};
if (!core.isset(editor.pos)) return;
@ -141,17 +205,19 @@ editor_mode = function (editor) {
//editor.info=editor.ids[editor.indexs[201]];
if (!core.isset(editor.info)) return;
if (Object.keys(editor.info).length !== 0 && editor.info.idnum!=17) editor_mode.info = editor.info;//避免editor.info被清空导致无法获得是物品还是怪物
if (Object.keys(editor.info).length !== 0 && editor.info.idnum != 17) editor_mode.info = editor.info;//避免editor.info被清空导致无法获得是物品还是怪物
if (!core.isset(editor_mode.info.id)) {
// document.getElementById('table_a3f03d4c_55b8_4ef6_b362_b345783acd72').innerHTML = '';
document.getElementById('enemyItemTable').style.display = 'none';
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') {
@ -231,7 +297,7 @@ editor_mode = function (editor) {
tableinfo.listen(tableinfo.guids);
if (Boolean(callback)) callback();
}
editor_mode.prototype.plugins = function (callback) {
var objs = [];
editor.file.editPlugins([], function (objs_) {
@ -245,11 +311,17 @@ editor_mode = function (editor) {
if (Boolean(callback)) callback();
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/**
* editor.dom.editModeSelect.onchange
*/
editor_mode.prototype.editModeSelect_onchange = function () {
editor_mode.change(editor.dom.editModeSelect.value);
}
editor_mode.prototype.listen = function (callback) {
// 移动至 editor_unsorted_2.js
// 移动至 editor_listen.js -> editor.constructor.prototype.mode_listen
}
var editor_mode = new editor_mode();

View File

@ -81,6 +81,12 @@ editor_multi = function () {
_format();
}
editor_multi.hasError = function () {
if (!editor_multi.lintAutocomplete) return false;
return JSHINT.errors.filter(function (e) {
return e.code.startsWith("E")
}).length > 0;
}
editor_multi.import = function (id_, args) {
var thisTr = document.getElementById(id_);
@ -94,6 +100,8 @@ editor_multi = function () {
editor_multi.lintAutocomplete = false;
if (args.lint === true) editor_multi.lintAutocomplete = true;
if (field.indexOf('Effect') !== -1) editor_multi.lintAutocomplete = true;
if ((!input.value || input.value == 'null') && editor_mode.mode == 'plugins')
input.value = '"function () {\\n\\t// 在此增加新插件\\n\\t\\n}"';
if (input.value.slice(0, 1) === '"' || args.string) {
editor_multi.isString = true;
codeEditor.setValue(JSON.parse(input.value) || '');
@ -113,6 +121,7 @@ editor_multi = function () {
}
codeEditor.setValue(tstr || '');
}
document.getElementById('showPlugins').style.display = editor_mode.mode == 'plugins' ? 'block': 'none';
editor_multi.show();
return true;
}
@ -124,6 +133,11 @@ editor_multi = function () {
}
editor_multi.confirm = function () {
if (editor_multi.hasError()) {
alert("当前好像存在严重的语法错误,请处理后再保存。\n严重的语法错误可能会导致整个编辑器的崩溃。");
return;
}
if (!editor_multi.id) {
editor_multi.id = '';
return;
@ -173,6 +187,11 @@ editor_multi = function () {
setvalue(codeEditor.getValue() || '');
}
editor_multi.showPlugins = function () {
if (editor.isMobile && !confirm("你确定要跳转到云端插件列表吗?")) return;
window.open("https://h5mota.com/plugins/", "_blank");
}
var multiLineArgs = [null, null, null];
editor_multi.multiLineEdit = function (value, b, f, args, callback) {
editor_multi.id = 'callFromBlockly';

View File

@ -12,34 +12,41 @@ editor_table_wrapper = function (editor) {
values.map(function (v) {
return editor.table.option(v)
}).join('')
return `<select>\n${content}</select>\n`
return /* html */`<select>\n${content}</select>\n`
}
editor_table.prototype.option = function (value) {
return `<option value='${JSON.stringify(value)}'>${JSON.stringify(value)}</option>\n`
return /* html */`<option value='${JSON.stringify(value)}'>${JSON.stringify(value)}</option>\n`
}
editor_table.prototype.text = function (value) {
return `<input type='text' spellcheck='false' value='${JSON.stringify(value)}'/>\n`
return /* html */`<input type='text' spellcheck='false' value='${JSON.stringify(value)}'/>\n`
}
editor_table.prototype.checkbox = function (value) {
return `<input type='checkbox' ${(value ? 'checked ' : '')}/>\n`
return /* html */`<input type='checkbox' ${(value ? 'checked ' : '')}/>\n`
}
editor_table.prototype.textarea = function (value, indent) {
return `<textarea spellcheck='false'>${JSON.stringify(value, null, indent || 0)}</textarea>\n`
return /* html */`<textarea spellcheck='false'>${JSON.stringify(value, null, indent || 0)}</textarea>\n`
}
editor_table.prototype.editGrid = function (showComment) {
var html = "";
if (showComment) html += "<button onclick='editor.table.onCommentBtnClick(this)'>显示完整注释</button><br/>";
html += "<button onclick='editor.table.onEditBtnClick(this)'>编辑表格内容</button>";
return html;
}
editor_table.prototype.title = function () {
return `\n<tr><td>条目</td><td>注释</td><td>值</td></tr>\n`
return /* html */`\n<tr><td>条目</td><td>注释</td><td>值</td><td>操作</td></tr>\n`
}
editor_table.prototype.gap = function (field) {
return `<tr><td>----</td><td>----</td><td>${field}</td></tr>\n`
return /* html */`<tr><td>----</td><td>----</td><td>${field}</td><td>----</td></tr>\n`
}
editor_table.prototype.tr = function (guid, field, shortField, commentHTMLescape, cobjstr, shortCommentHTMLescape, tdstr) {
return `<tr id="${guid}">
return /* html */`<tr id="${guid}">
<td title="${field}">${shortField}</td>
<td title="${commentHTMLescape}" cobj="${cobjstr}">${shortCommentHTMLescape}</td>
<td><div class="etableInputDiv">${tdstr}</div></td>
<td>${editor.table.editGrid(commentHTMLescape != shortCommentHTMLescape)}</td>
</tr>\n`
}
@ -145,6 +152,7 @@ editor_table_wrapper = function (editor) {
if (key === '_data') continue;
if (cobj[key] instanceof Function) cobj[key] = cobj[key](args);
}
pvobj[ii] = vobj = args.vobj;
// 标记为_hide的属性不展示
if (cobj._hide) continue;
if (!cobj._leaf) {
@ -193,7 +201,7 @@ editor_table_wrapper = function (editor) {
// "['a']['b']" => "b"
var shortField = field.split("']").slice(-2)[0].split("['").slice(-1)[0];
// 把长度超过 charlength 的字符改成 固定长度+...的形式
shortField = (shortField.length < charlength ? shortField : shortField.slice(0, charlength) + '...');
// shortField = (shortField.length < charlength ? shortField : shortField.slice(0, charlength) + '...');
// 完整的内容转义后供悬停查看
var commentHTMLescape = editor.util.HTMLescape(comment);
@ -285,6 +293,7 @@ editor_table_wrapper = function (editor) {
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);
@ -298,6 +307,25 @@ editor_table_wrapper = function (editor) {
}
}
/**
* "显示完整注释"被按下时
*/
editor_table.prototype.onCommentBtnClick = function (button) {
var tr = button.parentNode.parentNode;
printf(tr.children[1].getAttribute('title'));
}
/**
* "编辑表格内容"被按下时
*/
editor_table.prototype.onEditBtnClick = function (button) {
var tr = button.parentNode.parentNode;
var guid = tr.getAttribute('id');
var cobj = JSON.parse(tr.children[1].getAttribute('cobj'));
if (cobj._type === 'event') editor_blockly.import(guid, { type: cobj._event });
if (cobj._type === 'textarea') editor_multi.import(guid, { lint: cobj._lint, string: cobj._string });
}
/**
* 双击表格时
* 正常编辑: 尝试用事件编辑器或多行文本编辑器打开
@ -337,12 +365,22 @@ editor_table_wrapper = function (editor) {
editor_table.prototype.addfunc = function (guid, obj, commentObj, thisTr, input, field, cobj, modeNode) {
editor_mode.onmode(editor_mode._ids[modeNode.getAttribute('id')]);
var mode = document.getElementById('editModeSelect').value;
var mode = editor.dom.editModeSelect.value;
// 1.输入id
var newid = prompt('请输入新项的ID仅公共事件支持中文ID');
if (newid == null || newid.length == 0) {
return;
var newid = '2';
if (mode == 'loc') {
var ae = editor.currentFloorData.autoEvent[editor_mode.pos.x + ',' + editor_mode.pos.y];
if (ae != null) {
var testid;
for (testid = 2; Object.hasOwnProperty.call(ae, testid); testid++); // 从3开始是因为comment中设置了始终显示012
newid = testid + '';
}
} else {
newid = prompt('请输入新项的ID仅公共事件支持中文ID');
if (newid == null || newid.length == 0) {
return;
}
}
// 检查commentEvents

570
_server/editor_ui.js Normal file
View File

@ -0,0 +1,570 @@
editor_ui_wrapper = function (editor) {
/**
* 根据鼠标点击, 得到从元素向上到body的所有id
*/
editor.uifunctions.getClickpath = function (e) {
//console.log(e);
var clickpath = [];
var getpath = function (e) {
var path = [];
var currentElem = e.target;
while (currentElem) {
path.push(currentElem);
currentElem = currentElem.parentElement;
}
if (path.indexOf(window) === -1 && path.indexOf(document) === -1)
path.push(document);
if (path.indexOf(window) === -1)
path.push(window);
return path;
}
getpath(e).forEach(function (node) {
if (!node.getAttribute) return;
var id_ = node.getAttribute('id');
if (id_) {
if (['left', 'left1', 'left2', 'left3', 'left4', 'left5', 'left8', 'mobileview'].indexOf(id_) !== -1) clickpath.push('edit');
clickpath.push(id_);
}
});
return clickpath;
}
/**
* editor.dom.body.onmousedown
* 检测鼠标点击,
* + 如果选中了绘图区域之外, 就保存地图
* + 维护绘图区的菜单的隐藏
* + 记录最后一次点击的id(主要为了数据区服务)
*/
editor.uifunctions.body_click = function (e) {
var clickpath = editor.uifunctions.getClickpath(e);
var unselect = true;
for (var ii = 0, thisId; thisId = ['edit', 'tip', 'brushMod', 'brushMod2', 'brushMod3', 'layerMod', 'layerMod2', 'layerMod3', 'viewportButtons'][ii]; ii++) {
if (clickpath.indexOf(thisId) !== -1) {
unselect = false;
break;
}
}
if (unselect && !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('地图保存成功');
});
}
selectBox.isSelected(false);
editor.info = {};
}
}
//editor.mode.onmode('');
if (e.button != 2 && !editor.isMobile) {
editor.uifunctions.hideMidMenu();
}
if (clickpath.indexOf('down') !== -1 && editor.isMobile && clickpath.indexOf('midMenu') === -1) {
editor.uifunctions.hideMidMenu();
}
if (clickpath.length >= 2 && clickpath[0].indexOf('id_') === 0) { editor.lastClickId = clickpath[0] }
}
/**
* editor.dom.body.onkeydown
* 绑定快捷键
*/
editor.uifunctions.body_shortcut = function (e) {
// UI预览 & 地图选点
if (editor.uievent && editor.uievent.isOpen) {
e.preventDefault();
if (e.keyCode == 27) editor.uievent.close();
else if (e.keyCode == 13) editor.uievent.confirm();
else if (e.keyCode == 87) editor.uievent.move(0, -1)
else if (e.keyCode == 65) editor.uievent.move(-1, 0)
else if (e.keyCode == 83) editor.uievent.move(0, 1);
else if (e.keyCode == 68) editor.uievent.move(1, 0);
return;
}
// 监听Ctrl+S保存
if (e.ctrlKey && e.keyCode == 83) {
e.preventDefault();
if (editor_multi.id != "") {
editor_multi.confirm(); // 保存脚本编辑器
}
else if (editor_blockly.id != "") {
editor_blockly.confirm(); // 保存事件编辑器
}
else {
editor_mode.saveFloor();
}
return;
}
// 如果是开启事件/脚本编辑器状态,则忽略
if (editor_multi.id != "" || editor_blockly.id != "")
return;
// PGUP和PGDOWN切换楼层
if (e.keyCode == 33 || e.keyCode == 34) {
e.preventDefault();
var index = editor.core.floorIds.indexOf(editor.currentFloorId);
var nextIndex = index + (e.keyCode == 33 ? 1 : -1);
if (nextIndex >= 0 && nextIndex < editor.core.floorIds.length) {
var toId = editor.core.floorIds[nextIndex];
editor_mode.onmode('nextChange');
editor_mode.onmode('floor');
document.getElementById('selectFloor').value = toId;
editor.changeFloor(toId);
}
return;
}
var focusElement = document.activeElement;
if (!focusElement || focusElement.tagName.toLowerCase() == 'body'
|| focusElement.id == 'selectFloor') {
//Ctrl+z 撤销上一步undo
if (e.keyCode == 90 && e.ctrlKey) {
e.preventDefault();
if (editor.uivalues.preMapData.length > 0) {
var data = editor.uivalues.preMapData.pop();
editor.map = JSON.parse(JSON.stringify(data.map));
editor.fgmap = JSON.parse(JSON.stringify(data.fgmap));
editor.bgmap = JSON.parse(JSON.stringify(data.bgmap));
editor.updateMap();
editor.uivalues.postMapData.push(data);
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.map = JSON.parse(JSON.stringify(data.map));
editor.fgmap = JSON.parse(JSON.stringify(data.fgmap));
editor.bgmap = JSON.parse(JSON.stringify(data.bgmap));
editor.updateMap();
editor.uivalues.preMapData.push(data);
printf("已重做此操作,你可能需要重新保存地图。");
}
return;
}
// Ctrl+C, Ctrl+X, Ctrl+V
if (e.ctrlKey && e.keyCode == 67 && !selectBox.isSelected()) {
e.preventDefault();
editor.uivalues.copyedInfo = editor.copyFromPos();
printf('该点事件已复制');
return;
}
if (e.ctrlKey && e.keyCode == 88 && !selectBox.isSelected()) {
e.preventDefault();
editor.uivalues.copyedInfo = editor.copyFromPos();
editor.clearPos(true, null, function () {
printf('该点事件已剪切');
})
return;
}
if (e.ctrlKey && e.keyCode == 86 && !selectBox.isSelected()) {
e.preventDefault();
if (!editor.uivalues.copyedInfo) {
printe("没有复制的事件");
return;
}
editor.pasteToPos(editor.uivalues.copyedInfo);
editor.updateMap();
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw (err)
}
; printf('粘贴事件成功');
editor.drawPosSelection();
});
return;
}
// DELETE
if (e.keyCode == 46 && !selectBox.isSelected()) {
editor.clearPos(true);
return;
}
// ESC
if (e.keyCode == 27) {
if (selectBox.isSelected()) {
editor_mode.onmode('');
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw (err)
}
; printf('地图保存成功');
});
}
selectBox.isSelected(false);
editor.info = {};
return;
}
//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;
// Z~.
case 90: editor_mode.change('map'); break; // Z
case 88: editor_mode.change('loc'); break; // X
case 67: editor_mode.change('enemyitem'); break; // C
case 86: editor_mode.change('floor'); break; // V
case 66: editor_mode.change('tower'); break; // B
case 78: editor_mode.change('functions'); break; // N
case 77: editor_mode.change('appendpic'); break; // M
case 188: editor_mode.change('commonevent'); break; // ,
case 190: editor_mode.change('plugins'); break; // .
// H
case 72: editor.uifunctions.showHelp(); break;
}
return;
}
}
editor.uifunctions.showHelp = function () {
alert(
"快捷操作帮助:\n" +
"ESC / 点击空白处:自动保存当前修改" +
"WASD / 长按箭头:平移大地图\n" +
"PgUp, PgDn / 鼠标滚轮:上下切换楼层\n" +
"Z~.(键盘的第三排):快捷切换标签\n" +
"双击地图:选中对应点的素材\n" +
"右键地图:弹出菜单栏\n" +
"Alt+0~9保存当前使用的图块\n" +
"0~9选中保存的图块\n" +
"Ctrl+Z / Ctrl+Y撤销/重做上次绘制\n" +
"Ctrl+S事件与脚本编辑器的保存并退出\n" +
"双击事件编辑器:长文本编辑/脚本编辑/地图选点/UI绘制预览"
);
}
// ------ UI预览 & 地图选点相关 ------ //
var uievent = {
elements: {},
values: {},
isOpen: false,
mode: ""
};
uievent.elements.div = document.getElementById('uieventDiv');
uievent.elements.title = document.getElementById('uieventTitle');
uievent.elements.yes = document.getElementById('uieventYes');
uievent.elements.no = document.getElementById('uieventNo');
uievent.elements.selectBackground = document.getElementById('uieventBackground');
uievent.elements.selectPoint = document.getElementById('selectPoint');
uievent.elements.selectFloor = document.getElementById('selectPointFloor');
uievent.elements.selectPointBox = document.getElementById('selectPointBox');
uievent.elements.body = document.getElementById('uieventBody');
uievent.elements.selectPointButtons = document.getElementById('selectPointButtons');
uievent.elements.canvas = document.getElementById('uievent');
uievent.elements.usedFlags = document.getElementById('uieventUsedFlags');
uievent.elements.usedFlagList = document.getElementById('uieventUsedFlagList');
uievent.confirm = function () {
var callback = uievent.values.callback, floorId = uievent.values.floorId,
x = uievent.values.x, y = uievent.values.y;
uievent.close();
if (callback) {
callback(floorId, x, y);
}
}
uievent.elements.yes.onclick = uievent.confirm;
uievent.close = function () {
uievent.isOpen = false;
uievent.elements.div.style.display = 'none';
uievent.values = {};
}
uievent.elements.no.onclick = uievent.close;
uievent.elements.selectBackground.onchange = function () {
uievent.drawPreviewUI();
}
uievent.drawPreviewUI = function () {
core.setAlpha('uievent', 1);
core.clearMap('uievent');
// 绘制UI
var background = uievent.elements.selectBackground.value;
if (background == 'thumbnail') {
core.drawThumbnail(editor.currentFloorId, null, {}, 'uievent');
}
else {
core.fillRect('uievent', 0, 0, core.__PIXELS__, core.__PIXELS__, background);
}
if (uievent.values.list instanceof Array) {
uievent.values.list.forEach(function (data) {
var type = data.type;
if (!type || !core.ui["_uievent_" + type]) return;
core.ui["_uievent_" + type](data);
})
}
}
uievent.previewUI = function (list) {
uievent.isOpen = true;
uievent.elements.div.style.display = 'block';
uievent.mode = 'previewUI';
uievent.elements.selectPoint.style.display = 'none';
uievent.elements.yes.style.display = 'none';
uievent.elements.title.innerText = 'UI绘制预览';
uievent.elements.selectBackground.style.display = 'inline';
uievent.elements.selectBackground.value = 'thumbnail';
uievent.elements.selectFloor.style.display = 'none';
uievent.elements.selectPointBox.style.display = 'none';
uievent.elements.canvas.style.display = 'block';
uievent.elements.usedFlags.style.display = 'none';
uievent.elements.usedFlagList.style.display = 'none';
uievent.elements.body.style.overflow = "hidden";
uievent.values.list = list;
uievent.drawPreviewUI();
}
uievent.selectPoint = function (floorId, x, y, hideFloor, callback) {
uievent.values.hideFloor = hideFloor;
uievent.values.callback = callback;
uievent.values.size = editor.isMobile ? window.innerWidth / core.__SIZE__ : 32;
uievent.elements.selectPointBox.style.width = (uievent.values.size - 6) + "px";
uievent.elements.selectPointBox.style.height = (uievent.values.size - 6) + "px";
uievent.isOpen = true;
uievent.elements.div.style.display = 'block';
uievent.mode = 'selectPoint';
uievent.elements.selectPoint.style.display = 'block';
uievent.elements.yes.style.display = 'inline';
uievent.elements.selectBackground.style.display = 'none';
uievent.elements.selectFloor.style.display = hideFloor ? 'none' : 'inline';
uievent.elements.selectPointBox.style.display = 'block';
uievent.elements.canvas.style.display = 'block';
uievent.elements.usedFlags.style.display = 'none';
uievent.elements.usedFlagList.style.display = 'none';
uievent.elements.body.style.overflow = "hidden";
// Append children
var floors = "";
core.floorIds.forEach(function (f) {
floors += "<option value=" + f + ">" + f + "</option>";
})
uievent.elements.selectFloor.innerHTML = floors;
this.setPoint(floorId || editor.currentFloorId, core.calValue(x) || 0, core.calValue(y) || 0);
}
uievent.updateSelectPoint = function (redraw) {
uievent.elements.title.innerText = '地图选点 (' + uievent.values.x + "," + uievent.values.y + ')';
if (redraw) {
core.setAlpha('uievent', 1);
core.clearMap('uievent');
core.drawThumbnail(uievent.values.floorId, null, null,
{
ctx: 'uievent', centerX: uievent.values.left + core.__HALF_SIZE__,
centerY: uievent.values.top + core.__HALF_SIZE__
});
}
uievent.elements.selectPointBox.style.left = uievent.values.size * (uievent.values.x - uievent.values.left) + "px";
uievent.elements.selectPointBox.style.top = uievent.values.size * (uievent.values.y - uievent.values.top) + "px";
}
uievent.setPoint = function (floorId, x, y) {
if (core.floorIds.indexOf(floorId) == -1) floorId = editor.currentFloorId;
uievent.values.floorId = floorId;
uievent.elements.selectFloor.value = floorId;
uievent.values.x = x != null ? x : (uievent.values.x || 0);
uievent.values.y = y != null ? y : (uievent.values.y || 0);
uievent.values.width = core.floors[uievent.values.floorId].width || core.__SIZE__;
uievent.values.height = core.floors[uievent.values.floorId].height || core.__SIZE__;
uievent.values.left = core.clamp(uievent.values.x - core.__HALF_SIZE__, 0, uievent.values.width - core.__SIZE__);
uievent.values.top = core.clamp(uievent.values.y - core.__HALF_SIZE__, 0, uievent.values.height - core.__SIZE__);
uievent.updateSelectPoint(true);
}
uievent.elements.selectFloor.onchange = function () {
uievent.setPoint(uievent.elements.selectFloor.value);
}
uievent.elements.selectPointBox.onclick = function (e) {
e.stopPropagation();
}
uievent.elements.body.onclick = function (e) {
if (uievent.mode != 'selectPoint') return;
uievent.values.x = uievent.values.left + Math.floor(e.offsetX / uievent.values.size);
uievent.values.y = uievent.values.top + Math.floor(e.offsetY / uievent.values.size);
uievent.updateSelectPoint(false);
}
uievent.move = function (dx, dy) {
if (uievent.mode != 'selectPoint') return;
uievent.values.left = core.clamp(uievent.values.left + dx, 0, uievent.values.width - core.__SIZE__);
uievent.values.top = core.clamp(uievent.values.top + dy, 0, uievent.values.height - core.__SIZE__);
this.updateSelectPoint(true);
};
(function () {
var viewportButtons = uievent.elements.selectPointButtons;
var pressTimer = null;
for (var ii = 0, node; node = viewportButtons.children[ii]; ii++) {
(function (x, y) {
var move = function () {
uievent.move(x, y);
}
node.onmousedown = function () {
clearTimeout(pressTimer);
pressTimer = setTimeout(function () {
pressTimer = -1;
var f = function () {
if (pressTimer != null) {
move();
setTimeout(f, 150);
}
}
f();
}, 500);
};
node.onmouseup = function () {
if (pressTimer > 0) {
clearTimeout(pressTimer);
move();
}
pressTimer = null;
}
})([-1, 0, 0, 1][ii], [0, -1, 1, 0][ii]);
}
})();
uievent.elements.div.onmousewheel = function (e) {
if (uievent.mode != 'selectPoint' || uievent.values.hideFloor) return;
var index = core.floorIds.indexOf(uievent.values.floorId);
try {
if (e.wheelDelta)
index += Math.sign(e.wheelDelta);
else if (e.detail)
index += Math.sign(e.detail);
} catch (ee) { main.log(ee); }
index = core.clamp(index, 0, core.floorIds.length - 1);
uievent.setPoint(core.floorIds[index]);
}
// ------ 搜索变量出现的位置也放在uievent好了 ------ //
uievent.searchUsedFlags = function () {
uievent.isOpen = true;
uievent.elements.div.style.display = 'block';
uievent.mode = 'searchUsedFlags';
uievent.elements.selectPoint.style.display = 'none';
uievent.elements.yes.style.display = 'none';
uievent.elements.title.innerText = '搜索变量';
uievent.elements.selectBackground.style.display = 'none';
uievent.elements.selectFloor.style.display = 'none';
uievent.elements.selectPointBox.style.display = 'none';
uievent.elements.canvas.style.display = 'none';
uievent.elements.usedFlags.style.display = 'inline';
uievent.elements.usedFlagList.style.display = 'block';
uievent.elements.body.style.overflow = "auto";
// build flags
var html = "";
Object.keys(editor.used_flags).sort().forEach(function (v) {
v = "flag:" + v;
html += "<option value='" + v + "'>" + v + "</option>";
});
uievent.elements.usedFlags.innerHTML = html;
uievent.doSearchUsedFlags();
}
uievent.doSearchUsedFlags = function () {
var flag = uievent.elements.usedFlags.value;
var html = "<p style='margin-left: 10px'>该变量出现的所有位置如下:</p><ul>";
var list = uievent._searchUsedFlags(flag);
list.forEach(function (v) {
var x = "<li>";
if (v[0] != null) x += v[0] + "层 ";
else x += "公共事件 ";
x += v[1];
if (v[2] != null) x += " 的 (" + v[2] + ") 点";
x += "</li>";
html += x;
});
html += "</ul>";
uievent.elements.usedFlagList.innerHTML = html;
}
var hasUsedFlags = function (obj, flag) {
if (obj == null) return false;
if (typeof obj != 'string') return hasUsedFlags(JSON.stringify(obj), flag);
var index = -1, length = flag.length;
while (true) {
index = obj.indexOf(flag, index + 1);
if (index < 0) return false;
if (!/^[a-zA-Z0-9_\u4E00-\u9FCC]$/.test(obj.charAt(index + length))) return true;
}
}
uievent._searchUsedFlags = function (flag) {
var list = [];
var events = ["events", "autoEvent", "changeFloor", "afterBattle", "afterGetItem", "afterOpenDoor"]
for (var floorId in core.floors) {
var floor = core.floors[floorId];
if (hasUsedFlags(floor.firstArrive, flag)) list.push([floorId, "firstArrive"]);
if (hasUsedFlags(floor.eachArrive, flag)) list.push([floorId, "eachArrive"]);
events.forEach(function (e) {
if (floor[e]) {
for (var loc in floor[e]) {
if (hasUsedFlags(floor[e][loc], flag)) {
list.push([floorId, e, loc]);
}
}
}
});
}
// 公共事件
if (core.events.commonEvent) {
for (var name in core.events.commonEvent) {
if (hasUsedFlags(core.events.commonEvent[name], flag))
list.push([null, name]);
}
}
return list;
}
editor.constructor.prototype.uievent=uievent;
}

View File

@ -1,839 +0,0 @@
editor_unsorted_1_wrapper=function(editor){
editor.constructor.prototype.listen=function () {
document.body.onmousedown = function (e) {
//console.log(e);
var clickpath = [];
var getpath=function(e) {
var path = [];
var currentElem = e.target;
while (currentElem) {
path.push(currentElem);
currentElem = currentElem.parentElement;
}
if (path.indexOf(window) === -1 && path.indexOf(document) === -1)
path.push(document);
if (path.indexOf(window) === -1)
path.push(window);
return path;
}
getpath(e).forEach(function (node) {
if (!node.getAttribute) return;
var id_ = node.getAttribute('id');
if (id_) {
if (['left', 'left1', 'left2', 'left3', 'left4', 'left5', 'left8', 'mobileview'].indexOf(id_) !== -1) clickpath.push('edit');
clickpath.push(id_);
}
});
var unselect=true;
for(var ii=0,thisId;thisId=['edit','tip','brushMod','brushMod2','brushMod3','layerMod','layerMod2','layerMod3','viewportButtons'][ii];ii++){
if (clickpath.indexOf(thisId) !== -1){
unselect=false;
break;
}
}
if (unselect) {
if (clickpath.indexOf('eui') === -1) {
if (selectBox.isSelected()) {
editor_mode.onmode('');
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw(err)
}
;printf('地图保存成功');
});
}
selectBox.isSelected(false);
editor.info = {};
}
}
//editor.mode.onmode('');
if (e.button!=2 && !editor.isMobile){
editor.hideMidMenu();
}
if (clickpath.indexOf('down') !== -1 && editor.isMobile && clickpath.indexOf('midMenu') === -1){
editor.hideMidMenu();
}
if(clickpath.length>=2 && clickpath[0].indexOf('id_')===0){editor.lastClickId=clickpath[0]}
}
var eui=document.getElementById('eui');
var uc = eui.getContext('2d');
function fillPos(pos) {
uc.fillStyle = '#' + ~~(Math.random() * 8) + ~~(Math.random() * 8) + ~~(Math.random() * 8);
uc.fillRect(pos.x * 32 + 12 - core.bigmap.offsetX, pos.y * 32 + 12 - core.bigmap.offsetY, 8, 8);
}//在格子内画一个随机色块
function eToLoc(e) {
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop
var xx=e.clientX,yy=e.clientY
if(editor.isMobile){xx=e.touches[0].clientX,yy=e.touches[0].clientY}
editor.loc = {
'x': scrollLeft + xx - mid.offsetLeft - mapEdit.offsetLeft,
'y': scrollTop + yy - mid.offsetTop - mapEdit.offsetTop,
'size': editor.isMobile?(32*innerWidth*0.96/core.__PIXELS__):32
};
return editor.loc;
}//返回可用的组件内坐标
function locToPos(loc, addViewportOffset) {
var offsetX=0, offsetY=0;
if (addViewportOffset){
offsetX=core.bigmap.offsetX/32;
offsetY=core.bigmap.offsetY/32;
}
editor.pos = {'x': ~~(loc.x / loc.size)+offsetX, 'y': ~~(loc.y / loc.size)+offsetY}
return editor.pos;
}
var holdingPath = 0;
var stepPostfix = null;//用于存放寻路检测的第一个点之后的后续移动
var mouseOutCheck = 2;
function clear1() {
if (mouseOutCheck > 1) {
mouseOutCheck--;
setTimeout(clear1, 1000);
return;
}
holdingPath = 0;
stepPostfix = [];
uc.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__);
}//用于鼠标移出canvas时的自动清除状态
eui.oncontextmenu=function(e){e.preventDefault()}
eui.ondblclick = function(e) {
// 双击地图可以选中素材
var loc = eToLoc(e);
var pos = locToPos(loc,true);
editor.setSelectBoxFromInfo(editor[editor.layerMod][pos.y][pos.x]);
return;
}
eui.onmousedown = function (e) {
if (e.button==2){
var loc = eToLoc(e);
var pos = locToPos(loc,true);
editor.showMidMenu(e.clientX,e.clientY);
return;
}
if (!selectBox.isSelected()) {
var loc = eToLoc(e);
var pos = locToPos(loc,true);
editor_mode.onmode('nextChange');
editor_mode.onmode('loc');
//editor_mode.loc();
//tip.whichShow(1);
if(editor.isMobile)editor.showMidMenu(e.clientX,e.clientY);
return;
}
holdingPath = 1;
mouseOutCheck = 2;
setTimeout(clear1);
e.stopPropagation();
uc.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__);
var loc = eToLoc(e);
var pos = locToPos(loc,true);
stepPostfix = [];
stepPostfix.push(pos);
fillPos(pos);
}
eui.onmousemove = function (e) {
if (!selectBox.isSelected()) {
//tip.whichShow(1);
return;
}
if (holdingPath == 0) {
return;
}
mouseOutCheck = 2;
e.stopPropagation();
var loc = eToLoc(e);
var pos = locToPos(loc,true);
var pos0 = stepPostfix[stepPostfix.length - 1]
var directionDistance = [pos.y - pos0.y, pos0.x - pos.x, pos0.y - pos.y, pos.x - pos0.x]
var max = 0, index = 4;
for (var i = 0; i < 4; i++) {
if (directionDistance[i] > max) {
index = i;
max = directionDistance[i];
}
}
var pos = [{'x': 0, 'y': 1}, {'x': -1, 'y': 0}, {'x': 0, 'y': -1}, {'x': 1, 'y': 0}, false][index]
if (pos) {
pos.x += pos0.x;
pos.y += pos0.y;
stepPostfix.push(pos);
fillPos(pos);
}
}
eui.onmouseup = function (e) {
if (!selectBox.isSelected()) {
//tip.whichShow(1);
return;
}
holdingPath = 0;
e.stopPropagation();
if (stepPostfix && stepPostfix.length) {
editor.preMapData = JSON.parse(JSON.stringify({map:editor.map,fgmap:editor.fgmap,bgmap:editor.bgmap}));
if(editor.brushMod!=='line'){
var x0=stepPostfix[0].x;
var y0=stepPostfix[0].y;
var x1=stepPostfix[stepPostfix.length-1].x;
var y1=stepPostfix[stepPostfix.length-1].y;
if(x0>x1){x0^=x1;x1^=x0;x0^=x1;}//swap
if(y0>y1){y0^=y1;y1^=y0;y0^=y1;}//swap
stepPostfix=[];
for(var jj=y0;jj<=y1;jj++){
for(var ii=x0;ii<=x1;ii++){
stepPostfix.push({x:ii,y:jj})
}
}
}
currDrawData.pos = JSON.parse(JSON.stringify(stepPostfix));
currDrawData.info = JSON.parse(JSON.stringify(editor.info));
reDo = null;
// console.log(stepPostfix);
if(editor.brushMod==='tileset' && core.tilesets.indexOf(editor.info.images)!==-1){
var imgWidth=~~(core.material.images.tilesets[editor.info.images].width/32);
var x0=stepPostfix[0].x;
var y0=stepPostfix[0].y;
var idnum=editor.info.idnum;
for (var ii = 0; ii < stepPostfix.length; ii++){
if(stepPostfix[ii].y!=y0){
y0++;
idnum+=imgWidth;
}
editor[editor.layerMod][stepPostfix[ii].y][stepPostfix[ii].x] = editor.ids[editor.indexs[idnum+stepPostfix[ii].x-x0]];
}
} else {
for (var ii = 0; ii < stepPostfix.length; ii++)
editor[editor.layerMod][stepPostfix[ii].y][stepPostfix[ii].x] = editor.info;
}
// console.log(editor.map);
editor.updateMap();
holdingPath = 0;
stepPostfix = [];
uc.clearRect(0, 0, core.__PIXELS__, core.__PIXELS__);
}
}
/*
document.getElementById('mid').onkeydown = function (e) {
console.log(e);
if (e.keyCode==37) {
editor.moveViewport(-1, 0);
}
if (e.keyCode==38) {
editor.moveViewport(0, -1);
}
if (e.keyCode==39) {
editor.moveViewport(1, 0);
}
if (e.keyCode==40) {
editor.moveViewport(0, 1);
}
}
*/
document.getElementById('mid').onmousewheel = function (e) {
e.preventDefault();
var wheel = function (direct) {
var index=editor.core.floorIds.indexOf(editor.currentFloorId);
var toId = editor.currentFloorId;
if (direct>0 && index<editor.core.floorIds.length-1)
toId = editor.core.floorIds[index+1];
else if (direct<0 && index>0)
toId = editor.core.floorIds[index-1];
else return;
editor_mode.onmode('nextChange');
editor_mode.onmode('floor');
document.getElementById('selectFloor').value = toId;
editor.changeFloor(toId);
}
try {
if (e.wheelDelta)
wheel(Math.sign(e.wheelDelta))
else if (e.detail)
wheel(Math.sign(e.detail));
}
catch (ee) {
console.log(ee);
}
}
editor.preMapData = null;
var currDrawData = {
pos: [],
info: {}
};
var reDo = null;
var shortcut = core.getLocalStorage('shortcut',{48: 0, 49: 0, 50: 0, 51: 0, 52: 0, 53: 0, 54: 0, 55: 0, 56: 0, 57: 0});
document.body.onkeydown = function (e) {
// 监听Ctrl+S保存
if (e.ctrlKey && e.keyCode == 83) {
e.preventDefault();
if (editor_multi.id != "") {
editor_multi.confirm(); // 保存脚本编辑器
}
else if (editor_blockly.id != "") {
editor_blockly.confirm(); // 保存事件编辑器
}
else {
editor_mode.saveFloor();
}
return;
}
// 如果是开启事件/脚本编辑器状态,则忽略
if (editor_multi.id!="" || editor_blockly.id!="")
return;
// 禁止快捷键的默认行为
if (e.ctrlKey && [89, 90, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57].indexOf(e.keyCode) !== -1)
e.preventDefault();
if (e.altKey && [48, 49, 50, 51, 52, 53, 54, 55, 56, 57].indexOf(e.keyCode) !== -1)
e.preventDefault();
//Ctrl+z 撤销上一步undo
if (e.keyCode == 90 && e.ctrlKey && editor.preMapData && currDrawData.pos.length && selectBox.isSelected()) {
editor.map = JSON.parse(JSON.stringify(editor.preMapData.map));
editor.fgmap = JSON.parse(JSON.stringify(editor.preMapData.fgmap));
editor.bgmap = JSON.parse(JSON.stringify(editor.preMapData.bgmap));
editor.updateMap();
reDo = JSON.parse(JSON.stringify(currDrawData));
currDrawData = {pos: [], info: {}};
editor.preMapData = null;
}
//Ctrl+y 重做一步redo
if (e.keyCode == 89 && e.ctrlKey && reDo && reDo.pos.length && selectBox.isSelected()) {
editor.preMapData = JSON.parse(JSON.stringify({map:editor.map,fgmap:editor.fgmap,bgmap:editor.bgmap}));
for (var j = 0; j < reDo.pos.length; j++)
editor.map[reDo.pos[j].y][reDo.pos[j].x] = JSON.parse(JSON.stringify(reDo.info));
editor.updateMap();
currDrawData = JSON.parse(JSON.stringify(reDo));
reDo = null;
}
// PGUP和PGDOWN切换楼层
if (e.keyCode==33) {
e.preventDefault();
var index=editor.core.floorIds.indexOf(editor.currentFloorId);
if (index<editor.core.floorIds.length-1) {
var toId = editor.core.floorIds[index+1];
editor_mode.onmode('nextChange');
editor_mode.onmode('floor');
document.getElementById('selectFloor').value = toId;
editor.changeFloor(toId);
}
}
if (e.keyCode==34) {
e.preventDefault();
var index=editor.core.floorIds.indexOf(editor.currentFloorId);
if (index>0) {
var toId = editor.core.floorIds[index-1];
editor_mode.onmode('nextChange');
editor_mode.onmode('floor');
document.getElementById('selectFloor').value = toId;
editor.changeFloor(toId);
}
}
//ctrl + 0~9 切换到快捷图块
if (e.ctrlKey && [48, 49, 50, 51, 52, 53, 54, 55, 56, 57].indexOf(e.keyCode) !== -1){
editor.setSelectBoxFromInfo(JSON.parse(JSON.stringify(shortcut[e.keyCode]||0)));
}
//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;
shortcut[e.keyCode]=JSON.parse(infoToSave);
printf('已保存该快捷图块, ctrl + '+(e.keyCode-48)+' 使用.')
core.setLocalStorage('shortcut',shortcut);
}
var focusElement = document.activeElement;
if (!focusElement || focusElement.tagName.toLowerCase()=='body') {
// wasd平移大地图
if (e.keyCode==87)
editor.moveViewport(0,-1)
else if (e.keyCode==65)
editor.moveViewport(-1,0)
else if (e.keyCode==83)
editor.moveViewport(0,1);
else if (e.keyCode==68)
editor.moveViewport(1,0);
}
}
var 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;
}
var scrollBarHeight = getScrollBarHeight();
var dataSelection = document.getElementById('dataSelection');
var iconLib=document.getElementById('iconLib');
iconLib.onmousedown = function (e) {
e.stopPropagation();
if (!editor.isMobile && e.clientY>=((core.__SIZE__==13?630:655) - scrollBarHeight)) return;
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
var loc = {
'x': scrollLeft + e.clientX + iconLib.scrollLeft - right.offsetLeft - iconLib.offsetLeft,
'y': scrollTop + e.clientY + iconLib.scrollTop - right.offsetTop - iconLib.offsetTop,
'size': 32
};
editor.loc = loc;
var pos = locToPos(loc);
for (var spriter in editor.widthsX) {
if (pos.x >= editor.widthsX[spriter][1] && pos.x < editor.widthsX[spriter][2]) {
var ysize = spriter.indexOf('48') === -1 ? 32 : 48;
loc.ysize = ysize;
pos.images = editor.widthsX[spriter][0];
pos.y = ~~(loc.y / loc.ysize);
if(core.tilesets.indexOf(pos.images)==-1)pos.x = editor.widthsX[spriter][1];
var autotiles = core.material.images['autotile'];
if (pos.images == 'autotile') {
var imNames = Object.keys(autotiles);
if ((pos.y + 1) * ysize > editor.widthsX[spriter][3])
pos.y = ~~(editor.widthsX[spriter][3] / ysize) - 4;
else {
for (var i = 0; i < imNames.length; i++) {
if (pos.y >= 4 * i && pos.y < 4 * (i + 1)) {
pos.images = imNames[i];
pos.y = 4 * i;
}
}
}
} else if ((pos.y + 1) * ysize > editor.widthsX[spriter][3])
pos.y = ~~(editor.widthsX[spriter][3] / ysize) - 1;
selectBox.isSelected(true);
// console.log(pos,core.material.images[pos.images].height)
dataSelection.style.left = pos.x * 32 + 'px';
dataSelection.style.top = pos.y * ysize + 'px';
dataSelection.style.height = ysize - 6 + 'px';
if (pos.x == 0 && pos.y == 0) {
// editor.info={idnum:0, id:'empty','images':'清除块', 'y':0};
editor.info = 0;
} else if(pos.x == 0 && pos.y == 1){
editor.info = editor.ids[editor.indexs[17]];
} else {
if (Object.prototype.hasOwnProperty.call(autotiles, pos.images)) editor.info = {'images': pos.images, 'y': 0};
else if (pos.images == 'terrains') editor.info = {'images': pos.images, 'y': pos.y - 2};
else if (core.tilesets.indexOf(pos.images)!=-1) editor.info = {'images': pos.images, 'y': pos.y, 'x': pos.x-editor.widthsX[spriter][1]};
else editor.info = {'images': pos.images, 'y': pos.y};
for (var ii = 0; ii < editor.ids.length; ii++) {
if ((core.tilesets.indexOf(pos.images)!=-1 && editor.info.images == editor.ids[ii].images
&& editor.info.y == editor.ids[ii].y && editor.info.x == editor.ids[ii].x)
|| (Object.prototype.hasOwnProperty.call(autotiles, pos.images) && editor.info.images == editor.ids[ii].id
&& editor.info.y == editor.ids[ii].y)
|| (core.tilesets.indexOf(pos.images)==-1 && editor.info.images == editor.ids[ii].images
&& editor.info.y == editor.ids[ii].y )
) {
editor.info = editor.ids[ii];
break;
}
}
}
tip.infos(JSON.parse(JSON.stringify(editor.info)));
editor_mode.onmode('nextChange');
editor_mode.onmode('enemyitem');
//editor_mode.enemyitem();
}
}
}
var midMenu=document.getElementById('midMenu');
midMenu.oncontextmenu=function(e){e.preventDefault()}
editor.lastRightButtonPos=[{x:0,y:0},{x:0,y:0}];
editor.showMidMenu=function(x,y){
editor.lastRightButtonPos=JSON.parse(JSON.stringify(
[editor.pos,editor.lastRightButtonPos[0]]
));
var locStr='('+editor.lastRightButtonPos[1].x+','+editor.lastRightButtonPos[1].y+')';
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
// 检测是否是上下楼
var thisevent = editor.map[editor.pos.y][editor.pos.x];
if (thisevent.id=='upFloor') {
addFloorEvent.style.display='block';
addFloorEvent.children[0].innerHTML='绑定上楼事件';
}
else if (thisevent.id=='downFloor') {
addFloorEvent.style.display='block';
addFloorEvent.children[0].innerHTML='绑定下楼事件';
}
else addFloorEvent.style.display='none';
chooseThis.children[0].innerHTML='选中此点'+'('+editor.pos.x+','+editor.pos.y+')'
copyLoc.children[0].innerHTML='复制事件'+locStr+'到此处';
moveLoc.children[0].innerHTML='交换事件'+locStr+'与此事件的位置';
midMenu.style='top:'+(y+scrollTop)+'px;left:'+(x+scrollLeft)+'px;';
}
editor.hideMidMenu=function(){
if(editor.isMobile){
setTimeout(function(){
midMenu.style='display:none';
},200)
} else {
midMenu.style='display:none';
}
}
var addFloorEvent = document.getElementById('addFloorEvent');
addFloorEvent.onmousedown = function(e) {
editor.hideMidMenu();
e.stopPropagation();
var thisevent = editor.map[editor.pos.y][editor.pos.x];
if (thisevent.id=='upFloor') {
editor.currentFloorData.changeFloor[editor.pos.x+","+editor.pos.y] = {"floorId": ":next", "stair": "downFloor"};
}
else if (thisevent.id=='downFloor') {
editor.currentFloorData.changeFloor[editor.pos.x+","+editor.pos.y] = {"floorId": ":before", "stair": "upFloor"};
}
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw(err)
}
;printf('添加楼梯事件成功');
editor.drawPosSelection();
editor_mode.showMode('loc');
});
}
var chooseThis = document.getElementById('chooseThis');
chooseThis.onmousedown = function(e){
editor.hideMidMenu();
e.stopPropagation();
selectBox.isSelected(false);
editor_mode.onmode('nextChange');
editor_mode.onmode('loc');
//editor_mode.loc();
//tip.whichShow(1);
if(editor.isMobile)editor.showdataarea(false);
}
var chooseInRight = document.getElementById('chooseInRight');
chooseInRight.onmousedown = function(e){
editor.hideMidMenu();
e.stopPropagation();
var thisevent = editor[editor.layerMod][editor.pos.y][editor.pos.x];
editor.setSelectBoxFromInfo(thisevent);
}
var fields = Object.keys(editor.file.comment._data.floors._data.loc._data);
var copyLoc = document.getElementById('copyLoc');
copyLoc.onmousedown = function(e){
editor.hideMidMenu();
e.stopPropagation();
editor.preMapData = null;
reDo = null;
editor_mode.onmode('');
var now = editor.pos;
var last = editor.lastRightButtonPos[1];
var lastevent = editor.map[last.y][last.x];
var lastinfo = 0;
if(lastevent==0){
lastinfo = 0;
} else {
var ids=editor.indexs[lastevent.idnum];
ids=ids[0]?ids[0]:ids;
lastinfo=editor.ids[ids];
}
editor.map[now.y][now.x]=lastinfo;
editor.updateMap();
fields.forEach(function(v){
editor.currentFloorData[v][now.x+','+now.y]=editor.currentFloorData[v][last.x+','+last.y]
})
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw(err)
}
;printf('复制事件成功');
editor.drawPosSelection();
});
}
var moveLoc = document.getElementById('moveLoc');
moveLoc.onmousedown = function(e){
editor.hideMidMenu();
e.stopPropagation();
editor.preMapData = null;
reDo = null;
var thisevent = editor.map[editor.pos.y][editor.pos.x];
if(thisevent==0){
editor.info = 0;
} else {
var ids=editor.indexs[thisevent.idnum];
ids=ids[0]?ids[0]:ids;
editor.info=editor.ids[ids];
}
editor_mode.onmode('');
var now = editor.pos;
var last = editor.lastRightButtonPos[1];
var lastevent = editor.map[last.y][last.x];
var lastinfo = 0;
if(lastevent==0){
lastinfo = 0;
} else {
var ids=editor.indexs[lastevent.idnum];
ids=ids[0]?ids[0]:ids;
lastinfo=editor.ids[ids];
}
editor.map[last.y][last.x]=editor.info;
editor.map[now.y][now.x]=lastinfo;
editor.updateMap();
fields.forEach(function(v){
var temp_atsfcytaf=editor.currentFloorData[v][now.x+','+now.y];
editor.currentFloorData[v][now.x+','+now.y]=editor.currentFloorData[v][last.x+','+last.y];
editor.currentFloorData[v][last.x+','+last.y]=temp_atsfcytaf;
})
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw(err)
}
;printf('两位置的事件已互换');
editor.drawPosSelection();
});
}
var _clearPoint = function (clearPoint) {
editor.hideMidMenu();
editor.preMapData = null;
reDo = null;
editor.info = 0;
editor_mode.onmode('');
var now = editor.pos;
if (clearPoint)
editor.map[now.y][now.x]=editor.info;
editor.updateMap();
fields.forEach(function(v){
delete editor.currentFloorData[v][now.x+','+now.y];
})
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw(err)
}
;printf(clearPoint?'清空该点和事件成功':'只清空该点事件成功');
editor.drawPosSelection();
});
}
var clearEvent = document.getElementById('clearEvent');
clearEvent.onmousedown = function (e) {
e.stopPropagation();
_clearPoint(false);
}
var clearLoc = document.getElementById('clearLoc');
clearLoc.onmousedown = function(e){
e.stopPropagation();
_clearPoint(true);
}
var brushMod=document.getElementById('brushMod');
brushMod.onchange=function(){
editor.brushMod=brushMod.value;
}
var brushMod2=document.getElementById('brushMod2');
if(brushMod2)brushMod2.onchange=function(){
editor.brushMod=brushMod2.value;
}
var brushMod3=document.getElementById('brushMod3');
if(brushMod3)brushMod3.onchange=function(){
editor.brushMod=brushMod3.value;
}
var bgc = document.getElementById('bg'), fgc = document.getElementById('fg'),
evc = document.getElementById('event'), ev2c = document.getElementById('event2');
var layerMod=document.getElementById('layerMod');
layerMod.onchange=function(){
editor.layerMod=layerMod.value;
[bgc,fgc,evc,ev2c].forEach(function (x) {
x.style.opacity = 1;
});
// 手机端....
if (editor.isMobile) {
if (layerMod.value == 'bgmap') {
[fgc,evc,ev2c].forEach(function (x) {
x.style.opacity = 0.3;
});
}
if (layerMod.value == 'fgmap') {
[bgc,evc,ev2c].forEach(function (x) {
x.style.opacity = 0.3;
});
}
}
}
var layerMod2=document.getElementById('layerMod2');
if(layerMod2)layerMod2.onchange=function(){
editor.layerMod=layerMod2.value;
[fgc,evc,ev2c].forEach(function (x) {
x.style.opacity = 0.3;
});
bgc.style.opacity = 1;
}
var layerMod3=document.getElementById('layerMod3');
if(layerMod3)layerMod3.onchange=function(){
editor.layerMod=layerMod3.value;
[bgc,evc,ev2c].forEach(function (x) {
x.style.opacity = 0.3;
});
fgc.style.opacity = 1;
}
var viewportButtons=document.getElementById('viewportButtons');
for(var ii=0,node;node=viewportButtons.children[ii];ii++){
(function(x,y){
node.onclick=function(){
editor.moveViewport(x,y);
}
})([-1,0,0,1][ii],[0,-1,1,0][ii]);
}
}
editor.constructor.prototype.mobile_listen=function () {
if(!editor.isMobile)return;
var mobileview=document.getElementById('mobileview');
var editModeSelect=document.getElementById('editModeSelect');
var mid=document.getElementById('mid');
var right=document.getElementById('right');
var mobileeditdata=document.getElementById('mobileeditdata');
editor.showdataarea=function(callShowMode){
mid.style='z-index:-1;opacity: 0;';
right.style='z-index:-1;opacity: 0;';
mobileeditdata.style='';
if(callShowMode)editor.mode.showMode(editModeSelect.value);
editor.hideMidMenu();
}
mobileview.children[0].onclick=function(){
editor.showdataarea(true)
}
mobileview.children[1].onclick=function(){
mid.style='';
right.style='z-index:-1;opacity: 0;';
mobileeditdata.style='z-index:-1;opacity: 0;';
editor.lastClickId='';
}
mobileview.children[3].onclick=function(){
mid.style='z-index:-1;opacity: 0;';
right.style='';
mobileeditdata.style='z-index:-1;opacity: 0;';
editor.lastClickId='';
}
var gettrbyid=function(){
if(!editor.lastClickId)return false;
thisTr = document.getElementById(editor.lastClickId);
input = thisTr.children[2].children[0].children[0];
field = thisTr.children[0].getAttribute('title');
cobj = JSON.parse(thisTr.children[1].getAttribute('cobj'));
return [thisTr,input,field,cobj];
}
mobileeditdata.children[0].onclick=function(){
var info = gettrbyid()
if(!info)return;
info[1].ondblclick()
}
mobileeditdata.children[1].onclick=function(){
var info = gettrbyid()
if(!info)return;
printf(info[2])
}
mobileeditdata.children[2].onclick=function(){
var info = gettrbyid()
if(!info)return;
printf(info[0].children[1].getAttribute('title'))
}
//=====
document.body.ontouchstart=document.body.onmousedown;
document.body.onmousedown=null;
var eui=document.getElementById('eui');
eui.ontouchstart=eui.onmousedown
eui.onmousedown=null
eui.ontouchmove=eui.onmousemove
eui.onmousemove=null
eui.ontouchend=eui.onmouseup
eui.onmouseup=null
var chooseThis = document.getElementById('chooseThis');
chooseThis.ontouchstart=chooseThis.onmousedown
chooseThis.onmousedown=null
var chooseInRight = document.getElementById('chooseInRight');
chooseInRight.ontouchstart=chooseInRight.onmousedown
chooseInRight.onmousedown=null
var copyLoc = document.getElementById('copyLoc');
copyLoc.ontouchstart=copyLoc.onmousedown
copyLoc.onmousedown=null
var moveLoc = document.getElementById('moveLoc');
moveLoc.ontouchstart=moveLoc.onmousedown
moveLoc.onmousedown=null
var clearLoc = document.getElementById('clearLoc');
clearLoc.ontouchstart=clearLoc.onmousedown
clearLoc.onmousedown=null
}
}

View File

@ -1,581 +0,0 @@
editor_unsorted_2_wrapper=function(editor_mode){
editor_mode.constructor.prototype.listen=function (callback) {
var newIdIdnum = document.getElementById('newIdIdnum');
newIdIdnum.children[2].onclick = function () {
if (newIdIdnum.children[0].value && newIdIdnum.children[1].value) {
var id = newIdIdnum.children[0].value;
var idnum = parseInt(newIdIdnum.children[1].value);
if (!core.isset(idnum)) {
printe('不合法的idnum');
return;
}
if (!/^[0-9a-zA-Z_]+$/.test(id)) {
printe('不合法的id请使用字母、数字或下划线')
return;
}
editor.file.changeIdAndIdnum(id, idnum, editor_mode.info, function (err) {
if (err) {
printe(err);
throw(err)
}
printe('添加id的idnum成功,请F5刷新编辑器');
});
} else {
printe('请输入id和idnum');
}
}
newIdIdnum.children[4].onclick = function () {
editor.file.autoRegister(editor_mode.info, function (err) {
if (err) {
printe(err);
throw(err)
}
printe('该列所有剩余项全部自动注册成功,请F5刷新编辑器');
})
}
var selectFloor = document.getElementById('selectFloor');
editor.file.getFloorFileList(function (floors) {
var outstr = [];
floors[0].forEach(function (floor) {
outstr.push(["<option value='", floor, "'>", floor, '</option>\n'].join(''));
});
selectFloor.innerHTML = outstr.join('');
selectFloor.value = core.status.floorId;
selectFloor.onchange = function () {
editor_mode.onmode('nextChange');
editor_mode.onmode('floor');
editor.changeFloor(selectFloor.value);
}
});
var saveFloor = document.getElementById('saveFloor');
editor_mode.saveFloor = function () {
editor_mode.onmode('');
editor.file.saveFloorFile(function (err) {
if (err) {
printe(err);
throw(err)
}
;printf('保存成功');
});
}
saveFloor.onclick = editor_mode.saveFloor;
var newMap = document.getElementById('newMap');
var newFileName = document.getElementById('newFileName');
newMap.onclick = function () {
if (!newFileName.value) return;
if (core.floorIds.indexOf(newFileName.value)>=0) {
printe("该楼层已存在!");
return;
}
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(newFileName.value)) {
printe("楼层名不合法!请使用字母、数字、下划线,且不能以数字开头!");
return;
}
var width = parseInt(document.getElementById('newMapWidth').value);
var height = parseInt(document.getElementById('newMapHeight').value);
if (!core.isset(width) || !core.isset(height) || width<core.__SIZE__ || height<core.__SIZE__ || width*height>1000) {
printe("新建地图的宽高都不得小于"+core.__SIZE__+"且宽高之积不能超过1000");
return;
}
editor_mode.onmode('');
editor.file.saveNewFile(newFileName.value, function (err) {
if (err) {
printe(err);
throw(err)
}
core.floorIds.push(newFileName.value);
editor.file.editTower([['change', "['main']['floorIds']", core.floorIds]], function (objs_) {//console.log(objs_);
if (objs_.slice(-1)[0] != null) {
printe(objs_.slice(-1)[0]);
throw(objs_.slice(-1)[0])
}
;printe('新建成功,请F5刷新编辑器生效');
});
});
}
var newMaps = document.getElementById('newMaps');
var newFloors = document.getElementById('newFloors');
newMaps.onclick = function () {
if (newFloors.style.display == 'none') newFloors.style.display = 'block';
else newFloors.style.display = 'none';
}
var createNewMaps = document.getElementById('createNewMaps');
createNewMaps.onclick = function () {
var floorIds = document.getElementById('newFloorIds').value;
if (!floorIds) return;
var from = parseInt(document.getElementById('newMapsFrom').value),
to = parseInt(document.getElementById('newMapsTo').value);
if (!core.isset(from) || !core.isset(to) || from>to || from<0 || to<0) {
printe("请输入有效的起始和终止楼层");
return;
}
if (to-from >= 100) {
printe("一次最多创建99个楼层");
return;
}
var floorIdList = [];
for (var i = from; i<=to; i++) {
var floorId = floorIds.replace(/\${(.*?)}/g, function (word, value) {
return eval(value);
});
if (core.floorIds.indexOf(floorId)>=0) {
printe("要创建的楼层 "+floorId+" 已存在!");
return;
}
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(floorId)) {
printe("楼层名 "+floorId+" 不合法!请使用字母、数字、下划线,且不能以数字开头!");
return;
}
if (floorIdList.indexOf(floorId)>=0) {
printe("尝试重复创建楼层 "+floorId+" ");
return;
}
floorIdList.push(floorId);
}
var width = parseInt(document.getElementById('newMapsWidth').value);
var height = parseInt(document.getElementById('newMapsHeight').value);
if (!core.isset(width) || !core.isset(height) || width<core.__SIZE__ || height<core.__SIZE__ || width*height>1000) {
printe("新建地图的宽高都不得小于"+core.__SIZE__+"且宽高之积不能超过1000");
return;
}
editor_mode.onmode('');
editor.file.saveNewFiles(floorIdList, from, to, function (err) {
if (err) {
printe(err);
throw(err)
}
core.floorIds = core.floorIds.concat(floorIdList);
editor.file.editTower([['change', "['main']['floorIds']", core.floorIds]], function (objs_) {//console.log(objs_);
if (objs_.slice(-1)[0] != null) {
printe(objs_.slice(-1)[0]);
throw(objs_.slice(-1)[0])
}
;printe('批量创建 '+floorIdList[0]+'~'+floorIdList[floorIdList.length-1]+' 成功,请F5刷新编辑器生效');
});
});
}
var ratio = 1;
var appendPicCanvas = document.getElementById('appendPicCanvas');
var bg = appendPicCanvas.children[0];
var source = appendPicCanvas.children[1];
var source_ctx=source.getContext('2d');
var picClick = appendPicCanvas.children[2];
var sprite = appendPicCanvas.children[3];
var sprite_ctx=sprite.getContext('2d');
var appendPicSelection = document.getElementById('appendPicSelection');
[source_ctx,sprite_ctx].forEach(function(ctx){
ctx.mozImageSmoothingEnabled = false;
ctx.webkitImageSmoothingEnabled = false;
ctx.msImageSmoothingEnabled = false;
ctx.imageSmoothingEnabled = false;
})
var selectAppend = document.getElementById('selectAppend');
var selectAppend_str = [];
["terrains", "animates", "enemys", "enemy48", "items", "npcs", "npc48", "autotile"].forEach(function (image) {
selectAppend_str.push(["<option value='", image, "'>", image, '</option>\n'].join(''));
});
selectAppend.innerHTML = selectAppend_str.join('');
selectAppend.onchange = function () {
var value = selectAppend.value;
if (value == 'autotile') {
editor_mode.appendPic.imageName = 'autotile';
for (var jj=0;jj<4;jj++) appendPicSelection.children[jj].style = 'display:none';
if (editor_mode.appendPic.img) {
sprite.style.width = (sprite.width = editor_mode.appendPic.img.width) / ratio + 'px';
sprite.style.height = (sprite.height = editor_mode.appendPic.img.height) / ratio + 'px';
sprite_ctx.clearRect(0, 0, sprite.width, sprite.height);
sprite_ctx.drawImage(editor_mode.appendPic.img, 0, 0);
}
return;
}
var ysize = selectAppend.value.endsWith('48') ? 48 : 32;
editor_mode.appendPic.imageName = value;
var img = core.material.images[value];
editor_mode.appendPic.toImg = img;
var num = ~~img.width / 32;
editor_mode.appendPic.num = num;
editor_mode.appendPic.index = 0;
var selectStr = '';
for (var ii = 0; ii < num; ii++) {
appendPicSelection.children[ii].style = 'left:0;top:0;height:' + (ysize - 6) + 'px';
selectStr += '{"x":0,"y":0},'
}
editor_mode.appendPic.selectPos = eval('[' + selectStr + ']');
for (var jj = num; jj < 4; jj++) {
appendPicSelection.children[jj].style = 'display:none';
}
sprite.style.width = (sprite.width = img.width) / ratio + 'px';
sprite.style.height = (sprite.height = img.height + ysize) / ratio + 'px';
sprite_ctx.drawImage(img, 0, 0);
}
selectAppend.onchange();
var getPixel=editor.util.getPixel
var setPixel=editor.util.setPixel
var autoAdjust = function (image, callback) {
var changed = false;
// Step 1: 检测白底
var tempCanvas = document.createElement('canvas').getContext('2d');
tempCanvas.canvas.width = image.width;
tempCanvas.canvas.height = image.height;
tempCanvas.mozImageSmoothingEnabled = false;
tempCanvas.webkitImageSmoothingEnabled = false;
tempCanvas.msImageSmoothingEnabled = false;
tempCanvas.imageSmoothingEnabled = false;
tempCanvas.drawImage(image, 0, 0);
var imgData = tempCanvas.getImageData(0, 0, image.width, image.height);
var trans = 0, white = 0, black=0;
for (var i=0;i<image.width;i++) {
for (var j=0;j<image.height;j++) {
var pixel = getPixel(imgData, i, j);
if (pixel[3]==0) trans++;
if (pixel[0]==255 && pixel[1]==255 && pixel[2]==255 && pixel[3]==255) white++;
// if (pixel[0]==0 && pixel[1]==0 && pixel[2]==0 && pixel[3]==255) black++;
}
}
if (white>black && white>trans*10 && confirm("看起来这张图片是以纯白为底色,是否自动调整为透明底色?")) {
for (var i=0;i<image.width;i++) {
for (var j=0;j<image.height;j++) {
var pixel = getPixel(imgData, i, j);
if (pixel[0]==255 && pixel[1]==255 && pixel[2]==255 && pixel[3]==255) {
setPixel(imgData, i, j, [0,0,0,0]);
}
}
}
tempCanvas.clearRect(0, 0, image.width, image.height);
tempCanvas.putImageData(imgData, 0, 0);
changed = true;
}
/*
if (black>white && black>trans*10 && confirm("看起来这张图片是以纯黑为底色,是否自动调整为透明底色?")) {
for (var i=0;i<image.width;i++) {
for (var j=0;j<image.height;j++) {
var pixel = getPixel(imgData, i, j);
if (pixel[0]==0 && pixel[1]==0 && pixel[2]==0 && pixel[3]==255) {
setPixel(imgData, i, j, [0,0,0,0]);
}
}
}
tempCanvas.clearRect(0, 0, image.width, image.height);
tempCanvas.putImageData(imgData, 0, 0);
changed = true;
}
*/
// Step 2: 检测长宽比
var ysize = selectAppend.value.endsWith('48') ? 48 : 32;
if ((image.width%32!=0 || image.height%ysize!=0) && (image.width<=128 && image.height<=ysize*4)
&& confirm("目标长宽不符合条件,是否自动进行调整?")) {
var ncanvas = document.createElement('canvas').getContext('2d');
ncanvas.canvas.width = 128;
ncanvas.canvas.height = 4*ysize;
ncanvas.mozImageSmoothingEnabled = false;
ncanvas.webkitImageSmoothingEnabled = false;
ncanvas.msImageSmoothingEnabled = false;
ncanvas.imageSmoothingEnabled = false;
var w = image.width / 4, h = image.height / 4;
for (var i=0;i<4;i++) {
for (var j=0;j<4;j++) {
ncanvas.drawImage(tempCanvas.canvas, i*w, j*h, w, h, i*32 + (32-w)/2, j*ysize + (ysize-h)/2, w, h);
}
}
tempCanvas = ncanvas;
changed = true;
}
if (!changed) {
callback(image);
}
else {
var nimg = new Image();
nimg.onload = function () {
callback(nimg);
};
nimg.src = tempCanvas.canvas.toDataURL();
}
}
var selectFileBtn = document.getElementById('selectFileBtn');
selectFileBtn.onclick = function () {
var loadImage = function (content, callback) {
var image = new Image();
try {
image.onload = function () {
callback(image);
}
image.src = content;
}
catch (e) {
printe(e);
}
}
core.readFile(function (content) {
loadImage(content, function (image) {
autoAdjust(image, function (image) {
editor_mode.appendPic.img = image;
editor_mode.appendPic.width = image.width;
editor_mode.appendPic.height = image.height;
if (selectAppend.value == 'autotile') {
for (var ii = 0; ii < 3; ii++) {
var newsprite = appendPicCanvas.children[ii];
newsprite.style.width = (newsprite.width = image.width) / ratio + 'px';
newsprite.style.height = (newsprite.height = image.height) / ratio + 'px';
}
sprite_ctx.clearRect(0, 0, sprite.width, sprite.height);
sprite_ctx.drawImage(image, 0, 0);
}
else {
var ysize = selectAppend.value.endsWith('48') ? 48 : 32;
for (var ii = 0; ii < 3; ii++) {
var newsprite = appendPicCanvas.children[ii];
newsprite.style.width = (newsprite.width = Math.floor(image.width / 32) * 32) / ratio + 'px';
newsprite.style.height = (newsprite.height = Math.floor(image.height / ysize) * ysize) / ratio + 'px';
}
}
//画灰白相间的格子
var bgc = bg.getContext('2d');
var colorA = ["#f8f8f8", "#cccccc"];
var colorIndex;
var sratio = 4;
for (var ii = 0; ii < image.width / 32 * sratio; ii++) {
colorIndex = 1 - ii % 2;
for (var jj = 0; jj < image.height / 32 * sratio; jj++) {
bgc.fillStyle = colorA[colorIndex];
colorIndex = 1 - colorIndex;
bgc.fillRect(ii * 32 / sratio, jj * 32 / sratio, 32 / sratio, 32 / sratio);
}
}
//把导入的图片画出
source_ctx.drawImage(image, 0, 0);
editor_mode.appendPic.sourceImageData=source_ctx.getImageData(0,0,image.width,image.height);
//重置临时变量
selectAppend.onchange();
});
});
}, null, 'img');
return;
}
var changeColorInput=document.getElementById('changeColorInput')
changeColorInput.oninput=function(){
var delta=(~~changeColorInput.value)*30;
var imgData=editor_mode.appendPic.sourceImageData;
var nimgData=new ImageData(imgData.width,imgData.height);
// ImageData .data 形如一维数组,依次排着每个点的 R(0~255) G(0~255) B(0~255) A(0~255)
var convert=function(rgba,delta){
var rgbToHsl = editor.util.rgbToHsl
var hue2rgb = editor.util.hue2rgb
var hslToRgb = editor.util.hslToRgb
//
var hsl=rgbToHsl(rgba)
hsl[0]=(hsl[0]+delta)%360
var nrgb=hslToRgb(hsl)
nrgb.push(rgba[3])
return nrgb
}
for(var x=0; x<imgData.width; x++){
for(var y=0 ; y<imgData.height; y++){
setPixel(nimgData,x,y,convert(getPixel(imgData,x,y),delta))
}
}
source_ctx.clearRect(0, 0, imgData.width, imgData.height);
source_ctx.putImageData(nimgData, 0, 0);
}
var left1 = document.getElementById('left1');
var eToLoc = function (e) {
var scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop
var loc = {
'x': scrollLeft + e.clientX + appendPicCanvas.scrollLeft - left1.offsetLeft - appendPicCanvas.offsetLeft,
'y': scrollTop + e.clientY + appendPicCanvas.scrollTop - left1.offsetTop - appendPicCanvas.offsetTop,
'size': 32,
'ysize': selectAppend.value.endsWith('48') ? 48 : 32
};
return loc;
}//返回可用的组件内坐标
var locToPos = function (loc) {
var pos = {'x': ~~(loc.x / loc.size), 'y': ~~(loc.y / loc.ysize), 'ysize': loc.ysize}
return pos;
}
picClick.onclick = function (e) {
var loc = eToLoc(e);
var pos = locToPos(loc);
//console.log(e,loc,pos);
var num = editor_mode.appendPic.num;
var ii = editor_mode.appendPic.index;
if (ii + 1 >= num) editor_mode.appendPic.index = ii + 1 - num;
else editor_mode.appendPic.index++;
editor_mode.appendPic.selectPos[ii] = pos;
appendPicSelection.children[ii].style = [
'left:', pos.x * 32, 'px;',
'top:', pos.y * pos.ysize, 'px;',
'height:', pos.ysize - 6, 'px;'
].join('');
}
var appendConfirm = document.getElementById('appendConfirm');
appendConfirm.onclick = function () {
var confirmAutotile = function () {
var image = editor_mode.appendPic.img;
if (image.width % 96 !=0 || image.height != 128) {
printe("不合法的Autotile图片");
return;
}
var imgData = source_ctx.getImageData(0,0,image.width,image.height);
sprite_ctx.putImageData(imgData, 0, 0);
var imgbase64 = sprite.toDataURL().split(',')[1];
// Step 1: List文件名
fs.readdir('./project/images', function (err, data) {
if (err) {
printe(err);
throw(err);
}
// Step 2: 选择Autotile文件名
var filename;
for (var i=1;;++i) {
filename = 'autotile'+i;
if (data.indexOf(filename+".png")==-1) break;
}
// Step 3: 写入文件
fs.writeFile('./project/images/'+filename+".png", imgbase64, 'base64', function (err, data) {
if (err) {
printe(err);
throw(err);
}
// Step 4: 自动注册
editor_file.registerAutotile(filename, function (err) {
if (err) {
printe(err);
throw(err);
}
printe('自动元件'+filename+'注册成功,请F5刷新编辑器');
})
})
})
}
if (selectAppend.value == 'autotile') {
confirmAutotile();
return;
}
var ysize = selectAppend.value.endsWith('48') ? 48 : 32;
for (var ii = 0, v; v = editor_mode.appendPic.selectPos[ii]; ii++) {
// var imgData = source_ctx.getImageData(v.x * 32, v.y * ysize, 32, ysize);
// sprite_ctx.putImageData(imgData, ii * 32, sprite.height - ysize);
// sprite_ctx.drawImage(editor_mode.appendPic.img, v.x * 32, v.y * ysize, 32, ysize, ii * 32, height, 32, ysize)
sprite_ctx.drawImage(source_ctx.canvas, v.x*32, v.y*ysize, 32, ysize, 32*ii, sprite.height - ysize, 32, ysize);
}
var dt = sprite_ctx.getImageData(0, 0, sprite.width, sprite.height);
var imgbase64 = sprite.toDataURL().split(',')[1];
fs.writeFile('./project/images/' + editor_mode.appendPic.imageName + '.png', imgbase64, 'base64', function (err, data) {
if (err) {
printe(err);
throw(err)
}
printe('追加素材成功请F5刷新编辑器或继续追加当前素材');
sprite.style.height = (sprite.height = (sprite.height+ysize)) + "px";
sprite_ctx.putImageData(dt, 0, 0);
});
}
var editModeSelect = document.getElementById('editModeSelect');
editModeSelect.onchange = function () {
editor_mode.onmode('nextChange');
editor_mode.onmode(editModeSelect.value);
if(editor.isMobile)editor.showdataarea(false);
}
editor_mode.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.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.changeDoubleClickModeByButton=function(mode){
({
delete:function(){
printf('下一次双击表格的项删除,切换下拉菜单可取消;编辑后需刷新浏览器生效。');
editor_mode.doubleClickMode=mode;
},
add:function(){
printf('下一次双击表格的项则在同级添加新项,切换下拉菜单可取消;编辑后需刷新浏览器生效。');
editor_mode.doubleClickMode=mode;
}
}[mode])();
}
if (Boolean(callback)) callback();
}
}

View File

@ -157,6 +157,17 @@ editor_util_wrapper = function (editor) {
}).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);

Some files were not shown because too many files have changed in this diff Show More