BlitzRhythm Editor Mod Loader

A BlitzRhythm Editor Mod Loader

当前为 2023-09-06 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name BlitzRhythm Editor Mod Loader
  3. // @name:zh 闪韵灵境谱面编辑器 模组加载器
  4. // @namespace cipher-editor-mods-loader
  5. // @version 1.0.3
  6. // @description A BlitzRhythm Editor Mod Loader
  7. // @description:zh 一款《闪韵灵境》谱面编辑器的Mod加载器
  8. // @author Moyuer
  9. // @author:zh 如梦Nya
  10. // @license MIT
  11. // @grant unsafeWindow
  12. // @grant GM_xmlhttpRequest
  13. // @connect beatsaver.com
  14. // @connect githubusercontent.com
  15. // @match https://cipher-editor-cn.picovr.com/*
  16. // @match https://cipher-editor-va.picovr.com/*
  17. // @icon https://cipher-editor-va.picovr.com/favicon.ico
  18. // @require https://code.jquery.com/jquery-3.6.0.min.js
  19. // @require https://greasyfork.org/scripts/473358-jszip/code/main.js?version=1237031
  20. // @require https://greasyfork.org/scripts/473361-xml-http-request-interceptor/code/main.js?version=1237032
  21. // @require https://greasyfork.org/scripts/473362-web-indexeddb-helper/code/main.js?version=1237033
  22. // @require https://greasyfork.org/scripts/474680-blitzrhythm-editor-mod-base-lib/code/main.js?version=1246368
  23. // @require https://greasyfork.org/scripts/474682-extra-song-search/code/main.js?version=1246392
  24. // ==/UserScript==
  25.  
  26. let htmlSrc = "https://raw.githubusercontent.com/CMoyuer/BlitzRhythm-Editor-Mod-Loader/main/ModLoaderDrawer/dist/index.html"
  27.  
  28. if (GM_info.script.namespace.endsWith("-dev"))
  29. htmlSrc = "http://127.0.0.1"
  30.  
  31.  
  32. /** @type {HTMLElement} */
  33. let modloaderBox
  34. /** @type {HTMLElement} */
  35. let divMask
  36. /** @type {HTMLElement} */
  37. let iframe
  38.  
  39. function initModloaderBox() {
  40. if (modloaderBox) return
  41. modloaderBox = document.createElement("div")
  42. modloaderBox.style = "position:absolute;width:100%;height:100%;top:0;left:0;z-index:9001;pointer-events:none;"
  43.  
  44. divMask = document.createElement("div")
  45. divMask.style = "width:100%;height:100%;background-color:#00000050;display:none;pointer-events:auto;"
  46. divMask.onclick = hideIframe
  47. modloaderBox.append(divMask)
  48.  
  49. iframe = document.createElement("iframe")
  50. modloaderBox.id = "modloaderIframe"
  51. iframe.style = "box-shadow: 0 0 10px 0 black;border:none;width:360px;height:100vh;position:fixed;right:0;top:0;bottom:0;transform:translateX(100%);z-index:9999;transition: transform 0.3s ease-in-out;pointer-events: auto;"
  52. GM_xmlhttpRequest({
  53. url: htmlSrc + "?t=" + new Date().getTime(),
  54. method: "GET",
  55. onload: res => {
  56. iframe.srcdoc = res.response
  57. },
  58. onerror: res => {
  59. console.error(res)
  60. }
  61. })
  62. modloaderBox.append(iframe)
  63. document.body.append(modloaderBox)
  64. }
  65.  
  66. function showIframe() {
  67. divMask.style.display = "block"
  68. iframe.style.transform = "translateX(0)"
  69. }
  70.  
  71. function hideIframe() {
  72. divMask.style.display = "none"
  73. iframe.style.transform = "translateX(100%)"
  74. }
  75.  
  76. function initShowButton() {
  77. let btnShow = document.createElement("div")
  78. btnShow.id = "btnModLoaderShow"
  79. btnShow.innerHTML = "M"
  80. btnShow.style = "position:absolute;transform:translate(-50%, -50%);left:calc(100vw - 50px);top:calc(100vh - 50px);width:50px;height: 50px;background-color:#2196F3;border-radius:25px;z-index:9000;font-size:1.5em;line-height:50px;text-align:center;color:white;font-family:Roboto,Helvetica,Arial,sans-serif;box-shadow: 0 0 6px 0 gray;user-select:none;"
  81. let info = {
  82. handle: 0,
  83. mousedown: false,
  84. dragging: false,
  85. canClick: true,
  86. rawPos: [0, 0],
  87. position: [0, 0],
  88. }
  89.  
  90. function getMoveDistance() {
  91. return Math.abs(info.position[0] - info.rawPos[0]) + Math.abs(info.position[1] - info.rawPos[1])
  92. }
  93.  
  94. btnShow.onmousedown = res => {
  95. btnShow.style.backgroundColor = "#1769AA"
  96. info.canClick = true
  97. info.mousedown = true
  98. info.handle = setTimeout(() => {
  99. btnShow.style.boxShadow = "0 0 6px 2px white"
  100. info.dragging = true
  101. info.handle = 0
  102. }, 100)
  103. if (btnShow.style.left && btnShow.style.left.startsWith("calc"))
  104. btnShow.style.left = btnShow.offsetLeft + "px"
  105. if (btnShow.style.top && btnShow.style.top.startsWith("calc"))
  106. btnShow.style.top = btnShow.offsetTop + "px"
  107. info.rawPos = [btnShow.offsetLeft, btnShow.offsetTop]
  108. info.position = [res.clientX, res.clientY]
  109. }
  110. btnShow.onmousemove = res => {
  111. if (!info.dragging) return
  112. let x = res.clientX
  113. let y = res.clientY
  114. let deltaX = x - info.position[0]
  115. let deltaY = y - info.position[1]
  116. let left = parseInt(btnShow.style.left || 0)
  117. let top = parseInt(btnShow.style.top || 0)
  118. btnShow.style.left = left + deltaX + 'px'
  119. btnShow.style.top = top + deltaY + 'px'
  120. info.position = [x, y]
  121. }
  122. btnShow.onmouseup = btnShow.onmouseleave = () => {
  123. btnShow.style.backgroundColor = "#2196F3"
  124. btnShow.style.boxShadow = "0 0 6px 0 gray"
  125. if (info.handle > 0) {
  126. clearTimeout(info.handle)
  127. info.handle = 0
  128. }
  129. info.canClick = !info.dragging
  130. info.mousedown = false
  131. info.dragging = false
  132. }
  133. btnShow.onclick = () => {
  134. if (!info.canClick) return
  135. showIframe()
  136. }
  137.  
  138. window.onresize = () => {
  139. let left = parseInt(btnShow.style.left || 0)
  140. let top = parseInt(btnShow.style.top || 0)
  141. if (window.innerWidth < left + 50)
  142. btnShow.style.left = "calc(100vw - 50px)"
  143. if (window.innerHeight < top + 50)
  144. btnShow.style.top = "calc(100vh - 50px)"
  145. }
  146.  
  147. document.body.appendChild(btnShow)
  148. }
  149.  
  150. (function () {
  151. 'use strict'
  152. initModloaderBox()
  153.  
  154. let handle = setInterval(() => {
  155. if (!unsafeWindow.modloader) return
  156. unsafeWindow.modloader.drawer = {
  157. methods: {
  158. show: showIframe,
  159. hide: hideIframe
  160. }
  161. }
  162. initShowButton()
  163. clearInterval(handle)
  164. }, 100)
  165. })();