commit 2e1b7d5c8a0a40d553ea6e2f3e552800f16bb123 Author: fan Date: Mon Jul 3 13:16:08 2023 +0800 代码提交 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9d08a1a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..7b59e09 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,7 @@ +/dist +/src-capacitor +/src-cordova +/.quasar +/node_modules +.eslintrc.js +/src-ssr diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..796b2e8 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,90 @@ +module.exports = { + // https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy + // This option interrupts the configuration hierarchy at this file + // Remove this if you have an higher level ESLint config file (it usually happens into a monorepos) + root: true, + + // https://eslint.vuejs.org/user-guide/#how-to-use-a-custom-parser + // Must use parserOptions instead of "parser" to allow vue-eslint-parser to keep working + // `parser: 'vue-eslint-parser'` is already included with any 'plugin:vue/**' config and should be omitted + parserOptions: { + parser: require.resolve('@typescript-eslint/parser'), + extraFileExtensions: [ '.vue' ] + }, + + env: { + browser: true, + es2021: true, + node: true, + 'vue/setup-compiler-macros': true + }, + + // Rules order is important, please avoid shuffling them + extends: [ + // Base ESLint recommended rules + // 'eslint:recommended', + + // https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#usage + // ESLint typescript rules + 'plugin:@typescript-eslint/recommended', + + // Uncomment any of the lines below to choose desired strictness, + // but leave only one uncommented! + // See https://eslint.vuejs.org/rules/#available-rules + 'plugin:vue/vue3-essential', // Priority A: Essential (Error Prevention) + // 'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability) + // 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead) + + // https://github.com/prettier/eslint-config-prettier#installation + // usage with Prettier, provided by 'eslint-config-prettier'. + 'prettier' + ], + + plugins: [ + // required to apply rules which need type information + '@typescript-eslint', + + // https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-files + // required to lint *.vue files + 'vue' + + // https://github.com/typescript-eslint/typescript-eslint/issues/389#issuecomment-509292674 + // Prettier has not been included as plugin to avoid performance impact + // add it as an extension for your IDE + + ], + + globals: { + ga: 'readonly', // Google Analytics + cordova: 'readonly', + __statics: 'readonly', + __QUASAR_SSR__: 'readonly', + __QUASAR_SSR_SERVER__: 'readonly', + __QUASAR_SSR_CLIENT__: 'readonly', + __QUASAR_SSR_PWA__: 'readonly', + process: 'readonly', + Capacitor: 'readonly', + chrome: 'readonly' + }, + + // add your custom rules here + rules: { + + 'prefer-promise-reject-errors': 'off', + + quotes: ['warn', 'single', { avoidEscape: true }], + + // this rule, if on, would require explicit return type on the `render` function + '@typescript-eslint/explicit-function-return-type': 'off', + + // in plain CommonJS modules, you can't use `import foo = require('foo')` to pass this rule, so it has to be disabled + '@typescript-eslint/no-var-requires': 'off', + + // The core 'no-unused-vars' rules (in the eslint:recommended ruleset) + // does not work with type definitions + 'no-unused-vars': 'off', + + // allow debugger during development only + 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..553e134 --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +.DS_Store +.thumbs.db +node_modules + +# Quasar core related directories +.quasar +/dist + +# Cordova related directories and files +/src-cordova/node_modules +/src-cordova/platforms +/src-cordova/plugins +/src-cordova/www + +# Capacitor related directories and files +/src-capacitor/www +/src-capacitor/node_modules + +# BEX related directories and files +/src-bex/www +/src-bex/js/core + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Editor directories and files +.idea +*.suo +*.ntvs* +*.njsproj +*.sln diff --git a/.gitmodule b/.gitmodule new file mode 100644 index 0000000..0f4cb2d --- /dev/null +++ b/.gitmodule @@ -0,0 +1,2 @@ +[submodule "graphic-pixi"] + branch = bj-rtss diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..2eba59a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,7 @@ +[submodule "bj-rtss-message"] + path = bj-rtss-message + url = https://git.code.tencent.com/beijing-rtss-test/bj-rtss-message.git +[submodule "graphic-pixi"] + path = graphic-pixi + url = https://git.code.tencent.com/jl-framework/graphic-pixi.git + branch = bj-rtss diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..32bd84d --- /dev/null +++ b/.npmrc @@ -0,0 +1,3 @@ +# pnpm-related options +shamefully-hoist=true +strict-peer-dependencies=false diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..650cb88 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "semi": true +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..fe38802 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,15 @@ +{ + "recommendations": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "editorconfig.editorconfig", + "vue.volar", + "wayou.vscode-todo-highlight" + ], + "unwantedRecommendations": [ + "octref.vetur", + "hookyqr.beautify", + "dbaeumer.jshint", + "ms-vscode.vscode-typescript-tslint-plugin" + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..746cf57 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,16 @@ +{ + "editor.bracketPairColorization.enabled": true, + "editor.guides.bracketPairs": true, + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.codeActionsOnSave": [ + "source.fixAll.eslint" + ], + "eslint.validate": [ + "javascript", + "javascriptreact", + "typescript", + "vue" + ], + "typescript.tsdk": "node_modules/typescript/lib" +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..b725997 --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +# BjRtssClient (bj-rtss-client) + +beijing rtss 测试系统 + +## 项目 clone 说明 + +此项目包含子模块,拉取方式: + +- 1.在克隆主项目的时候带上参数 --recurse-submodules +- 2.或者 clone 完成后,在项目目录中执行:git submodule init && git submodule update + +## 安装依赖 + +```bash +yarn +# or +npm install +``` + +## 编译 proto 文件 + +```bash +yarn run proto +# or +npm run proto +``` + +### Start the app in development mode (hot-code reloading, error reporting, etc.) + +```bash +quasar dev +# or +yarn run dev +# or +npm run dev +``` + +### Lint the files + +```bash +yarn lint +# or +npm run lint +``` + +### Format the files + +```bash +yarn format +# or +npm run format +``` + +### Build the app for production + +```bash +quasar build +``` + +### Customize the configuration + +See [Configuring quasar.config.js](https://v2.quasar.dev/quasar-cli-vite/quasar-config-js). diff --git a/graphic-pixi b/graphic-pixi new file mode 160000 index 0000000..7e4eaed --- /dev/null +++ b/graphic-pixi @@ -0,0 +1 @@ +Subproject commit 7e4eaed0cf06d68c75cb51c30329eff5fe4d1e3f diff --git a/index.html b/index.html new file mode 100644 index 0000000..3c8c78f --- /dev/null +++ b/index.html @@ -0,0 +1,21 @@ + + + + <%= productName %> + + + + + + + + + + + + + + + + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..d6f2c59 --- /dev/null +++ b/package.json @@ -0,0 +1,52 @@ +{ + "name": "bj-rtss-client", + "version": "0.0.1", + "description": "beijing rtss 测试系统", + "productName": "BJRTSSCLIENT", + "author": "walker ", + "private": true, + "scripts": { + "lint": "eslint --ext .js,.ts,.vue ./", + "format": "prettier --write \"**/*.{js,ts,vue,scss,html,md,json}\" --ignore-path .gitignore", + "test": "echo \"No test specified\" && exit 0", + "dev": "quasar dev", + "build": "quasar build", + "protoc": "node scripts/proto.cjs", + "sync": "node scripts/sync.cjs" + }, + "dependencies": { + "@pixi/filter-outline": "^5.2.0", + "@pixi/graphics-extras": "^7.2.4", + "@quasar/extras": "^1.0.0", + "@stomp/stompjs": "^7.0.0", + "axios": "^1.2.1", + "google-protobuf": "^3.21.2", + "js-base64": "^3.7.5", + "pinia": "^2.0.11", + "pixi-viewport": "^5.0.1", + "pixi.js": "^7.2.4", + "quasar": "^2.6.0", + "vue": "^3.0.0", + "vue-router": "^4.0.0" + }, + "devDependencies": { + "@quasar/app-vite": "^1.0.0", + "@types/google-protobuf": "^3.15.6", + "@types/node": "^12.20.21", + "@typescript-eslint/eslint-plugin": "^5.10.0", + "@typescript-eslint/parser": "^5.10.0", + "autoprefixer": "^10.4.2", + "eslint": "^8.10.0", + "eslint-config-prettier": "^8.1.0", + "eslint-plugin-vue": "^9.0.0", + "prettier": "^2.5.1", + "protoc-gen-ts": "^0.8.6", + "ts-md5": "^1.3.1", + "typescript": "^4.5.4" + }, + "engines": { + "node": "^18 || ^16 || ^14.19", + "npm": ">= 6.13.4", + "yarn": ">= 1.21.1" + } +} diff --git a/postcss.config.cjs b/postcss.config.cjs new file mode 100644 index 0000000..94b7b1c --- /dev/null +++ b/postcss.config.cjs @@ -0,0 +1,27 @@ +/* eslint-disable */ +// https://github.com/michael-ciniawsky/postcss-load-config + +module.exports = { + plugins: [ + // https://github.com/postcss/autoprefixer + require('autoprefixer')({ + overrideBrowserslist: [ + 'last 4 Chrome versions', + 'last 4 Firefox versions', + 'last 4 Edge versions', + 'last 4 Safari versions', + 'last 4 Android versions', + 'last 4 ChromeAndroid versions', + 'last 4 FirefoxAndroid versions', + 'last 4 iOS versions' + ] + }) + + // https://github.com/elchininet/postcss-rtlcss + // If you want to support RTL css, then + // 1. yarn/npm install postcss-rtlcss + // 2. optionally set quasar.config.js > framework > lang to an RTL language + // 3. uncomment the following line: + // require('postcss-rtlcss') + ] +} diff --git a/public/drawIcon.svg b/public/drawIcon.svg new file mode 100644 index 0000000..e6ff62e --- /dev/null +++ b/public/drawIcon.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..ae7bbdb Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/icons/favicon-128x128.png b/public/icons/favicon-128x128.png new file mode 100644 index 0000000..1401176 Binary files /dev/null and b/public/icons/favicon-128x128.png differ diff --git a/public/icons/favicon-16x16.png b/public/icons/favicon-16x16.png new file mode 100644 index 0000000..679063a Binary files /dev/null and b/public/icons/favicon-16x16.png differ diff --git a/public/icons/favicon-32x32.png b/public/icons/favicon-32x32.png new file mode 100644 index 0000000..fd1fbc6 Binary files /dev/null and b/public/icons/favicon-32x32.png differ diff --git a/public/icons/favicon-96x96.png b/public/icons/favicon-96x96.png new file mode 100644 index 0000000..e93b80a Binary files /dev/null and b/public/icons/favicon-96x96.png differ diff --git a/quasar.config.js b/quasar.config.js new file mode 100644 index 0000000..00a1002 --- /dev/null +++ b/quasar.config.js @@ -0,0 +1,213 @@ +/* eslint-env node */ + +/* + * This file runs in a Node context (it's NOT transpiled by Babel), so use only + * the ES6 features that are supported by your Node version. https://node.green/ + */ + +// Configuration for your app +// https://v2.quasar.dev/quasar-cli-vite/quasar-config-js + +const { configure } = require('quasar/wrappers'); + +const BasePath = 'bjrtss'; + +module.exports = configure(function (/* ctx */) { + return { + eslint: { + // fix: true, + // include: [], + // exclude: [], + // rawOptions: {}, + warnings: true, + errors: true, + exclude: ['src/protos/*'], + }, + + // https://v2.quasar.dev/quasar-cli-vite/prefetch-feature + // preFetch: true, + + // app boot file (/src/boot) + // --> boot files are part of "main.js" + // https://v2.quasar.dev/quasar-cli-vite/boot-files + boot: ['axios', '@pixi/graphics-extras'], + + // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css + css: ['app.scss'], + + // https://github.com/quasarframework/quasar/tree/dev/extras + extras: [ + // 'ionicons-v4', + // 'mdi-v5', + // 'fontawesome-v6', + // 'eva-icons', + // 'themify', + // 'line-awesome', + // 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both! + + 'roboto-font', // optional, you are not bound to it + 'material-icons', // optional, you are not bound to it + 'material-symbols-outlined', + ], + + // Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#build + build: { + target: { + browser: ['es2019', 'edge88', 'firefox78', 'chrome87', 'safari13.1'], + node: 'node16', + }, + + vueRouterMode: 'history', // available values: 'hash', 'history' + vueRouterBase: BasePath, + // vueDevtools, + // vueOptionsAPI: false, + + // rebuildCache: true, // rebuilds Vite/linter/etc cache on startup + + publicPath: BasePath, + // analyze: true, + // env: {}, + // rawDefine: {} + // ignorePublicFolder: true, + // minify: false, + // polyfillModulePreload: true, + // distDir + // distDir: `dist/${BasePath}`, + + // extendViteConf (viteConf) {}, + // viteVuePluginOptions: {}, + + // vitePlugins: [ + // [ 'package-name', { ..options.. } ] + // ] + }, + + // Full list of options: https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#devServer + devServer: { + // https: true + open: true, // opens browser window automatically + base: BasePath, + }, + + // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#framework + framework: { + config: { + notify: { + position: 'top', + timeout: 2000, + progress: true, + }, + }, + + // iconSet: 'material-icons', // Quasar icon set + // lang: 'en-US', // Quasar language pack + lang: 'zh-CN', + + // For special cases outside of where the auto-import strategy can have an impact + // (like functional components as one of the examples), + // you can manually specify Quasar components/directives to be available everywhere: + // + // components: [], + // directives: [], + + // Quasar plugins + plugins: ['Notify', 'Dialog', 'Dark', 'AppFullscreen', 'Loading'], + }, + + // animations: 'all', // --- includes all animations + // https://v2.quasar.dev/options/animations + animations: [], + + // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#sourcefiles + // sourceFiles: { + // rootComponent: 'src/App.vue', + // router: 'src/router/index', + // store: 'src/store/index', + // registerServiceWorker: 'src-pwa/register-service-worker', + // serviceWorker: 'src-pwa/custom-service-worker', + // pwaManifestFile: 'src-pwa/manifest.json', + // electronMain: 'src-electron/electron-main', + // electronPreload: 'src-electron/electron-preload' + // }, + + // https://v2.quasar.dev/quasar-cli-vite/developing-ssr/configuring-ssr + ssr: { + // ssrPwaHtmlFilename: 'offline.html', // do NOT use index.html as name! + // will mess up SSR + + // extendSSRWebserverConf (esbuildConf) {}, + // extendPackageJson (json) {}, + + pwa: false, + + // manualStoreHydration: true, + // manualPostHydrationTrigger: true, + + prodPort: 3000, // The default port that the production server should use + // (gets superseded if process.env.PORT is specified at runtime) + + middlewares: [ + 'render', // keep this as last one + ], + }, + + // https://v2.quasar.dev/quasar-cli-vite/developing-pwa/configuring-pwa + pwa: { + workboxMode: 'generateSW', // or 'injectManifest' + injectPwaMetaTags: true, + swFilename: 'sw.js', + manifestFilename: 'manifest.json', + useCredentialsForManifestTag: false, + // useFilenameHashes: true, + // extendGenerateSWOptions (cfg) {} + // extendInjectManifestOptions (cfg) {}, + // extendManifestJson (json) {} + // extendPWACustomSWConf (esbuildConf) {} + }, + + // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-cordova-apps/configuring-cordova + cordova: { + // noIosLegacyBuildFlag: true, // uncomment only if you know what you are doing + }, + + // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-capacitor-apps/configuring-capacitor + capacitor: { + hideSplashscreen: true, + }, + + // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-electron-apps/configuring-electron + electron: { + // extendElectronMainConf (esbuildConf) + // extendElectronPreloadConf (esbuildConf) + + inspectPort: 5858, + + bundler: 'packager', // 'packager' or 'builder' + + packager: { + // https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options + // OS X / Mac App Store + // appBundleId: '', + // appCategoryType: '', + // osxSign: '', + // protocol: 'myapp://path', + // Windows only + // win32metadata: { ... } + }, + + builder: { + // https://www.electron.build/configuration/configuration + + appId: 'bj-rtss-client', + }, + }, + + // Full list of options: https://v2.quasar.dev/quasar-cli-vite/developing-browser-extensions/configuring-bex + bex: { + contentScripts: ['my-content-script'], + + // extendBexScriptsConf (esbuildConf) {} + // extendBexManifestJson (json) {} + }, + }; +}); diff --git a/scripts/proto.cjs b/scripts/proto.cjs new file mode 100644 index 0000000..90b41ad --- /dev/null +++ b/scripts/proto.cjs @@ -0,0 +1,91 @@ +/** + * 将proto文件编译到 src/proto/ + */ +const { readdirSync } = require('fs'); +const { resolve } = require('path'); +const os = require('os'); + +const { exec } = require('child_process'); + +const messageDir = resolve(__dirname, '../bj-rtss-message'); +const protoDir = resolve(messageDir, 'protos'); +const destDir = resolve(__dirname, '../src/protos'); + +/** + * 递归处理所有proto文件生成 + * @param {*} file 文件 + * @param {*} path 目录 + */ +function recursiveGenerate(file, path = [], cmds = []) { + if (file.isFile()) { + // 文件,生成 + if (file.name.endsWith('.proto')) { + cmds.push(buildGenerateCmd(file.name, path)); + } else { + console.warn('不是proto文件', file.name); + } + } else if (file.isDirectory()) { + // 文件夹,递归 + readdirSync(resolve(protoDir, ...path, file.name), { + withFileTypes: true, + }).forEach((f) => { + const subPath = [...path, file.name]; + recursiveGenerate(f, subPath, cmds); + }); + } +} + +const isLinux = os.type().toLowerCase().includes('linux'); + +function buildGenerateCmd(name, path = []) { + const protoPath = resolve(protoDir, ...path); + const tsPath = resolve(destDir, ...path); + + let cmd = ['protoc', `-I=${protoPath}`, `--ts_out=${tsPath}`, `${name}`]; + let cmdStr = cmd.join(' '); + return cmdStr; +} + +function main() { + const protocDir = resolve(messageDir, 'protoc-23.1'); + const protocBin = resolve( + protocDir, + `bin/${isLinux ? 'linux-x86_64' : 'win64'}` + ); + const prepareCmds = []; + const setPathCmd = isLinux + ? ['export', `PATH=${protocBin}:${protocDir}:"$PATH"`].join(' ') + : ['set', `PATH=${protocBin};${protocDir};%PATH%`].join(' '); + const protocVersionCmd = ['protoc', '--version'].join(' '); + prepareCmds.push(setPathCmd); + prepareCmds.push(protocVersionCmd); + + readdirSync(protoDir, { + withFileTypes: true, + }).forEach((f) => { + recursiveGenerate(f, [], prepareCmds); + }); + + console.log(prepareCmds); + + exec( + prepareCmds.join(' && '), + { + maxBuffer: 1024 * 2000, + }, + (err, stdout, stderr) => { + if (err) { + console.error(err); + throw err; + } else if (stderr.length > 0) { + console.error(stderr.toString()); + throw new Error(stderr.toString()); + } else { + console.log(stdout); + } + } + ); +} + +// 执行 +main(); diff --git a/scripts/sync.cjs b/scripts/sync.cjs new file mode 100644 index 0000000..a8fc918 --- /dev/null +++ b/scripts/sync.cjs @@ -0,0 +1,70 @@ +/** + * 同步图形框架文件到 src/jl-graphic/ + */ +const { + readdirSync, + existsSync, + copyFileSync, + mkdirSync, + rmSync, +} = require('fs'); +const { resolve } = require('path'); + +const jlGraphicSrcPath = resolve(__dirname, '../graphic-pixi/src/jlgraphic'); +const jlGraphicLibPath = resolve(__dirname, '../src/jl-graphic'); + +/** + * 检查并初始化当前项目引入的jl-graphic库 + */ +function checkAndInitJlGraphicLib() { + const exist = existsSync(jlGraphicLibPath); + if (exist) { + console.log('jl-graphic文件夹已存在,清空'); + readdirSync(jlGraphicLibPath, { + withFileTypes: true, + }).forEach((file) => { + if (file.isDirectory()) { + rmSync(resolve(jlGraphicLibPath, file.name), { recursive: true }); + } else { + rmSync(resolve(jlGraphicLibPath, file.name)); + } + }); + } else { + console.log('jl-graphic文件夹不存在,创建'); + // 文件夹不存在,创建 + mkdirSync(jlGraphicLibPath); + } +} + +function copyJlGraphicFiles() { + readdirSync(jlGraphicSrcPath, { + withFileTypes: true, + }).forEach((file) => { + recursiveCopyFiles(file); + }); +} + +function recursiveCopyFiles(file, path = []) { + if (file.isFile()) { + const fileSrcPath = resolve(jlGraphicSrcPath, ...path, file.name); + const fileDestPath = resolve(jlGraphicLibPath, ...path, file.name); + console.log(`copy file ${fileSrcPath} -> ${fileDestPath}`); + copyFileSync(fileSrcPath, fileDestPath); + } else if (file.isDirectory()) { + const srcDir = resolve(jlGraphicSrcPath, ...path, file.name); + const dirPath = resolve(jlGraphicLibPath, ...path, file.name); + mkdirSync(dirPath); + readdirSync(srcDir, { + withFileTypes: true, + }).forEach((subFile) => { + recursiveCopyFiles(subFile, [...path, file.name]); + }); + } +} + +function main() { + checkAndInitJlGraphicLib(); + copyJlGraphicFiles(); +} + +main(); diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..fe0a246 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,7 @@ + + + diff --git a/src/api/ApiCommon.ts b/src/api/ApiCommon.ts new file mode 100644 index 0000000..18494ce --- /dev/null +++ b/src/api/ApiCommon.ts @@ -0,0 +1,42 @@ +export class PageQueryDto { + current: number; + size: number; + orders?: OrderItemDto[]; + constructor(current: number, size: number, orders?: OrderItemDto[]) { + this.current = current; + this.size = size; + this.orders = orders; + } +} + +export class OrderItemDto { + column: string; + asc: boolean; + constructor(column: string, asc: boolean) { + this.column = column; + this.asc = asc; + } + + static asc(column: string): OrderItemDto { + return new OrderItemDto(column, true); + } + static desc(column: string): OrderItemDto { + return new OrderItemDto(column, false); + } +} + +export interface PageDto { + records: T[]; + /** + * 记录总数 + */ + total: number; + /** + * 第几页 + */ + current: number; + /** + * 每页数量 + */ + size: number; +} diff --git a/src/api/DraftApi.ts b/src/api/DraftApi.ts new file mode 100644 index 0000000..92970da --- /dev/null +++ b/src/api/DraftApi.ts @@ -0,0 +1,86 @@ +import { api } from 'src/boot/axios'; +import { PageDto, PageQueryDto } from './ApiCommon'; + +const DraftUriBase = '/api/drafting'; + +interface Item { + id: number; + name: string; + proto: string; + type: string; + createdAt: string; + updateAt: string; + creatorId?: number; +} + +export class PagingQueryParams extends PageQueryDto { + name?: string; +} + +/** + * 分页查询 + * @param params + * @returns + */ +export async function pageQuery( + params: PagingQueryParams +): Promise> { + const response = await api.get(`${DraftUriBase}/paging`, { + params: params, + }); + return response.data; +} + +/** + * 创建草稿 + * @param params + * @returns + */ +export function createDraft(draftData: { name: string; type: string }) { + return api.post(`${DraftUriBase}`, draftData); +} + +/** + * 删除草稿 + * @param id 草稿id + */ +export function deleteDraft(id: number) { + return api.delete(`${DraftUriBase}/${id}`); +} + +/** + * 获取草稿数据 + * @param params + * @returns + */ +export async function getDraft(id: number): Promise { + const response = await api.get(`${DraftUriBase}/${id}`); + return response.data; +} + +/** + * 保存草稿数据 + * @param data + * @returns + */ +export function saveDraft( + id: number, + data: { + proto: string; + } +) { + return api.put(`${DraftUriBase}/${id}`, data); +} + +/** + * 另存草稿数据 + * @param data + * @returns + */ +export async function saveAsDraft( + id: number, + data: { name: string; proto: string } +): Promise { + const response = await api.post(`${DraftUriBase}/${id}/saveAs`, data); + return response.data; +} diff --git a/src/api/LineInfoApi.ts b/src/api/LineInfoApi.ts new file mode 100644 index 0000000..a2c5fb2 --- /dev/null +++ b/src/api/LineInfoApi.ts @@ -0,0 +1,79 @@ +import { api } from 'src/boot/axios'; +import { PageDto, PageQueryDto } from './ApiCommon'; + +const UriBase = '/api/lineInfo'; + +export interface createParams { + name: string; + lineId: number; + config?: string; +} + +interface Item extends createParams { + id: number; + createdAt: string; + updateAt: string; +} + +export class PagingQueryParams extends PageQueryDto { + name?: string; +} + +/** + * 分页查询 + * @param params + * @returns + */ +export async function pageQuery( + params: PagingQueryParams +): Promise> { + const response = await api.get(`${UriBase}/paging`, { + params: params, + }); + return response.data; +} + +/** + * 创建线路 + * @param params + * @returns + */ +export function createLine(data: createParams) { + return api.post(`${UriBase}`, data); +} + +/** + * 删除线路 + * @param id 线路id + */ +export function deleteLine(id: number) { + return api.delete(`${UriBase}/${id}`); +} + +/** + * 保存线路数据 + * @param id 草稿id + */ +export function saveLineData(id: number, data: createParams) { + return api.put(`${UriBase}/${id}`, data); +} + +/** + * 获取线路数据详情 + * @param params + * @returns + */ +export async function getLineInfo(id: number): Promise { + const response = await api.get(`${UriBase}/${id}`); + return response.data; +} + +/** + * 获取线路信息列表 + * @param params + * @returns + */ +export async function getLineList(): Promise> { + const response = await api.get(`${UriBase}/list`); + return response.data; +} diff --git a/src/api/PublishApi.ts b/src/api/PublishApi.ts new file mode 100644 index 0000000..db1f1c3 --- /dev/null +++ b/src/api/PublishApi.ts @@ -0,0 +1,89 @@ +import { api } from 'src/boot/axios'; +import { PageDto, PageQueryDto } from './ApiCommon'; + +const PublishUriBase = '/api/publishedGi'; + +interface Item { + id: number; + name: string; + proto: string; + createdAt: string; + updateAt: string; + creatorId?: number; +} + +export class PagingQueryParams extends PageQueryDto { + name?: string; +} + +/** + * 草稿图发布 + * @param id 草稿id + */ +export function publishDraft(data: { + name: string; + lineId?: number; + draftingId: number; +}) { + return api.post(`${PublishUriBase}/publish`, data); +} + +/** + * 获取发布图形数据列表 + * @param params + * @returns + */ +export async function getDraft(): Promise { + const response = await api.get(`${PublishUriBase}/list`); + return response.data; +} + +/** + * 分页查询 + * @param params + * @returns + */ +export async function pageQuery( + params: PagingQueryParams +): Promise> { + const response = await api.get(`${PublishUriBase}/paging`, { + params: params, + }); + return response.data; +} + +/** + * 删除发布图 + * @param id 草稿id + */ +export function deletePublish(id: number) { + return api.delete(`${PublishUriBase}/${id}`); +} +/** + * 获取发布地图详细信息 + * @param id 发布地图id + */ +export async function getPublishMapInfoById(id: number): Promise { + const response = await api.get(`${PublishUriBase}/${id}`); + return response.data; +} +/** + * 获取已发布的线路地图数据 + */ +export async function getPublishLineNet(): Promise { + const response = await api.get(`${PublishUriBase}/publish/lineNetwork/info`); + return response.data; +} + +/** + * 获取发布地图详细信息 + * @param id 发布地图线路ID + * @param type 发布地图线路类型 + */ +export async function getPublishMapInfoByLineId( + lineId: number, + type: string +): Promise { + const response = await api.get(`${PublishUriBase}/${type}/${lineId}`); + return response.data; +} diff --git a/src/api/UserApi.ts b/src/api/UserApi.ts new file mode 100644 index 0000000..085fe3f --- /dev/null +++ b/src/api/UserApi.ts @@ -0,0 +1,77 @@ +import { api } from 'src/boot/axios'; +import { PageDto, PageQueryDto } from './ApiCommon'; +import { Md5 } from 'ts-md5'; + +const UserUriBase = '/api/user'; + +interface RegisterInfo { + name: string; + mobile: string; + password: string; +} + +interface User { + id: string; + name: string; + mobile: string; + password: string; + registerTime: string; +} + +const PasswordSult = '4a6d74126bfd06d69406fcccb7e7d5d9'; // 密码加盐 +function encryptPassword(password: string): string { + const md5 = new Md5(); + return md5.appendStr(`${password}${PasswordSult}`).end() as string; +} + +/** + * 用户注册 + * @param info + * @returns + */ +export async function register(info: RegisterInfo): Promise { + const response = await api.post(`${UserUriBase}/register`, { + ...info, + password: encryptPassword(info.password), + }); + return response.data as User; +} + +interface LoginInfo { + account: string; + password: string; +} + +/** + * 用户登录 + * @param loginInfo + * @returns + */ +export async function login(loginInfo: LoginInfo): Promise { + const info = { ...loginInfo, password: encryptPassword(loginInfo.password) }; + const response = await api.post(`${UserUriBase}/login`, info); + return response.data; +} + +export class PagingQueryParams extends PageQueryDto { + name?: string; + roleId?: number; +} + +/** + * 分页查询用户信息 + * @param params + * @returns + */ +export async function pageQuery( + params: PagingQueryParams +): Promise> { + const response = await api.get(`${UserUriBase}/paging`, { + params: params, + }); + return response.data; +} + +export function distributeRole(query: { userId: number; roleIds: number[] }) { + return api.post('/api/role/distribute', query); +} diff --git a/src/assets/quasar-logo-vertical.svg b/src/assets/quasar-logo-vertical.svg new file mode 100644 index 0000000..8210831 --- /dev/null +++ b/src/assets/quasar-logo-vertical.svg @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/boot/.gitkeep b/src/boot/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/boot/@pixi/graphics-extras.ts b/src/boot/@pixi/graphics-extras.ts new file mode 100644 index 0000000..4a70eb8 --- /dev/null +++ b/src/boot/@pixi/graphics-extras.ts @@ -0,0 +1,7 @@ +import { boot } from 'quasar/wrappers'; +import * as GraphicsExtras from '@pixi/graphics-extras'; +// "async" is optional; +// more info on params: https://v2.quasar.dev/quasar-cli/boot-files +export default boot(async (/* { app, router, ... } */) => { + GraphicsExtras; +}); diff --git a/src/boot/axios.ts b/src/boot/axios.ts new file mode 100644 index 0000000..3fe93a6 --- /dev/null +++ b/src/boot/axios.ts @@ -0,0 +1,111 @@ +import axios, { AxiosInstance } from 'axios'; +import { AxiosError } from 'axios'; +import { Dialog } from 'quasar'; +import { boot } from 'quasar/wrappers'; +import { getJwtToken } from 'src/configs/TokenManage'; +import { getHttpBase } from 'src/configs/UrlManage'; + +declare module '@vue/runtime-core' { + interface ComponentCustomProperties { + $axios: AxiosInstance; + } +} + +interface ErrorData { + status: number; + title: string; + detail: string; + code: number; +} + +export class ApiError { + origin: AxiosError; + /** + * 业务错误代码 + */ + code: number; + /** + * 错误信息 + */ + title: string; + /** + * 相关问题描述 + */ + detail?: string; + constructor(origin: AxiosError) { + this.origin = origin; + const response = origin.response; + if (response) { + const err = response.data as ErrorData; + this.code = err.code; + this.title = err.title; + this.detail = err.detail; + } else { + this.code = origin.status || -1; + this.title = origin.message; + } + } + + static from(err: AxiosError): ApiError { + return new ApiError(err); + } + + /** + * 是否认证失败(登录过期) + * @returns + */ + isAuthError(): boolean { + return this.origin.response?.status === 401; + } +} + +// Be careful when using SSR for cross-request state pollution +// due to creating a Singleton instance here; +// If any client changes this (global) instance, it might be a +// good idea to move this instance creation inside of the +// "export default () => {}" function below (which runs individually +// for each client) +const api = axios.create({ baseURL: getHttpBase() }); + +export default boot(({ app, router }) => { + // for use inside Vue files (Options API) through this.$axios and this.$api + + // 拦截请求,添加 + api.interceptors.request.use( + (config) => { + config.headers.Authorization = getJwtToken(); + return config; + }, + (err: AxiosError) => { + return Promise.reject(ApiError.from(err)); + } + ); + + api.interceptors.response.use( + (response) => { + return response; + }, + (err) => { + if (err.response && err.response.status === 401) { + Dialog.create({ + title: '认证失败', + message: '认证失败或登录超时,请重新登录', + persistent: true, + }).onOk(() => { + router.push({ name: 'login' }); + }); + } + return Promise.reject(ApiError.from(err)); + } + ); + + app.config.globalProperties.$axios = axios; + // ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form) + // so you won't necessarily have to import axios in each vue file + + app.config.globalProperties.$api = api; + // ^ ^ ^ this will allow you to use this.$api (for Vue Options API form) + // so you can easily perform requests against your app's API +}); + +export { api }; diff --git a/src/components/SysMenu.vue b/src/components/SysMenu.vue new file mode 100644 index 0000000..cd3d17e --- /dev/null +++ b/src/components/SysMenu.vue @@ -0,0 +1,85 @@ + + + diff --git a/src/components/draw-app/DrawProperties.vue b/src/components/draw-app/DrawProperties.vue new file mode 100644 index 0000000..31f4a2b --- /dev/null +++ b/src/components/draw-app/DrawProperties.vue @@ -0,0 +1,133 @@ + + + diff --git a/src/components/draw-app/properties/AxleCountingProperty.vue b/src/components/draw-app/properties/AxleCountingProperty.vue new file mode 100644 index 0000000..c503ea4 --- /dev/null +++ b/src/components/draw-app/properties/AxleCountingProperty.vue @@ -0,0 +1,164 @@ + + + diff --git a/src/components/draw-app/properties/CanvasProperty.vue b/src/components/draw-app/properties/CanvasProperty.vue new file mode 100644 index 0000000..e5d4f11 --- /dev/null +++ b/src/components/draw-app/properties/CanvasProperty.vue @@ -0,0 +1,80 @@ + + + diff --git a/src/components/draw-app/properties/IscsFanProperty.vue b/src/components/draw-app/properties/IscsFanProperty.vue new file mode 100644 index 0000000..95e1d3d --- /dev/null +++ b/src/components/draw-app/properties/IscsFanProperty.vue @@ -0,0 +1,42 @@ + + + diff --git a/src/components/draw-app/properties/LinkProperty.vue b/src/components/draw-app/properties/LinkProperty.vue new file mode 100644 index 0000000..e6d9b89 --- /dev/null +++ b/src/components/draw-app/properties/LinkProperty.vue @@ -0,0 +1,96 @@ + + + diff --git a/src/components/draw-app/properties/PathLineProperty.vue b/src/components/draw-app/properties/PathLineProperty.vue new file mode 100644 index 0000000..75c6c5e --- /dev/null +++ b/src/components/draw-app/properties/PathLineProperty.vue @@ -0,0 +1,91 @@ + + diff --git a/src/components/draw-app/properties/PlatformProperty.vue b/src/components/draw-app/properties/PlatformProperty.vue new file mode 100644 index 0000000..dd085c6 --- /dev/null +++ b/src/components/draw-app/properties/PlatformProperty.vue @@ -0,0 +1,75 @@ + + + diff --git a/src/components/draw-app/properties/RectProperty.vue b/src/components/draw-app/properties/RectProperty.vue new file mode 100644 index 0000000..d1ec7a3 --- /dev/null +++ b/src/components/draw-app/properties/RectProperty.vue @@ -0,0 +1,100 @@ + + + diff --git a/src/components/draw-app/properties/RunLineProperty.vue b/src/components/draw-app/properties/RunLineProperty.vue new file mode 100644 index 0000000..7183905 --- /dev/null +++ b/src/components/draw-app/properties/RunLineProperty.vue @@ -0,0 +1,189 @@ + + + diff --git a/src/components/draw-app/properties/SectionProperty.vue b/src/components/draw-app/properties/SectionProperty.vue new file mode 100644 index 0000000..12695da --- /dev/null +++ b/src/components/draw-app/properties/SectionProperty.vue @@ -0,0 +1,132 @@ + + + diff --git a/src/components/draw-app/properties/SeparatorProperty.vue b/src/components/draw-app/properties/SeparatorProperty.vue new file mode 100644 index 0000000..f5434d9 --- /dev/null +++ b/src/components/draw-app/properties/SeparatorProperty.vue @@ -0,0 +1,57 @@ + + + diff --git a/src/components/draw-app/properties/SignalProperty.vue b/src/components/draw-app/properties/SignalProperty.vue new file mode 100644 index 0000000..d3bf4e4 --- /dev/null +++ b/src/components/draw-app/properties/SignalProperty.vue @@ -0,0 +1,85 @@ + + + diff --git a/src/components/draw-app/properties/StationLineProperty.vue b/src/components/draw-app/properties/StationLineProperty.vue new file mode 100644 index 0000000..004d3dc --- /dev/null +++ b/src/components/draw-app/properties/StationLineProperty.vue @@ -0,0 +1,87 @@ + + + diff --git a/src/components/draw-app/properties/StationProperty.vue b/src/components/draw-app/properties/StationProperty.vue new file mode 100644 index 0000000..8742bd1 --- /dev/null +++ b/src/components/draw-app/properties/StationProperty.vue @@ -0,0 +1,127 @@ + + + diff --git a/src/components/draw-app/properties/TrainProperty.vue b/src/components/draw-app/properties/TrainProperty.vue new file mode 100644 index 0000000..e47f4ee --- /dev/null +++ b/src/components/draw-app/properties/TrainProperty.vue @@ -0,0 +1,84 @@ + + + diff --git a/src/components/draw-app/properties/TrainWindowProperty.vue b/src/components/draw-app/properties/TrainWindowProperty.vue new file mode 100644 index 0000000..9ba3067 --- /dev/null +++ b/src/components/draw-app/properties/TrainWindowProperty.vue @@ -0,0 +1,86 @@ + + + diff --git a/src/components/draw-app/properties/TurnoutProperty.vue b/src/components/draw-app/properties/TurnoutProperty.vue new file mode 100644 index 0000000..2944975 --- /dev/null +++ b/src/components/draw-app/properties/TurnoutProperty.vue @@ -0,0 +1,149 @@ + + + diff --git a/src/components/draw-app/templates/LinkTemplate.vue b/src/components/draw-app/templates/LinkTemplate.vue new file mode 100644 index 0000000..a6b82a1 --- /dev/null +++ b/src/components/draw-app/templates/LinkTemplate.vue @@ -0,0 +1,96 @@ + + + diff --git a/src/components/draw-app/templates/PlatformTemplate.vue b/src/components/draw-app/templates/PlatformTemplate.vue new file mode 100644 index 0000000..75c2ee2 --- /dev/null +++ b/src/components/draw-app/templates/PlatformTemplate.vue @@ -0,0 +1,76 @@ + + + diff --git a/src/components/draw-app/templates/RectTemplate.vue b/src/components/draw-app/templates/RectTemplate.vue new file mode 100644 index 0000000..75c2ee2 --- /dev/null +++ b/src/components/draw-app/templates/RectTemplate.vue @@ -0,0 +1,76 @@ + + + diff --git a/src/components/draw-app/templates/StationTemplate.vue b/src/components/draw-app/templates/StationTemplate.vue new file mode 100644 index 0000000..fe433bf --- /dev/null +++ b/src/components/draw-app/templates/StationTemplate.vue @@ -0,0 +1,70 @@ + + + diff --git a/src/components/draw-app/templates/TrainTemplate.vue b/src/components/draw-app/templates/TrainTemplate.vue new file mode 100644 index 0000000..5ecec59 --- /dev/null +++ b/src/components/draw-app/templates/TrainTemplate.vue @@ -0,0 +1,51 @@ + + + diff --git a/src/configs/TokenManage.ts b/src/configs/TokenManage.ts new file mode 100644 index 0000000..11dddf9 --- /dev/null +++ b/src/configs/TokenManage.ts @@ -0,0 +1,13 @@ +const JwtTokenKey = 'jwttoken'; + +export function saveJwtToken(token: string) { + sessionStorage.setItem(JwtTokenKey, `Bearer ${token}`); +} + +export function getJwtToken(): string | null { + return sessionStorage.getItem(JwtTokenKey); +} + +export function clearJwtToken(): void { + sessionStorage.removeItem(JwtTokenKey); +} diff --git a/src/configs/UrlManage.ts b/src/configs/UrlManage.ts new file mode 100644 index 0000000..3a4b1e4 --- /dev/null +++ b/src/configs/UrlManage.ts @@ -0,0 +1,15 @@ +function getHost(): string { + // return '192.168.3.7:9081'; + // return '192.168.3.47:9081'; + // return '192.168.3.37:9081'; + // return '192.168.3.15:9081'; + return '192.168.3.233:9081'; +} + +export function getHttpBase() { + return `http://${getHost()}`; +} + +export function getWebsocketUrl() { + return `ws://${getHost()}/ws-default`; +} diff --git a/src/css/app.scss b/src/css/app.scss new file mode 100644 index 0000000..ecac98f --- /dev/null +++ b/src/css/app.scss @@ -0,0 +1 @@ +// app global css in SCSS form diff --git a/src/css/quasar.variables.scss b/src/css/quasar.variables.scss new file mode 100644 index 0000000..3996ce1 --- /dev/null +++ b/src/css/quasar.variables.scss @@ -0,0 +1,25 @@ +// Quasar SCSS (& Sass) Variables +// -------------------------------------------------- +// To customize the look and feel of this app, you can override +// the Sass/SCSS variables found in Quasar's source Sass/SCSS files. + +// Check documentation for full list of Quasar variables + +// Your own variables (that are declared here) and Quasar's own +// ones will be available out of the box in your .vue/.scss/.sass files + +// It's highly recommended to change the default colors +// to match your app's branding. +// Tip: Use the "Theme Builder" on Quasar's documentation website. + +$primary : #1976D2; +$secondary : #26A69A; +$accent : #9C27B0; + +$dark : #1D1D1D; +$dark-page : #121212; + +$positive : #21BA45; +$negative : #C10015; +$info : #31CCEC; +$warning : #F2C037; diff --git a/src/drawApp/graphics/AxleCountingInteraction.ts b/src/drawApp/graphics/AxleCountingInteraction.ts new file mode 100644 index 0000000..ed80bfd --- /dev/null +++ b/src/drawApp/graphics/AxleCountingInteraction.ts @@ -0,0 +1,56 @@ +import * as pb_1 from 'google-protobuf'; +import { + AxleCounting, + IAxleCountingData, +} from 'src/graphics/axleCounting/AxleCounting'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { GraphicDataBase } from './GraphicDataBase'; +import { KilometerSystem } from 'src/graphics/signal/Signal'; + +export class AxleCountingData + extends GraphicDataBase + implements IAxleCountingData +{ + constructor(data?: graphicData.AxleCounting) { + let axleCounting; + if (!data) { + axleCounting = new graphicData.AxleCounting({ + common: GraphicDataBase.defaultCommonInfo(AxleCounting.Type), + }); + } else { + axleCounting = data; + } + super(axleCounting); + } + + public get data(): graphicData.AxleCounting { + return this.getData(); + } + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get kilometerSystem(): KilometerSystem { + return this.data.kilometerSystem; + } + set kilometerSystem(v: KilometerSystem) { + this.data.kilometerSystem = new graphicData.KilometerSystem(v); + } + get axleCountingRef(): graphicData.RelatedRef[] { + return this.data.axleCountingRef; + } + set axleCountingRef(points: graphicData.RelatedRef[]) { + this.data.axleCountingRef = points; + } + clone(): AxleCountingData { + return new AxleCountingData(this.data.cloneMessage()); + } + copyFrom(data: AxleCountingData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: AxleCountingData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} diff --git a/src/drawApp/graphics/GraphicDataBase.ts b/src/drawApp/graphics/GraphicDataBase.ts new file mode 100644 index 0000000..225b259 --- /dev/null +++ b/src/drawApp/graphics/GraphicDataBase.ts @@ -0,0 +1,153 @@ +import * as pb_1 from 'google-protobuf'; +import { + ChildTransform, + GraphicData, + GraphicState, + GraphicTransform, + IChildTransform, + IGraphicTransform, +} from 'src/jl-graphic'; +// import { toStorageTransform } from '..'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { IPointData, Point } from 'pixi.js'; +import { state } from 'src/protos/device_status'; + +export interface ICommonInfo { + id: string; + graphicType: string; + transform: IGraphicTransform; + childTransforms: IChildTransform[]; +} +export function fromStoragePoint(p: graphicData.Point): Point { + return new Point(p.x, p.y); +} + +export function toStoragePoint(p: IPointData): graphicData.Point { + return new graphicData.Point({ x: p.x, y: p.y }); +} +export function fromStorageTransfrom( + transfrom: graphicData.Transform +): GraphicTransform { + return new GraphicTransform( + fromStoragePoint(transfrom.position), + fromStoragePoint(transfrom.scale), + transfrom.rotation, + fromStoragePoint(transfrom.skew) + ); +} + +export function toStorageTransform( + transform: GraphicTransform +): graphicData.Transform { + return new graphicData.Transform({ + position: toStoragePoint(transform.position), + scale: toStoragePoint(transform.scale), + rotation: transform.rotation, + skew: toStoragePoint(transform.skew), + }); +} + +export interface IProtoGraphicData extends pb_1.Message { + common: ICommonInfo; + code: string; +} + +export abstract class GraphicDataBase implements GraphicData { + _data: IProtoGraphicData; + constructor(data: IProtoGraphicData) { + this._data = data; + } + + static defaultCommonInfo(graphicType: string): graphicData.CommonInfo { + return new graphicData.CommonInfo({ + id: '', + graphicType: graphicType, + transform: new graphicData.Transform({ + position: new graphicData.Point({ x: 0, y: 0 }), + scale: new graphicData.Point({ x: 1, y: 1 }), + rotation: 0, + skew: new graphicData.Point({ x: 0, y: 0 }), + }), + childTransforms: [], + }); + } + + getData(): D { + return this._data as D; + } + + get id(): string { + return this._data.common.id; + } + set id(v: string) { + this._data.common.id = v; + } + get graphicType(): string { + return this._data.common.graphicType; + } + set graphicType(v: string) { + this._data.common.graphicType = v; + } + get transform(): GraphicTransform { + return GraphicTransform.from(this._data.common.transform); + } + set transform(v: GraphicTransform) { + this._data.common.transform = toStorageTransform(v); + } + get childTransforms(): ChildTransform[] | undefined { + const cts: ChildTransform[] = []; + if (this._data.common.childTransforms) { + this._data.common.childTransforms.forEach((ct) => { + cts.push(ChildTransform.from(ct)); + }); + } + return cts; + } + set childTransforms(v: ChildTransform[] | undefined) { + if (v) { + const cts: graphicData.ChildTransform[] = []; + v.forEach((ct) => + cts.push( + new graphicData.ChildTransform({ + ...ct, + transform: toStorageTransform(ct.transform), + }) + ) + ); + this._data.common.childTransforms = cts; + } else { + this._data.common.childTransforms = []; + } + } + + clone(): GraphicData { + throw new Error('Method not implemented.'); + } + copyFrom(gd: GraphicDataBase): void { + pb_1.Message.copyInto(gd._data, this._data); + } + eq(other: GraphicDataBase): boolean { + return pb_1.Message.equals(this._data, other._data); + } +} + +export abstract class GraphicStateBase implements GraphicState { + _graphicType: string; + _state: pb_1.Message; + constructor(state: pb_1.Message, graphicType: string) { + this._state = state; + this._graphicType = graphicType; + } + abstract get code(): string; + abstract copyFrom(data: GraphicState): void; + abstract eq(data: GraphicState): boolean; + getState(): S { + return this._state as S; + } + get graphicType(): string { + return this._graphicType; + } + clone(): GraphicState { + throw new Error('Method not implemented.'); + } +} diff --git a/src/drawApp/graphics/IscsFanInteraction.ts b/src/drawApp/graphics/IscsFanInteraction.ts new file mode 100644 index 0000000..80a8e07 --- /dev/null +++ b/src/drawApp/graphics/IscsFanInteraction.ts @@ -0,0 +1,38 @@ +import * as pb_1 from 'google-protobuf'; +import { IIscsFanData, IscsFan } from 'src/graphics/iscs-fan/IscsFan'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { GraphicDataBase } from './GraphicDataBase'; + +export class IscsFanData extends GraphicDataBase implements IIscsFanData { + constructor(data?: graphicData.IscsFan) { + let fan; + if (data) { + fan = data; + } else { + fan = new graphicData.IscsFan({ + common: GraphicDataBase.defaultCommonInfo(IscsFan.Type), + }); + } + super(fan); + } + + public get data(): graphicData.IscsFan { + return this.getData(); + } + + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + clone(): IscsFanData { + return new IscsFanData(this.data.cloneMessage()); + } + copyFrom(data: IscsFanData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: IscsFanData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} diff --git a/src/drawApp/graphics/LinkInteraction.ts b/src/drawApp/graphics/LinkInteraction.ts new file mode 100644 index 0000000..cd28295 --- /dev/null +++ b/src/drawApp/graphics/LinkInteraction.ts @@ -0,0 +1,182 @@ +import * as pb_1 from 'google-protobuf'; +import { IPointData, DisplayObject, FederatedMouseEvent } from 'pixi.js'; +import { ILinkData, Link } from 'src/graphics/link/Link'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { GraphicDataBase } from './GraphicDataBase'; +import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu'; +import { MenuItemOptions } from 'src/jl-graphic/ui/Menu'; +import { + GraphicApp, + GraphicInteractionPlugin, + JlGraphic, +} from 'src/jl-graphic'; +import { + addWayPoint, + clearWayPoint, + getWaypointRangeIndex, + PolylineEditPlugin, + removeLineWayPoint, +} from 'src/jl-graphic/plugins/GraphicEditPlugin'; + +export class LinkData extends GraphicDataBase implements ILinkData { + constructor(data?: graphicData.Link) { + let link; + if (!data) { + link = new graphicData.Link({ + common: GraphicDataBase.defaultCommonInfo(Link.Type), + }); + } else { + link = data; + } + super(link); + } + + public get data(): graphicData.Link { + return this.getData(); + } + + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get curve(): boolean { + return this.data.curve; + } + set curve(v: boolean) { + this.data.curve = v; + } + get curveNumber(): number { + return this.data.curve ? 1 : 0; + } + set curveNumber(v: number) { + this.data.curve = v === 0 ? false : true; + } + get segmentsCount(): number { + return this.data.segmentsCount; + } + set segmentsCount(v: number) { + this.data.segmentsCount = v; + } + get points(): IPointData[] { + return this.data.points; + } + set points(points: IPointData[]) { + this.data.points = points.map( + (p) => new graphicData.Point({ x: p.x, y: p.y }) + ); + } + get lineWidth(): number { + return this.data.lineWidth; + } + set lineWidth(v: number) { + this.data.lineWidth = v; + } + get lineColor(): string { + return this.data.lineColor; + } + set lineColor(v: string) { + this.data.lineColor = v; + } + clone(): LinkData { + return new LinkData(this.data.cloneMessage()); + } + copyFrom(data: LinkData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: LinkData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} + +export const addWaypointConfig: MenuItemOptions = { + name: '添加路径点', +}; +export const removeWaypointConfig: MenuItemOptions = { + name: '移除路径点', +}; +export const clearWaypointsConfig: MenuItemOptions = { + name: '清除所有路径点', +}; + +const LinkEditMenu: ContextMenu = ContextMenu.init({ + name: '轨道编辑菜单', + groups: [ + { + items: [addWaypointConfig, clearWaypointsConfig], + }, + ], +}); +const EpEditMenu: ContextMenu = ContextMenu.init({ + name: '轨道编辑菜单2', + groups: [ + { + items: [removeWaypointConfig, clearWaypointsConfig], + }, + ], +}); + +export class DrawLinkPlugin extends GraphicInteractionPlugin { + static Name = 'link_draw_right_menu'; + constructor(app: GraphicApp) { + super(DrawLinkPlugin.Name, app); + app.registerMenu(LinkEditMenu); + app.registerMenu(EpEditMenu); + } + static init(app: GraphicApp) { + return new DrawLinkPlugin(app); + } + filter(...grahpics: JlGraphic[]): Link[] | undefined { + return grahpics.filter((g) => g.type === Link.Type).map((g) => g as Link); + } + bind(g: Link): void { + g.on('_rightclick', this.onContextMenu, this); + g.on('selected', this.onSelected, this); + } + + unbind(g: Link): void { + g.off('_rightclick', this.onContextMenu, this); + g.off('selected', this.onSelected, this); + } + + onSelected(g: DisplayObject) { + const polylineEditPlugin = g.assistantAppendMap.get( + PolylineEditPlugin.Name + ) as PolylineEditPlugin; + const link = g.getGraphic() as Link; + polylineEditPlugin.editedPoints.forEach((ep, index) => { + ep.on('rightclick', (e: FederatedMouseEvent) => { + this.app.registerMenu(EpEditMenu); + removeWaypointConfig.handler = () => { + removeLineWayPoint(link, index); + }; + clearWaypointsConfig.handler = () => { + clearWayPoint(link, false); + }; + EpEditMenu.open(e.global); + }); + }); + } + onContextMenu(e: FederatedMouseEvent) { + const target = e.target as DisplayObject; + const link = target.getGraphic() as Link; + this.app.updateSelected(link); + + addWaypointConfig.handler = () => { + const linePoints = link.linePoints; + const p = link.screenToLocalPoint(e.global); + const { start, end } = getWaypointRangeIndex( + linePoints, + false, + p, + link.datas.lineWidth + ); + addWayPoint(link, false, start, end, p); + }; + clearWaypointsConfig.handler = () => { + clearWayPoint(link, false); + }; + LinkEditMenu.open(e.global); + } +} diff --git a/src/drawApp/graphics/PathLineInteraction.ts b/src/drawApp/graphics/PathLineInteraction.ts new file mode 100644 index 0000000..dc34cd2 --- /dev/null +++ b/src/drawApp/graphics/PathLineInteraction.ts @@ -0,0 +1,70 @@ +import * as pb_1 from 'google-protobuf'; +import { IPointData } from 'pixi.js'; +import { + IPathLineData, + PathLine, + KilometerPoint, +} from 'src/graphics/pathLine/PathLine'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { GraphicDataBase } from './GraphicDataBase'; + +export class PathLineData extends GraphicDataBase implements IPathLineData { + constructor(data?: graphicData.PathLine) { + let pathLine; + if (!data) { + pathLine = new graphicData.PathLine({ + common: GraphicDataBase.defaultCommonInfo(PathLine.Type), + }); + } else { + pathLine = data; + } + super(pathLine); + } + + public get data(): graphicData.PathLine { + return this.getData(); + } + + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get points(): IPointData[] { + return this.data.points; + } + set points(points: IPointData[]) { + this.data.points = points.map( + (p) => new graphicData.Point({ x: p.x, y: p.y }) + ); + } + get isUp(): boolean { + return this.data.isUp; + } + set isUp(v: boolean) { + this.data.isUp = v; + } + get kilometerPoints(): KilometerPoint[] { + return this.data.kilometerPoints; + } + set kilometerPoints(kilometerPoints: KilometerPoint[]) { + this.data.kilometerPoints = kilometerPoints.map( + (p) => + new graphicData.KilometerPoint({ + point: new graphicData.Point({ x: p.point.x, y: p.point.y }), + kilometer: p.kilometer, + stName: p.stName, + }) + ); + } + clone(): PathLineData { + return new PathLineData(this.data.cloneMessage()); + } + copyFrom(data: PathLineData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: PathLineData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} diff --git a/src/drawApp/graphics/PlatformInteraction.ts b/src/drawApp/graphics/PlatformInteraction.ts new file mode 100644 index 0000000..c74247a --- /dev/null +++ b/src/drawApp/graphics/PlatformInteraction.ts @@ -0,0 +1,307 @@ +import * as pb_1 from 'google-protobuf'; +import { + IPlatformData, + IPlatformState, + Platform, +} from 'src/graphics/platform/Platform'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase'; +import { state } from 'src/protos/device_status'; +import { MenuItemOptions } from 'src/jl-graphic/ui/Menu'; +import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu'; +import { + GraphicApp, + GraphicInteractionPlugin, + JlGraphic, +} from 'src/jl-graphic'; +import { DisplayObject, FederatedMouseEvent } from 'pixi.js'; + +export class PlatformData extends GraphicDataBase implements IPlatformData { + constructor(data?: graphicData.Platform) { + let platform; + if (!data) { + platform = new graphicData.Platform({ + common: GraphicDataBase.defaultCommonInfo(Platform.Type), + }); + } else { + platform = data; + } + super(platform); + } + + public get data(): graphicData.Platform { + return this.getData(); + } + + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get hasdoor(): boolean { + return this.data.hasdoor; + } + set hasdoor(v: boolean) { + this.data.hasdoor = v; + } + get direction(): string { + return this.data.direction; + } + set direction(v: string) { + this.data.direction = v; + } + + clone(): PlatformData { + return new PlatformData(this.data.cloneMessage()); + } + copyFrom(data: PlatformData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: PlatformData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} + +export class PlatformState extends GraphicStateBase implements IPlatformState { + constructor(proto?: state.Platform) { + let states; + if (proto) { + states = proto; + } else { + states = new state.Platform(); + } + super(states, Platform.Type); + } + + get emergstop(): boolean { + return this.states.emergstop; + } + set emergstop(v: boolean) { + this.states.emergstop = v; + } + get trainberth(): boolean { + return this.states.trainberth; + } + set trainberth(v: boolean) { + this.states.trainberth = v; + } + get close(): boolean { + return this.states.close; + } + set close(v: boolean) { + this.states.close = v; + } + get upHold(): boolean { + return this.states.upHold; + } + set upHold(v: boolean) { + this.states.upHold = v; + } + get downHold(): boolean { + return this.states.downHold; + } + set downHold(v: boolean) { + this.states.downHold = v; + } + get upOccHold(): boolean { + return this.states.upOccHold; + } + set upOccHold(v: boolean) { + this.states.upOccHold = v; + } + get downOccHold(): boolean { + return this.states.downOccHold; + } + set downOccHold(v: boolean) { + this.states.downOccHold = v; + } + get psdOpen(): boolean { + return this.states.psdOpen; + } + set psdOpen(v: boolean) { + this.states.psdOpen = v; + } + get psdCut(): boolean { + return this.states.psdCut; + } + set psdCut(v: boolean) { + this.states.psdCut = v; + } + + get upSkipstop(): boolean { + return this.states.upSkipstop; + } + set upSkipstop(v: boolean) { + this.states.upSkipstop = v; + } + get downSkipstop(): boolean { + return this.states.downSkipstop; + } + set downSkipstop(v: boolean) { + this.states.downSkipstop = v; + } + get upTrainSkipstop(): boolean { + return this.states.upTrainSkipstop; + } + set upTrainSkipstop(v: boolean) { + this.states.upTrainSkipstop = v; + } + get downTrainSkipstop(): boolean { + return this.states.downTrainSkipstop; + } + set downTrainSkipstop(v: boolean) { + this.states.downTrainSkipstop = v; + } + get nextSectionRunTime(): number { + return this.states.nextSectionRunTime; + } + set nextSectionRunTime(v: number) { + this.states.nextSectionRunTime = v; + } + get nextSectionRunLevel(): number { + return this.states.nextSectionRunLevel; + } + set nextSectionRunLevel(v: number) { + this.states.nextSectionRunLevel = v; + } + get stopTime(): number { + return this.states.stopTime; + } + set stopTime(v: number) { + this.states.stopTime = v; + } + get states(): state.Platform { + return this.getState(); + } + clone(): PlatformState { + return new PlatformState(this.states.cloneMessage()); + } +} + +const holdConfig: MenuItemOptions = { + name: '扣车', +}; +const removeHoldrConfig: MenuItemOptions = { + name: '取消扣车', +}; +const batchHoldConfig: MenuItemOptions = { + name: '批量扣车', +}; +const removeBatchHoldConfig: MenuItemOptions = { + name: '批量取消扣车', +}; +const earlyDepartureConfig: MenuItemOptions = { + name: '提前发车', +}; +const skipStopConfig: MenuItemOptions = { + name: '设置跳停', +}; +const removeSkipStopConfig: MenuItemOptions = { + name: '取消跳停', +}; +const dockTimeConfig: MenuItemOptions = { + name: '设置停站时间', +}; +const operatingLevelConfig: MenuItemOptions = { + name: '设置运行等级', +}; +const numberOfRegionalTrainsConfig: MenuItemOptions = { + name: '区间列车数量限制', +}; +const removeNumberOfRegionalTrainsConfig: MenuItemOptions = { + name: '取消区间列车数量限制', +}; +const platformMessadeConfig: MenuItemOptions = { + name: '站台详细信息', +}; + +const PlatformOperateMenu: ContextMenu = ContextMenu.init({ + name: '站台操作菜单', + groups: [ + { + items: [ + holdConfig, + removeHoldrConfig, + skipStopConfig, + removeSkipStopConfig, + ], + }, + ], +}); + +const dispatchPlatformOperateMenu: ContextMenu = ContextMenu.init({ + name: '调度仿真站台操作菜单', + groups: [ + { + items: [ + holdConfig, + removeHoldrConfig, + batchHoldConfig, + removeBatchHoldConfig, + earlyDepartureConfig, + skipStopConfig, + removeSkipStopConfig, + dockTimeConfig, + operatingLevelConfig, + numberOfRegionalTrainsConfig, + removeNumberOfRegionalTrainsConfig, + platformMessadeConfig, + ], + }, + ], +}); + +export class PlatformOperateInteraction extends GraphicInteractionPlugin { + static Name = 'platform_operate_menu'; + constructor(app: GraphicApp) { + super(PlatformOperateInteraction.Name, app); + app.registerMenu(PlatformOperateMenu); + } + static init(app: GraphicApp) { + return new PlatformOperateInteraction(app); + } + filter(...grahpics: JlGraphic[]): Platform[] | undefined { + return grahpics + .filter((g) => g.type === Platform.Type) + .map((g) => g as Platform); + } + bind(g: Platform): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.selectable = true; + g.on('_rightclick', this.onContextMenu, this); + } + + unbind(g: Platform): void { + g.selectable = false; + g.eventMode = 'none'; + g.off('_rightclick', this.onContextMenu, this); + } + + onContextMenu(e: FederatedMouseEvent) { + const target = e.target as DisplayObject; + const platform = target.getGraphic() as Platform; + this.app.updateSelected(platform); + holdConfig.handler = () => { + platform.states.upHold = true; + platform.states.upOccHold = true; + platform.doRepaint(); + }; + removeHoldrConfig.handler = () => { + platform.states.upHold = false; + platform.states.upOccHold = false; + platform.doRepaint(); + }; + skipStopConfig.handler = () => { + platform.states.upSkipstop = true; + platform.doRepaint(); + }; + removeSkipStopConfig.handler = () => { + platform.states.upSkipstop = false; + platform.doRepaint(); + }; + + PlatformOperateMenu.open(e.global); + } +} diff --git a/src/drawApp/graphics/PolygonInteraction.ts b/src/drawApp/graphics/PolygonInteraction.ts new file mode 100644 index 0000000..034fe9b --- /dev/null +++ b/src/drawApp/graphics/PolygonInteraction.ts @@ -0,0 +1,197 @@ +import * as pb_1 from 'google-protobuf'; +import { IPolygonData, Polygon } from 'src/graphics/polygon/Polygon'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { GraphicDataBase } from './GraphicDataBase'; +import { DisplayObject, FederatedMouseEvent, IPointData } from 'pixi.js'; +import { + GraphicApp, + GraphicInteractionPlugin, + JlGraphic, +} from 'src/jl-graphic'; +import { MenuItemOptions } from 'src/jl-graphic/ui/Menu'; +import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu'; +import { + PolylineEditPlugin, + clearWayPoint, + removeLineWayPoint, +} from 'src/jl-graphic/plugins/GraphicEditPlugin'; +import { + addPolygonSegmentingPoint, + getWayLineIndex, +} from 'src/graphics/polygon/PolygonUtils'; + +export class PolygonData extends GraphicDataBase implements IPolygonData { + constructor(data?: graphicData.Polygon) { + let polygon; + if (!data) { + polygon = new graphicData.Polygon({ + common: GraphicDataBase.defaultCommonInfo(Polygon.Type), + }); + } else { + polygon = data; + } + super(polygon); + } + + public get data(): graphicData.Polygon { + return this.getData(); + } + + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get lineWidth(): number { + return this.data.lineWidth; + } + set lineWidth(v: number) { + this.data.lineWidth = v; + } + get lineColor(): string { + return this.data.lineColor; + } + set lineColor(v: string) { + this.data.lineColor = v; + } + get points(): IPointData[] { + return this.data.points; + } + set points(points: IPointData[]) { + this.data.points = points.map( + (p) => new graphicData.Point({ x: p.x, y: p.y }) + ); + } + + clone(): PolygonData { + return new PolygonData(this.data.cloneMessage()); + } + copyFrom(data: PolygonData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: PolygonData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} + +/** + * polygon编辑菜单配置 + */ + +const threeSegmentingConfig: MenuItemOptions = { + name: '3等分', +}; +const foreSegmentingConfig: MenuItemOptions = { + name: '4等分', +}; +const fiveSegmentingConfig: MenuItemOptions = { + name: '5等分', +}; + +const chooseSegmentingConfig: MenuItemOptions = { + name: '细分', + subMenu: [ + { + name: '内置图形', + items: [ + threeSegmentingConfig, + foreSegmentingConfig, + fiveSegmentingConfig, + ], + }, + ], +}; +const removeWaypointConfig: MenuItemOptions = { + name: '移除路径点', +}; +const clearWaypointsConfig: MenuItemOptions = { + name: '清除所有路径点', +}; +const PolygonEditMenu: ContextMenu = ContextMenu.init({ + name: '多边形边的编辑菜单', + groups: [ + { + items: [chooseSegmentingConfig, clearWaypointsConfig], + }, + ], +}); + +const EpEditMenu: ContextMenu = ContextMenu.init({ + name: '多边形点的编辑菜单', + groups: [ + { + items: [removeWaypointConfig, clearWaypointsConfig], + }, + ], +}); + +export class DrawPolygonPlugin extends GraphicInteractionPlugin { + static Name = 'polygon_draw_right_menu'; + constructor(app: GraphicApp) { + super(DrawPolygonPlugin.Name, app); + app.registerMenu(PolygonEditMenu); + app.registerMenu(EpEditMenu); + } + static init(app: GraphicApp) { + return new DrawPolygonPlugin(app); + } + filter(...grahpics: JlGraphic[]): Polygon[] | undefined { + return grahpics + .filter((g) => g.type === Polygon.Type) + .map((g) => g as Polygon); + } + bind(g: Polygon): void { + g.on('_rightclick', this.onContextMenu, this); + g.on('selected', this.onSelected, this); + } + + unbind(g: Polygon): void { + g.off('_rightclick', this.onContextMenu, this); + g.off('selected', this.onSelected, this); + } + + onSelected(g: DisplayObject) { + const polylineEditPlugin = g.assistantAppendMap.get( + PolylineEditPlugin.Name + ) as PolylineEditPlugin; + const link = g.getGraphic() as Polygon; + polylineEditPlugin.editedPoints.forEach((ep, index) => { + ep.on('rightclick', (e: FederatedMouseEvent) => { + this.app.registerMenu(EpEditMenu); + removeWaypointConfig.handler = () => { + removeLineWayPoint(link, index); + }; + clearWaypointsConfig.handler = () => { + clearWayPoint(link, false); + }; + EpEditMenu.open(e.global); + }); + }); + } + onContextMenu(e: FederatedMouseEvent) { + const target = e.target as DisplayObject; + const polygon = target.getGraphic() as Polygon; + this.app.updateSelected(polygon); + const linePoints = polygon.addOnePoints(); + const p = polygon.screenToLocalPoint(e.global); + const { start, end } = getWayLineIndex(linePoints, p); + + chooseSegmentingConfig.handler = () => { + addPolygonSegmentingPoint(polygon, start, end); + }; + threeSegmentingConfig.handler = () => { + addPolygonSegmentingPoint(polygon, start, end, 3); + }; + foreSegmentingConfig.handler = () => { + addPolygonSegmentingPoint(polygon, start, end, 4); + }; + fiveSegmentingConfig.handler = () => { + addPolygonSegmentingPoint(polygon, start, end, 5); + }; + clearWaypointsConfig.handler = () => { + clearWayPoint(polygon, false); + }; + PolygonEditMenu.open(e.global); + } +} diff --git a/src/drawApp/graphics/RectInteraction.ts b/src/drawApp/graphics/RectInteraction.ts new file mode 100644 index 0000000..3ea0c2e --- /dev/null +++ b/src/drawApp/graphics/RectInteraction.ts @@ -0,0 +1,75 @@ +import * as pb_1 from 'google-protobuf'; +import { IPointData } from 'pixi.js'; +import { IRectData, Rect } from 'src/graphics/rect/Rect'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { GraphicDataBase } from './GraphicDataBase'; + +export class RectData extends GraphicDataBase implements IRectData { + constructor(data?: graphicData.Rect) { + let rect; + if (!data) { + rect = new graphicData.Rect({ + common: GraphicDataBase.defaultCommonInfo(Rect.Type), + }); + } else { + rect = data; + } + super(rect); + } + + public get data(): graphicData.Rect { + return this.getData(); + } + + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get lineWidth(): number { + return this.data.lineWidth; + } + set lineWidth(v: number) { + this.data.lineWidth = v; + } + get lineColor(): string { + return this.data.lineColor; + } + set lineColor(v: string) { + this.data.lineColor = v; + } + get point(): IPointData { + return this.data.point; + } + set point(point: IPointData) { + this.data.point = new graphicData.Point({ x: point.x, y: point.y }); + } + get width(): number { + return this.data.width; + } + set width(v: number) { + this.data.width = v; + } + get height(): number { + return this.data.height; + } + set height(v: number) { + this.data.height = v; + } + get radius(): number { + return this.data.radius; + } + set radius(v: number) { + this.data.radius = v; + } + clone(): RectData { + return new RectData(this.data.cloneMessage()); + } + copyFrom(data: RectData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: RectData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} diff --git a/src/drawApp/graphics/RunLineInteraction.ts b/src/drawApp/graphics/RunLineInteraction.ts new file mode 100644 index 0000000..8a457f4 --- /dev/null +++ b/src/drawApp/graphics/RunLineInteraction.ts @@ -0,0 +1,214 @@ +import * as pb_1 from 'google-protobuf'; +import { + IRunLineData, + RunLine, + runLineConsts, +} from 'src/graphics/runLine/RunLine'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { GraphicDataBase } from './GraphicDataBase'; +import { + GraphicInteractionPlugin, + GraphicApp, + JlGraphic, +} from 'src/jl-graphic'; +import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu'; +import { MenuItemOptions } from 'src/jl-graphic/ui/Menu'; +import { FederatedMouseEvent, DisplayObject, IPointData } from 'pixi.js'; +import { + addWayPoint, + clearWayPoint, + getWaypointRangeIndex, + PolylineEditPlugin, + removeLineWayPoint, +} from 'src/jl-graphic/plugins/GraphicEditPlugin'; +import { RunLineGraphicHitArea } from 'src/graphics/runLine/RunLineDrawAssistant'; + +export class RunLineData extends GraphicDataBase implements IRunLineData { + constructor(data?: graphicData.RunLine) { + let runLine; + if (!data) { + runLine = new graphicData.RunLine({ + common: GraphicDataBase.defaultCommonInfo(RunLine.Type), + }); + } else { + runLine = data; + } + super(runLine); + } + public get data(): graphicData.RunLine { + return this.getData(); + } + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get points(): IPointData[] { + return this.data.points; + } + set points(points: IPointData[]) { + this.data.points = points.map( + (p) => new graphicData.Point({ x: p.x, y: p.y }) + ); + } + get nameColor(): string { + return this.data.nameColor; + } + set nameColor(v: string) { + this.data.nameColor = v; + } + get nameBgColor(): string { + return this.data.nameBgColor; + } + set nameBgColor(v: string) { + this.data.nameBgColor = v; + } + get containSta(): string[] { + return this.data.containSta; + } + set containSta(v: string[]) { + this.data.containSta = v; + } + get linkPathLines(): string[] { + return this.data.linkPathLines; + } + set linkPathLines(v: string[]) { + this.data.linkPathLines = v; + } + get lineId(): string { + return this.data.lineId; + } + set lineId(v: string) { + this.data.lineId = v; + } + clone(): RunLineData { + return new RunLineData(this.data.cloneMessage()); + } + copyFrom(data: RunLineData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: RunLineData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} + +export const addWaypointConfig: MenuItemOptions = { + name: '添加路径点', +}; +export const removeWaypointConfig: MenuItemOptions = { + name: '移除路径点', +}; +export const clearWaypointsConfig: MenuItemOptions = { + name: '清除所有路径点', +}; + +const RunLineEditMenu: ContextMenu = ContextMenu.init({ + name: '运行线编辑菜单', + groups: [ + { + items: [addWaypointConfig, clearWaypointsConfig], + }, + ], +}); +const EpEditMenu: ContextMenu = ContextMenu.init({ + name: '运行线编辑菜单2', + groups: [ + { + items: [removeWaypointConfig, clearWaypointsConfig], + }, + ], +}); + +export class DrawRunLinePlugin extends GraphicInteractionPlugin { + static Name = 'runline_draw_right_menu'; + constructor(app: GraphicApp) { + super(DrawRunLinePlugin.Name, app); + app.registerMenu(RunLineEditMenu); + app.registerMenu(EpEditMenu); + } + static init(app: GraphicApp) { + return new DrawRunLinePlugin(app); + } + filter(...grahpics: JlGraphic[]): RunLine[] | undefined { + return grahpics + .filter((g) => g.type === RunLine.Type) + .map((g) => g as RunLine); + } + bind(g: RunLine): void { + g.on('_rightclick', this.onContextMenu, this); + g.on('selected', this.onSelected, this); + } + + unbind(g: RunLine): void { + g.off('_rightclick', this.onContextMenu, this); + g.off('selected', this.onSelected, this); + } + + onSelected(g: DisplayObject) { + const polylineEditPlugin = g.assistantAppendMap.get( + PolylineEditPlugin.Name + ) as PolylineEditPlugin; + const runLine = g.getGraphic() as RunLine; + polylineEditPlugin.editedPoints.forEach((ep, index) => { + ep.on('rightclick', (e: FederatedMouseEvent) => { + this.app.registerMenu(EpEditMenu); + removeWaypointConfig.handler = () => { + removeLineWayPoint(runLine, index); + }; + clearWaypointsConfig.handler = () => { + clearWayPoint(runLine, false); + }; + EpEditMenu.open(e.global); + }); + }); + } + onContextMenu(e: FederatedMouseEvent) { + const target = e.target as DisplayObject; + const runLine = target.getGraphic() as RunLine; + this.app.updateSelected(runLine); + + addWaypointConfig.handler = () => { + const linePoints = runLine.linePoints; + const p = runLine.screenToLocalPoint(e.global); + const { start, end } = getWaypointRangeIndex( + linePoints, + false, + p, + runLineConsts.runLineWidth + ); + addWayPoint(runLine, false, start, end, p); + }; + clearWaypointsConfig.handler = () => { + clearWayPoint(runLine, false); + }; + RunLineEditMenu.open(e.global); + } +} + +export class RunLineOperateInteraction extends GraphicInteractionPlugin { + static Name = 'runLine_operate_menu'; + constructor(app: GraphicApp) { + super(RunLineOperateInteraction.Name, app); + app.registerMenu(EpEditMenu); + } + static init(app: GraphicApp) { + return new RunLineOperateInteraction(app); + } + filter(...grahpics: JlGraphic[]): RunLine[] | undefined { + return grahpics + .filter((g) => g.type === RunLine.Type) + .map((g) => g as RunLine); + } + bind(g: RunLine): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.lineBody.hitArea = new RunLineGraphicHitArea(g); + g.selectable = true; + } + + unbind(g: RunLine): void { + g.selectable = false; + g.eventMode = 'none'; + } +} diff --git a/src/drawApp/graphics/SectionInteraction.ts b/src/drawApp/graphics/SectionInteraction.ts new file mode 100644 index 0000000..b8a8bff --- /dev/null +++ b/src/drawApp/graphics/SectionInteraction.ts @@ -0,0 +1,69 @@ +import * as pb_1 from 'google-protobuf'; +import { GraphicDataBase } from './GraphicDataBase'; +import { ISectionData, Section } from 'src/graphics/section/Section'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { IPointData } from 'pixi.js'; + +export class SectionData extends GraphicDataBase implements ISectionData { + constructor(data?: graphicData.Section) { + let section; + if (!data) { + section = new graphicData.Section({ + common: GraphicDataBase.defaultCommonInfo(Section.Type), + }); + } else { + section = data; + } + super(section); + } + public get data(): graphicData.Section { + return this.getData(); + } + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get points(): IPointData[] { + return this.data.points; + } + set points(points: IPointData[]) { + this.data.points = points.map( + (p) => new graphicData.Point({ x: p.x, y: p.y }) + ); + } + get paRef(): graphicData.RelatedRef { + return this.data.paRef; + } + set paRef(ref: graphicData.RelatedRef) { + this.data.paRef = ref; + } + get pbRef(): graphicData.RelatedRef { + return this.data.pbRef; + } + set pbRef(ref: graphicData.RelatedRef) { + this.data.pbRef = ref; + } + get sectionType(): graphicData.Section.SectionType { + return this.data.sectionType; + } + set sectionType(type: graphicData.Section.SectionType) { + this.data.sectionType = type; + } + get children(): string[] { + return this.data.children; + } + set children(children: string[]) { + this.data.children = children; + } + clone(): SectionData { + return new SectionData(this.data.cloneMessage()); + } + copyFrom(data: SectionData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: SectionData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} diff --git a/src/drawApp/graphics/SeparatorInteraction.ts b/src/drawApp/graphics/SeparatorInteraction.ts new file mode 100644 index 0000000..303ca13 --- /dev/null +++ b/src/drawApp/graphics/SeparatorInteraction.ts @@ -0,0 +1,43 @@ +import * as pb_1 from 'google-protobuf'; +import { ISeparatorData, Separator } from 'src/graphics/separator/Separator'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { GraphicDataBase } from './GraphicDataBase'; + +export class SeparatorData extends GraphicDataBase implements ISeparatorData { + constructor(data?: graphicData.Separator) { + let separator; + if (!data) { + separator = new graphicData.Separator({ + common: GraphicDataBase.defaultCommonInfo(Separator.Type), + }); + } else { + separator = data; + } + super(separator); + } + + public get data(): graphicData.Separator { + return this.getData(); + } + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get separatorType(): string { + return this.data.separatorType; + } + set separatorType(v: string) { + this.data.separatorType = v; + } + clone(): SeparatorData { + return new SeparatorData(this.data.cloneMessage()); + } + copyFrom(data: SeparatorData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: SeparatorData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} diff --git a/src/drawApp/graphics/SignalInteraction.ts b/src/drawApp/graphics/SignalInteraction.ts new file mode 100644 index 0000000..658dede --- /dev/null +++ b/src/drawApp/graphics/SignalInteraction.ts @@ -0,0 +1,369 @@ +import * as pb_1 from 'google-protobuf'; +import { + ISignalData, + Signal, + ISignalState, + KilometerSystem, +} from 'src/graphics/signal/Signal'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase'; +import { + GraphicInteractionPlugin, + GraphicApp, + JlGraphic, +} from 'src/jl-graphic'; +import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu'; +import { MenuItemOptions } from 'src/jl-graphic/ui/Menu'; +import { FederatedMouseEvent, DisplayObject } from 'pixi.js'; +import { state } from 'src/protos/device_status'; + +export class SignalData extends GraphicDataBase implements ISignalData { + constructor(data?: graphicData.Signal) { + let signal; + if (!data) { + signal = new graphicData.Signal({ + common: GraphicDataBase.defaultCommonInfo(Signal.Type), + }); + } else { + signal = data; + } + super(signal); + } + public get data(): graphicData.Signal { + return this.getData(); + } + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get mirror(): boolean { + return this.data.mirror; + } + set mirror(v: boolean) { + this.data.mirror = v; + } + get kilometerSystem(): KilometerSystem { + return this.data.kilometerSystem; + } + set kilometerSystem(v: KilometerSystem) { + this.data.kilometerSystem = new graphicData.KilometerSystem(v); + } + clone(): SignalData { + return new SignalData(this.data.cloneMessage()); + } + copyFrom(data: SignalData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: SignalData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} + +export class SignalState extends GraphicStateBase implements ISignalState { + constructor(proto?: state.Signal) { + let states; + if (proto) { + states = proto; + } else { + states = new state.Signal(); + } + super(states, Signal.Type); + } + get code(): string { + return this.states.id; + } + get redOpen(): boolean { + return this.states.redOpen; + } + set redOpen(v: boolean) { + this.states.redOpen = v; + } + get redFlash(): boolean { + return this.states.redFlash; + } + set redFlash(v: boolean) { + this.states.redFlash = v; + } + get greenOpen(): boolean { + return this.states.greenOpen; + } + set greenOpen(v: boolean) { + this.states.greenOpen = v; + } + get greenFlash(): boolean { + return this.states.greenFlash; + } + set greenFlash(v: boolean) { + this.states.greenFlash = v; + } + get yellowOpen(): boolean { + return this.states.yellowOpen; + } + set yellowOpen(v: boolean) { + this.states.yellowOpen = v; + } + get yellowFlash(): boolean { + return this.states.yellowFlash; + } + set yellowFlash(v: boolean) { + this.states.yellowFlash = v; + } + get whiteOpen(): boolean { + return this.states.whiteOpen; + } + set whiteOpen(v: boolean) { + this.states.whiteOpen = v; + } + get whiteFlash(): boolean { + return this.states.whiteFlash; + } + set whiteFlash(v: boolean) { + this.states.whiteFlash = v; + } + get blueOpen(): boolean { + return this.states.blueOpen; + } + set blueOpen(v: boolean) { + this.states.blueOpen = v; + } + + get blueFlash(): boolean { + return this.states.blueFlash; + } + set blueFlash(v: boolean) { + this.states.blueFlash = v; + } + get fleetMode(): boolean { + return this.states.fleetMode; + } + set fleetMode(v: boolean) { + this.states.fleetMode = v; + } + get ctrlFleetMode(): boolean { + return this.states.ctrlFleetMode; + } + set ctrlFleetMode(v: boolean) { + this.states.ctrlFleetMode = v; + } + get autoMode(): boolean { + return this.states.autoMode; + } + set autoMode(v: boolean) { + this.states.autoMode = v; + } + get ctrlAutoMode(): boolean { + return this.states.ctrlAutoMode; + } + set ctrlAutoMode(v: boolean) { + this.states.ctrlAutoMode = v; + } + get extinguish(): boolean { + return this.states.extinguish; + } + set extinguish(v: boolean) { + this.states.extinguish = v; + } + get approachLock(): boolean { + return this.states.approachLock; + } + set approachLock(v: boolean) { + this.states.approachLock = v; + } + get protectRoute(): boolean { + return this.states.protectRoute; + } + set protectRoute(v: boolean) { + this.states.protectRoute = v; + } + get autoRouteDisable(): boolean { + return this.states.autoRouteDisable; + } + set autoRouteDisable(v: boolean) { + this.states.autoRouteDisable = v; + } + get callon(): boolean { + return this.states.callon; + } + set callon(v: boolean) { + this.states.callon = v; + } + get yellowYellow(): boolean { + return this.states.yellowYellow; + } + set yellowYellow(v: boolean) { + this.states.yellowYellow = v; + } + get yellowGreen(): boolean { + return this.states.yellowGreen; + } + set yellowGreen(v: boolean) { + this.states.yellowGreen = v; + } + get blocked(): boolean { + return this.states.blocked; + } + set blocked(v: boolean) { + this.states.blocked = v; + } + get lampFailure(): boolean { + return this.states.lampFailure; + } + set lampFailure(v: boolean) { + this.states.lampFailure = v; + } + get states(): state.Signal { + return this.getState(); + } + clone(): SignalState { + return new SignalState(this.states.cloneMessage()); + } + copyFrom(data: GraphicStateBase): void { + pb_1.Message.copyInto(data._state, this._state); + } + eq(data: GraphicStateBase): boolean { + return pb_1.Message.equals(this._state, data._state); + } +} + +const mirrorFlipConfig: MenuItemOptions = { + name: '镜像翻转', +}; +const signalCloseConfig: MenuItemOptions = { + name: '信号机关闭', +}; +const signalRedFlashConfig: MenuItemOptions = { + name: '信号机红闪', +}; +const signalOpenConfig: MenuItemOptions = { + name: '信号机开放', +}; +const signalFleetConfig: MenuItemOptions = { + name: '连锁自动进路', +}; +const humanControlConfig: MenuItemOptions = { + name: '进路交人工控', +}; +const logicConfig: MenuItemOptions = { + name: '逻辑点灯', +}; +const SignalEditMenu: ContextMenu = ContextMenu.init({ + name: '信号机编辑菜单', + groups: [ + { + items: [mirrorFlipConfig], + }, + ], +}); +const SignalOperateMenu: ContextMenu = ContextMenu.init({ + name: '信号机操作菜单', + groups: [ + { + items: [ + signalCloseConfig, + signalOpenConfig, + signalFleetConfig, + humanControlConfig, + logicConfig, + signalRedFlashConfig, + ], + }, + ], +}); +export class DrawSignalInteraction extends GraphicInteractionPlugin { + static Name = 'signal_draw_right_menu'; + constructor(app: GraphicApp) { + super(DrawSignalInteraction.Name, app); + app.registerMenu(SignalEditMenu); + } + static init(app: GraphicApp) { + return new DrawSignalInteraction(app); + } + filter(...grahpics: JlGraphic[]): Signal[] | undefined { + return grahpics + .filter((g) => g.type === Signal.Type) + .map((g) => g as Signal); + } + bind(g: Signal): void { + g.on('_rightclick', this.onContextMenu, this); + } + + unbind(g: Signal): void { + g.off('_rightclick', this.onContextMenu, this); + } + + onContextMenu(e: FederatedMouseEvent) { + const target = e.target as DisplayObject; + const signal = target.getGraphic() as Signal; + this.app.updateSelected(signal); + mirrorFlipConfig.handler = () => { + signal.mirror = !signal.mirror; + }; + SignalEditMenu.open(e.global); + } +} + +export class SignalOperateInteraction extends GraphicInteractionPlugin { + static Name = 'signal_operate_menu'; + constructor(app: GraphicApp) { + super(SignalOperateInteraction.Name, app); + app.registerMenu(SignalOperateMenu); + } + static init(app: GraphicApp) { + return new SignalOperateInteraction(app); + } + filter(...grahpics: JlGraphic[]): Signal[] | undefined { + return grahpics + .filter((g) => g.type === Signal.Type) + .map((g) => g as Signal); + } + bind(g: Signal): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.selectable = true; + g.on('_rightclick', this.onContextMenu, this); + } + + unbind(g: Signal): void { + g.selectable = false; + g.eventMode = 'none'; + g.off('_rightclick', this.onContextMenu, this); + } + + onContextMenu(e: FederatedMouseEvent) { + const target = e.target as DisplayObject; + const signal = target.getGraphic() as Signal; + this.app.updateSelected(signal); + signalCloseConfig.handler = () => { + signal.states.redOpen = true; + signal.states.greenOpen = false; + signal.doRepaint(); + }; + signalOpenConfig.handler = () => { + signal.states.redOpen = false; + signal.states.greenOpen = true; + signal.doRepaint(); + }; + signalFleetConfig.handler = () => { + signal.states.fleetMode = true; + signal.doRepaint(); + }; + humanControlConfig.handler = () => { + signal.states.autoRouteDisable = true; + signal.doRepaint(); + }; + logicConfig.handler = () => { + signal.states.extinguish = true; + signal.doRepaint(); + }; + signalRedFlashConfig.handler = () => { + signal.states.redFlash = true; + signal.states.redOpen = false; + signal.states.greenOpen = false; + signal.doRepaint(); + }; + + SignalOperateMenu.open(e.global); + } +} diff --git a/src/drawApp/graphics/StationInteraction.ts b/src/drawApp/graphics/StationInteraction.ts new file mode 100644 index 0000000..398cd24 --- /dev/null +++ b/src/drawApp/graphics/StationInteraction.ts @@ -0,0 +1,178 @@ +import * as pb_1 from 'google-protobuf'; +import { + IStationData, + IStationState, + Station, +} from 'src/graphics/station/Station'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase'; +import { state } from 'src/protos/device_status'; +import { MenuItemOptions } from 'src/jl-graphic/ui/Menu'; +import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu'; +import { + GraphicApp, + GraphicInteractionPlugin, + JlGraphic, +} from 'src/jl-graphic'; +import { DisplayObject, FederatedMouseEvent } from 'pixi.js'; +import { KilometerSystem } from 'src/graphics/signal/Signal'; + +export class StationData extends GraphicDataBase implements IStationData { + constructor(data?: graphicData.Station) { + let station; + if (!data) { + station = new graphicData.Station({ + common: GraphicDataBase.defaultCommonInfo(Station.Type), + }); + } else { + station = data; + } + super(station); + } + + public get data(): graphicData.Station { + return this.getData(); + } + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get kilometerSystem(): KilometerSystem { + return this.data.kilometerSystem; + } + set kilometerSystem(v: KilometerSystem) { + this.data.kilometerSystem = new graphicData.KilometerSystem(v); + } + get hasControl(): boolean { + return this.data.hasControl; + } + set hasControl(v: boolean) { + this.data.hasControl = v; + } + get concentrationStations(): boolean { + return this.data.concentrationStations; + } + set concentrationStations(v: boolean) { + this.data.concentrationStations = v; + } + clone(): StationData { + return new StationData(this.data.cloneMessage()); + } + copyFrom(data: StationData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: StationData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} + +export class StationState extends GraphicStateBase implements IStationState { + constructor(proto?: state.Rtu) { + let states; + if (proto) { + states = proto; + } else { + states = new state.Station(); + } + super(states, Station.Type); + } + + get ipRtuStusDown(): boolean { + return this.states.ipRtuStusDown; + } + set ipRtuStusDown(v: boolean) { + this.states.ipRtuStusDown = v; + } + get ipRtuStusInLocalCtrl(): boolean { + return this.states.ipRtuStusInLocalCtrl; + } + set ipRtuStusInLocalCtrl(v: boolean) { + this.states.ipRtuStusInLocalCtrl = v; + } + get ipRtuStusInCentralCtrl(): boolean { + return this.states.ipRtuStusInCentralCtrl; + } + set ipRtuStusInCentralCtrl(v: boolean) { + this.states.ipRtuStusInCentralCtrl = v; + } + get ipRtuStusInEmergencyCtrl(): boolean { + return this.states.ipRtuStusInEmergencyCtrl; + } + set ipRtuStusInEmergencyCtrl(v: boolean) { + this.states.ipRtuStusInEmergencyCtrl = v; + } + get states(): state.Rtu { + return this.getState(); + } + + clone(): StationState { + return new StationState(this.states.cloneMessage()); + } +} + +const powerUnlockConfig: MenuItemOptions = { + name: '上电解锁', +}; + +const chainConfig: MenuItemOptions = { + name: '全站设置连锁自动触发', +}; +const removeChainConfig: MenuItemOptions = { + name: '全站取消连锁自动触发', +}; +const StationOperateMenu: ContextMenu = ContextMenu.init({ + name: '车站操作菜单', + groups: [ + { + items: [powerUnlockConfig, chainConfig, removeChainConfig], + }, + ], +}); + +export class StationOperateInteraction extends GraphicInteractionPlugin { + static Name = 'station_operate_menu'; + constructor(app: GraphicApp) { + super(StationOperateInteraction.Name, app); + app.registerMenu(StationOperateMenu); + } + static init(app: GraphicApp) { + return new StationOperateInteraction(app); + } + filter(...grahpics: JlGraphic[]): Station[] | undefined { + return grahpics + .filter((g) => g.type === Station.Type) + .map((g) => g as Station); + } + bind(g: Station): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.selectable = true; + g.on('_rightclick', this.onContextMenu, this); + } + + unbind(g: Station): void { + g.selectable = false; + g.eventMode = 'none'; + g.off('_rightclick', this.onContextMenu, this); + } + + onContextMenu(e: FederatedMouseEvent) { + const target = e.target as DisplayObject; + const station = target.getGraphic() as Station; + this.app.updateSelected(station); + powerUnlockConfig.handler = () => { + station.states.ipRtuStusInLocalCtrl = true; + station.doRepaint(); + }; + chainConfig.handler = () => { + station.states.ipRtuStusDown = true; + station.doRepaint(); + }; + removeChainConfig.handler = () => { + console.log(2222); + }; + StationOperateMenu.open(e.global); + } +} diff --git a/src/drawApp/graphics/StationLineInteraction.ts b/src/drawApp/graphics/StationLineInteraction.ts new file mode 100644 index 0000000..14a22ca --- /dev/null +++ b/src/drawApp/graphics/StationLineInteraction.ts @@ -0,0 +1,55 @@ +import * as pb_1 from 'google-protobuf'; +import { + IStationLineData, + StationLine, +} from 'src/graphics/stationLine/StationLine'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { GraphicDataBase } from './GraphicDataBase'; + +export class StationLineData + extends GraphicDataBase + implements IStationLineData +{ + constructor(data?: graphicData.StationLine) { + let stationLine; + if (!data) { + stationLine = new graphicData.StationLine({ + common: GraphicDataBase.defaultCommonInfo(StationLine.Type), + }); + } else { + stationLine = data; + } + super(stationLine); + } + + public get data(): graphicData.StationLine { + return this.getData(); + } + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get hasTransfer(): boolean { + return this.data.hasTransfer; + } + set hasTransfer(v: boolean) { + this.data.hasTransfer = v; + } + get hideName(): boolean { + return this.data.hideName; + } + set hideName(v: boolean) { + this.data.hideName = v; + } + clone(): StationLineData { + return new StationLineData(this.data.cloneMessage()); + } + copyFrom(data: StationLineData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: StationLineData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} diff --git a/src/drawApp/graphics/TrainInteraction.ts b/src/drawApp/graphics/TrainInteraction.ts new file mode 100644 index 0000000..95d7f42 --- /dev/null +++ b/src/drawApp/graphics/TrainInteraction.ts @@ -0,0 +1,296 @@ +import * as pb_1 from 'google-protobuf'; +import { ITrainData, ITrainState, Train } from 'src/graphics/train/Train'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase'; +import { state } from 'src/protos/device_status'; +import { train } from 'src/protos/train'; +import { MenuItemOptions } from 'src/jl-graphic/ui/Menu'; +import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu'; +import { + GraphicApp, + GraphicInteractionPlugin, + JlGraphic, +} from 'src/jl-graphic'; +import { DisplayObject, FederatedMouseEvent } from 'pixi.js'; + +export class TrainData extends GraphicDataBase implements ITrainData { + constructor(data?: graphicData.Train) { + let train; + if (!data) { + train = new graphicData.Train({ + common: GraphicDataBase.defaultCommonInfo(Train.Type), + }); + } else { + train = data; + } + super(train); + } + + public get data(): graphicData.Train { + return this.getData(); + } + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + clone(): TrainData { + return new TrainData(this.data.cloneMessage()); + } + copyFrom(data: TrainData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: TrainData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} + +export class TrainState extends GraphicStateBase implements ITrainState { + constructor(proto?: StateTrain) { + let states; + if (proto) { + states = proto; + } else { + states = new StateTrain(); + } + super(states, Train.Type); + } + + get states(): StateTrain { + return this.getState(); + } + + get lineId(): number { + return this.states.lineId; + } + set lineId(v: number) { + this.states.lineId = v; + } + get rtuId(): number { + return this.states.rtuId; + } + set rtuId(v: number) { + this.states.rtuId = v; + } + get window(): train.NccWindow { + if (!this.states.window) { + this.states.window = new train.NccWindow(); + } + return this.states.window; + } + set window(v: train.NccWindow) { + this.states.window = v; + } + get devType(): number { + return this.states.devType; + } + set devType(v: number) { + this.states.devType = v; + } + get devName(): string { + return this.states.devName; + } + set devName(v: string) { + this.states.devName = v; + } + get id(): string { + return this.states.id; + } + set id(v: string) { + this.states.id = v; + } + get groupId(): string { + return this.states.groupId; + } + set groupId(v: string) { + this.states.groupId = v; + } + get trainId(): string { + return this.states.trainId; + } + set trainId(v: string) { + this.states.trainId = v; + } + get globalId(): string { + return this.states.globalId; + } + set globalId(v: string) { + this.states.globalId = v; + } + get destinationId(): number { + return this.states.destinationId; + } + set destinationId(v: number) { + this.states.destinationId = v; + } + get rollingStock(): number { + return this.states.rollingStock; + } + set rollingStock(v: number) { + this.states.rollingStock = v; + } + get driverId(): string { + return this.states.driverId; + } + set driverId(v: string) { + this.states.driverId = v; + } + get otpTime(): number { + return this.states.otpTime; + } + set otpTime(v: number) { + this.states.otpTime = v; + } + get mode(): state.TrainMode { + if (!this.states.mode) { + this.states.mode = new state.TrainMode(); + } + return this.states.mode; + } + set mode(v: state.TrainMode) { + this.states.mode = v; + } + get arriveTime(): number { + return this.states.arriveTime; + } + set arriveTime(v: number) { + this.states.arriveTime = v; + } + get departTime(): number { + return this.states.departTime; + } + set departTime(v: number) { + this.states.departTime = v; + } + get speed(): number { + return this.states.speed; + } + set speed(v: number) { + this.states.speed = v; + } + get show(): boolean { + return this.states.show; + } + set show(v: boolean) { + this.states.show = v; + } + get type(): boolean { + return this.states.type; + } + set type(v: boolean) { + this.states.type = v; + } + get routeId(): number { + return this.states.routeId; + } + set routeId(v: number) { + this.states.routeId = v; + } + get rate(): number { + return this.states.rate; + } + set rate(v: number) { + this.states.rate = v; + } + + clone(): TrainState { + return new TrainState(this.states.cloneMessage()); + } +} + +class StateTrain extends train.TrainInfo { + id: string; + constructor(data?: train.TrainInfo) { + super(data); + if (data?.trainIndex) { + this.id = data?.trainIndex; + } else { + this.id = ''; + } + } +} + +const negativeDirectionConfig: MenuItemOptions = { + name: '反方向运行', +}; +const HoldTrainConfig: MenuItemOptions = { + name: '扣车', +}; +const openDoorConfig: MenuItemOptions = { + name: '开门', +}; +const editGroupConfig: MenuItemOptions = { + name: '修改车组号', +}; +const TrainOperateMenu: ContextMenu = ContextMenu.init({ + name: '列车操作菜单', + groups: [ + { + items: [ + negativeDirectionConfig, + HoldTrainConfig, + openDoorConfig, + editGroupConfig, + ], + }, + ], +}); + +export class TrainOperateInteraction extends GraphicInteractionPlugin { + static Name = 'train_operate_menu'; + constructor(app: GraphicApp) { + super(TrainOperateInteraction.Name, app); + app.registerMenu(TrainOperateMenu); + } + static init(app: GraphicApp) { + return new TrainOperateInteraction(app); + } + filter(...grahpics: JlGraphic[]): Train[] | undefined { + return grahpics.filter((g) => g.type === Train.Type).map((g) => g as Train); + } + bind(g: Train): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.selectable = true; + g.on('_rightclick', this.onContextMenu, this); + } + + unbind(g: Train): void { + g.selectable = false; + g.eventMode = 'none'; + g.off('_rightclick', this.onContextMenu, this); + } + + onContextMenu(e: FederatedMouseEvent) { + const target = e.target as DisplayObject; + const train = target.getGraphic() as Train; + this.app.updateSelected(train); + negativeDirectionConfig.handler = () => { + const mode = train.states.mode; + if (!train.states.mode.ipModeTrainDirUp) { + mode.ipModeTrainDirUp = true; + mode.ipModeTrainDirDown = false; + } else if (!train.states.mode.ipModeTrainDirDown) { + mode.ipModeTrainDirUp = false; + mode.ipModeTrainDirDown = true; + } + train.chagneDirection(); + }; + HoldTrainConfig.handler = () => { + train.states.mode.ipModeTrainHolded = + !train.states.mode.ipModeTrainHolded; + train.chagneState(); + }; + openDoorConfig.handler = () => { + train.states.mode.ipModeTrainDoorOpen = + !train.states.mode.ipModeTrainDoorOpen; + train.chagneState(); + }; + editGroupConfig.handler = () => { + train.states.trainId = '022'; + train.doRepaint(); + }; + TrainOperateMenu.open(e.global); + } +} diff --git a/src/drawApp/graphics/TrainLineInteraction.ts b/src/drawApp/graphics/TrainLineInteraction.ts new file mode 100644 index 0000000..b263865 --- /dev/null +++ b/src/drawApp/graphics/TrainLineInteraction.ts @@ -0,0 +1,110 @@ +import * as pb_1 from 'google-protobuf'; +import { + ITrainLineData, + TrainLine, + ITrainLineState, +} from 'src/graphics/trainLine/TrainLine'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { GraphicDataBase, GraphicStateBase } from './GraphicDataBase'; +import { state } from 'src/protos/ws_message'; + +export class TrainLineData extends GraphicDataBase implements ITrainLineData { + constructor(data?: graphicData.TrainLine) { + let fan; + if (data) { + fan = data; + } else { + fan = new graphicData.TrainLine({ + common: GraphicDataBase.defaultCommonInfo(TrainLine.Type), + }); + } + super(fan); + } + + public get data(): graphicData.TrainLine { + return this.getData(); + } + + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + clone(): TrainLineData { + return new TrainLineData(this.data.cloneMessage()); + } + copyFrom(data: TrainLineData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: TrainLineData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} + +export class TrainLineState + extends GraphicStateBase + implements ITrainLineState +{ + constructor(proto?: state.WsLineNetTrainOffsetMessage) { + let states; + if (proto) { + states = proto; + } else { + states = new state.WsLineNetTrainOffsetMessage(); + } + super(states, TrainLine.Type); + } + get code(): string { + return this.states.groupId; + } + get lineId(): number { + return this.states.lineId; + } + set lineId(v: number) { + this.states.lineId = v; + } + get trainIndex(): string { + return this.states.trainIndex; + } + set trainIndex(v: string) { + this.states.trainIndex = v; + } + get groupId(): string { + return this.states.groupId; + } + set groupId(v: string) { + this.states.groupId = v; + } + get show(): boolean { + return this.states.show; + } + set show(v: boolean) { + this.states.show = v; + } + get kilometerCode(): number { + return this.states.kilometerCode; + } + set kilometerCode(v: number) { + this.states.kilometerCode = v; + } + get dir(): number { + return this.states.dir; + } + set dir(v: number) { + this.states.dir = v; + } + + get states(): state.WsLineNetTrainOffsetMessage { + return this.getState(); + } + clone(): TrainLineState { + return new TrainLineState(this.states.cloneMessage()); + } + copyFrom(data: GraphicStateBase): void { + pb_1.Message.copyInto(data._state, this._state); + } + eq(data: GraphicStateBase): boolean { + return pb_1.Message.equals(this._state, data._state); + } +} diff --git a/src/drawApp/graphics/TrainWindowInteraction.ts b/src/drawApp/graphics/TrainWindowInteraction.ts new file mode 100644 index 0000000..bab5372 --- /dev/null +++ b/src/drawApp/graphics/TrainWindowInteraction.ts @@ -0,0 +1,49 @@ +import * as pb_1 from 'google-protobuf'; +import { + ITrainWindowData, + TrainWindow, +} from 'src/graphics/trainWindow/TrainWindow'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { GraphicDataBase } from './GraphicDataBase'; + +export class TrainWindowData + extends GraphicDataBase + implements ITrainWindowData +{ + constructor(data?: graphicData.TrainWindow) { + let trainWindow; + if (!data) { + trainWindow = new graphicData.TrainWindow({ + common: GraphicDataBase.defaultCommonInfo(TrainWindow.Type), + }); + } else { + trainWindow = data; + } + super(trainWindow); + } + + public get data(): graphicData.TrainWindow { + return this.getData(); + } + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get sectionId(): string { + return this.data.sectionId; + } + set sectionId(v: string) { + this.data.sectionId = v; + } + clone(): TrainWindowData { + return new TrainWindowData(this.data.cloneMessage()); + } + copyFrom(data: TrainWindowData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: TrainWindowData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} diff --git a/src/drawApp/graphics/TurnoutInteraction.ts b/src/drawApp/graphics/TurnoutInteraction.ts new file mode 100644 index 0000000..0fa716e --- /dev/null +++ b/src/drawApp/graphics/TurnoutInteraction.ts @@ -0,0 +1,93 @@ +import { ITurnoutData, Turnout } from 'src/graphics/turnout/Turnout'; +import * as pb_1 from 'google-protobuf'; +import { GraphicDataBase } from './GraphicDataBase'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { IPointData } from 'pixi.js'; +import { KilometerSystem } from 'src/graphics/signal/Signal'; + +function getDefaultEndPoint() { + return { + pointA: [new graphicData.Point([50, 0])], + pointB: [new graphicData.Point([-50, 0])], + pointC: [new graphicData.Point([-50, -50])], + }; +} + +export class TurnoutData extends GraphicDataBase implements ITurnoutData { + constructor(data?: graphicData.Turnout) { + let turnout = new graphicData.Turnout(); + if (!data) { + turnout.common = GraphicDataBase.defaultCommonInfo(Turnout.Type); + const p = getDefaultEndPoint(); + turnout.pointA = p.pointA; + turnout.pointB = p.pointB; + turnout.pointC = p.pointC; + } else { + turnout = data; + } + super(turnout); + } + get data(): graphicData.Turnout { + return this.getData(); + } + + get code(): string { + return this.data.code; + } + set code(v: string) { + this.data.code = v; + } + get pointA(): IPointData[] { + return this.data.pointA; + } + set pointA(v: IPointData[]) { + this.data.pointA = v.map((p) => new graphicData.Point({ x: p.x, y: p.y })); + } + get pointB(): IPointData[] { + return this.data.pointB; + } + set pointB(v: IPointData[]) { + this.data.pointB = v.map((p) => new graphicData.Point({ x: p.x, y: p.y })); + } + get pointC(): IPointData[] { + return this.data.pointC; + } + set pointC(v: IPointData[]) { + this.data.pointC = v.map((p) => new graphicData.Point({ x: p.x, y: p.y })); + } + get paRef(): graphicData.RelatedRef { + return this.data.paRef; + } + set paRef(ref: graphicData.RelatedRef) { + this.data.paRef = ref; + } + get pbRef(): graphicData.RelatedRef { + return this.data.pbRef; + } + set pbRef(ref: graphicData.RelatedRef) { + this.data.pbRef = ref; + } + get pcRef(): graphicData.RelatedRef { + return this.data.pcRef; + } + set pcRef(ref: graphicData.RelatedRef) { + this.data.pcRef = ref; + } + get kilometerSystem(): KilometerSystem[] { + return this.data.kilometerSystem; + } + set kilometerSystem(value: KilometerSystem[]) { + this.data.kilometerSystem = value.map( + (v) => new graphicData.KilometerSystem(v) + ); + } + clone(): TurnoutData { + return new TurnoutData(this.data.cloneMessage()); + } + copyFrom(data: TurnoutData): void { + pb_1.Message.copyInto(data.data, this.data); + } + eq(other: TurnoutData): boolean { + return pb_1.Message.equals(this.data, other.data); + } +} diff --git a/src/drawApp/index.ts b/src/drawApp/index.ts new file mode 100644 index 0000000..b45f48e --- /dev/null +++ b/src/drawApp/index.ts @@ -0,0 +1,393 @@ +import { fromUint8Array, toUint8Array } from 'js-base64'; +import { IPointData, Point } from 'pixi.js'; +import { IscsFan } from 'src/graphics/iscs-fan/IscsFan'; +import { Link } from 'src/graphics/link/Link'; +import { LinkDraw } from 'src/graphics/link/LinkDrawAssistant'; +import { Train, TrainTemplate } from 'src/graphics/train/Train'; +import { TrainDraw } from 'src/graphics/train/TrainDrawAssistant'; +import { Signal, SignalTemplate } from 'src/graphics/signal/Signal'; +import { SignalDraw } from 'src/graphics/signal/SignalDrawAssistant'; +import { + CombinationKey, + GraphicApp, + GraphicData, + GraphicTransform, + JlDrawApp, + KeyListener, +} from 'src/jl-graphic'; +import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu'; +import { MenuItemOptions } from 'src/jl-graphic/ui/Menu'; +import { IscsFanData } from './graphics/IscsFanInteraction'; +import { LinkData } from './graphics/LinkInteraction'; +import { TrainData, TrainState } from './graphics/TrainInteraction'; +import { + SignalData, + DrawSignalInteraction, + SignalState, +} from './graphics/SignalInteraction'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { Rect, RectTemplate } from 'src/graphics/rect/Rect'; +import { RectDraw } from 'src/graphics/rect/RectDrawAssistant'; +import { RectData } from './graphics/RectInteraction'; +import { Platform, PlatformTemplate } from 'src/graphics/platform/Platform'; +import { PlatformData, PlatformState } from './graphics/PlatformInteraction'; +import { PlatformDraw } from 'src/graphics/platform/PlatformDrawAssistant'; +import { Station, StationTemplate } from 'src/graphics/station/Station'; +import { StationDraw } from 'src/graphics/station/StationDrawAssistant'; +import { StationData, StationState } from './graphics/StationInteraction'; +import { + StationLine, + StationLineTemplate, +} from 'src/graphics/stationLine/StationLine'; +import { StationLineDraw } from 'src/graphics/stationLine/StationLineDrawAssistant'; +import { StationLineData } from './graphics/StationLineInteraction'; +import { + ItrainLineTemplate, + TrainLine, +} from 'src/graphics/trainLine/TrainLine'; +import { TrainLineDraw } from 'src/graphics/trainLine/TrainLineAssistant'; +import { TrainLineData } from './graphics/TrainLineInteraction'; +import { + OneClickGenerateDraw, + OneClickGenerateTemplate, +} from 'src/graphics/trainWindow/oneClickDrawAssistant'; +import { + TrainWindow, + TrainWindowTemplate, +} from 'src/graphics/trainWindow/TrainWindow'; +import { TrainWindowDraw } from 'src/graphics/trainWindow/TrainWindowDrawAssistant'; +import { TrainWindowData } from './graphics/TrainWindowInteraction'; +import { + AxleCounting, + AxleCountingTemplate, +} from 'src/graphics/axleCounting/AxleCounting'; +import { AxleCountingDraw } from 'src/graphics/axleCounting/AxleCountingDrawAssistant'; +import { AxleCountingData } from './graphics/AxleCountingInteraction'; +import { Turnout, TurnoutTemplate } from 'src/graphics/turnout/Turnout'; +import { TurnoutDraw } from 'src/graphics/turnout/TurnoutDrawAssistant'; +import { TurnoutData } from './graphics/TurnoutInteraction'; +import { RunLine, RunLineTemplate } from 'src/graphics/runLine/RunLine'; +import { RunLineDraw } from 'src/graphics/runLine/RunLineDrawAssistant'; +import { RunLineData, DrawRunLinePlugin } from './graphics/RunLineInteraction'; +import { saveDraft, getDraft } from 'src/api/DraftApi'; +import { useDrawStore } from 'src/stores/draw-store'; +import { successNotify, errorNotify } from '../utils/CommonNotify'; +import { Section, SectionTemplate } from 'src/graphics/section/Section'; +import { SectionDraw } from 'src/graphics/section/SectionDrawAssistant'; +import { SectionData } from './graphics/SectionInteraction'; +import { PathLine, PathLineTemplate } from 'src/graphics/pathLine/PathLine'; +import { PathLineDraw } from 'src/graphics/pathLine/PathLineDrawAssistant'; +import { PathLineData } from './graphics/PathLineInteraction'; +import { toStorageTransform } from './graphics/GraphicDataBase'; +import { SeparatorDraw } from 'src/graphics/separator/SeparatorDrawAssistant'; +import { Separator, SeparatorTemplate } from 'src/graphics/separator/Separator'; +import { SeparatorData } from './graphics/SeparatorInteraction'; + +// export function fromStoragePoint(p: graphicData.Point): Point { +// return new Point(p.x, p.y); +// } + +// export function toStoragePoint(p: IPointData): graphicData.Point { +// return new graphicData.Point({ x: p.x, y: p.y }); +// } + +// export function fromStorageTransfrom( +// transfrom: graphicData.Transform +// ): GraphicTransform { +// return new GraphicTransform( +// fromStoragePoint(transfrom.position), +// fromStoragePoint(transfrom.scale), +// transfrom.rotation, +// fromStoragePoint(transfrom.skew) +// ); +// } + +// export function toStorageTransform( +// transform: GraphicTransform +// ): graphicData.Transform { +// return new graphicData.Transform({ +// position: toStoragePoint(transform.position), +// scale: toStoragePoint(transform.scale), +// rotation: transform.rotation, +// skew: toStoragePoint(transform.skew), +// }); +// } + +const UndoOptions: MenuItemOptions = { + name: '撤销', +}; +const RedoOptions: MenuItemOptions = { + name: '重做', +}; +const SelectAllOptions: MenuItemOptions = { + name: '全选', +}; + +export const DefaultCanvasMenu = new ContextMenu({ + name: '绘制-画布菜单', + groups: [ + { + items: [UndoOptions, RedoOptions], + }, + { + items: [SelectAllOptions], + }, + ], +}); + +let drawApp: JlDrawApp | null = null; + +export function getDrawApp(): JlDrawApp | null { + return drawApp; +} + +export function destroyDrawApp(): void { + if (drawApp) { + drawApp.destroy(); + drawApp = null; + } +} + +export function initDrawApp(dom: HTMLElement): JlDrawApp { + drawApp = new JlDrawApp(dom); + const app = drawApp; + //根据草稿图类型加载绘图工具 + const draftType = useDrawStore().$state.draftType; + let drawAssistants: ( + | PlatformDraw + | StationDraw + | SignalDraw + | TurnoutDraw + | RunLineDraw + | SectionDraw + | StationLineDraw + | RectDraw + | TrainLineDraw + | PathLineDraw + | TrainWindowDraw + | TrainDraw + | OneClickGenerateDraw + | AxleCountingDraw + | SeparatorDraw + )[] = []; + if (draftType === 'Line') { + drawAssistants = [ + new PlatformDraw( + app, + new PlatformTemplate(new PlatformData(), new PlatformState()) + ), + new StationDraw( + app, + new StationTemplate(new StationData(), new StationState()) + ), + new SignalDraw( + app, + new SignalTemplate(new SignalData(), new SignalState()) + ), + new TrainDraw(app, new TrainTemplate(new TrainData(), new TrainState())), + new SectionDraw(app, new SectionTemplate(new SectionData())), + new TurnoutDraw(app, new TurnoutTemplate(new TurnoutData())), + new TrainWindowDraw(app, new TrainWindowTemplate(new TrainWindowData())), + new OneClickGenerateDraw(app, new OneClickGenerateTemplate()), + new AxleCountingDraw( + app, + new AxleCountingTemplate(new AxleCountingData()) + ), + new SeparatorDraw(app, new SeparatorTemplate(new SeparatorData())), + ]; + DrawSignalInteraction.init(app); + } else { + drawAssistants = [ + new StationLineDraw(app, new StationLineTemplate(new StationLineData())), + new RectDraw(app, new RectTemplate(new RectData())), + new RunLineDraw(app, new RunLineTemplate(new RunLineData())), + new TrainLineDraw(app, new ItrainLineTemplate(new TrainLineData())), + new PathLineDraw(app, new PathLineTemplate(new PathLineData())), + ]; + DrawRunLinePlugin.init(app); + } + + app.setOptions({ drawAssistants: drawAssistants }); + + // 画布右键菜单 + app.registerMenu(DefaultCanvasMenu); + app.canvas.on('_rightclick', (e) => { + if (app._drawing) return; + UndoOptions.disabled = !app.opRecord.hasUndo; + RedoOptions.disabled = !app.opRecord.hasRedo; + UndoOptions.handler = () => { + app.opRecord.undo(); + }; + RedoOptions.handler = () => { + app.opRecord.redo(); + }; + SelectAllOptions.handler = () => { + app.selectAllGraphics(); + }; + DefaultCanvasMenu.open(e.global); + }); + app.addKeyboardListener( + new KeyListener({ + value: 'KeyS', + global: true, + combinations: [CombinationKey.Ctrl], + onPress: () => { + saveDrawToServer(app); + }, + }) + ); + return drawApp; +} + +export function saveDrawToServer(app: JlDrawApp) { + const base64 = saveDrawDatas(app); + const drawStore = useDrawStore(); + const id = drawStore.draftId; + if (!id) { + return; + } + saveDraft(id as number, { proto: base64 }) + .then(() => { + successNotify('保存数据成功!'); + }) + .catch((err) => { + errorNotify(err.message, err); + }); +} + +// const StorageKey = 'graphic-storage'; +export function saveDrawDatas(app: JlDrawApp) { + const storage = new graphicData.RtssGraphicStorage(); + const canvasData = app.canvas.saveData(); + storage.canvas = new graphicData.Canvas({ + ...canvasData, + viewportTransform: toStorageTransform(canvasData.viewportTransform), + }); + const graphics = app.queryStore.getAllGraphics(); + graphics.forEach((g) => { + if (Link.Type === g.type) { + const linkData = (g as Link).saveData(); + storage.links.push((linkData as LinkData).data); + } else if (Rect.Type === g.type) { + const rectData = (g as Rect).saveData(); + storage.rects.push((rectData as RectData).data); + } else if (IscsFan.Type === g.type) { + const IscsFanData = (g as IscsFan).saveData(); + storage.iscsFans.push((IscsFanData as IscsFanData).data); + } else if (Platform.Type === g.type) { + const platformData = (g as Platform).saveData(); + storage.Platforms.push((platformData as PlatformData).data); + } else if (Station.Type === g.type) { + const stationData = (g as Station).saveData(); + storage.stations.push((stationData as StationData).data); + } else if (Train.Type === g.type) { + const trainData = (g as Train).saveData(); + storage.train.push((trainData as TrainData).data); + } else if (Turnout.Type === g.type) { + const turnoutData = (g as Turnout).saveData(); + storage.turnouts.push((turnoutData as TurnoutData).data); + } else if (Signal.Type === g.type) { + const signalData = (g as Signal).saveData(); + storage.signals.push((signalData as SignalData).data); + } else if (RunLine.Type === g.type) { + const runLineData = (g as RunLine).saveData(); + storage.runLines.push((runLineData as RunLineData).data); + } else if (Section.Type === g.type) { + const sectionData = (g as Section).saveData(); + storage.section.push((sectionData as SectionData).data); + } else if (StationLine.Type === g.type) { + const stationLineData = (g as StationLine).saveData(); + storage.stationLines.push((stationLineData as StationLineData).data); + } else if (TrainLine.Type === g.type) { + const trainLineData = (g as TrainLine).saveData(); + storage.trainLines.push((trainLineData as TrainLineData).data); + } else if (PathLine.Type === g.type) { + const pathLineData = (g as PathLine).saveData(); + storage.pathLines.push((pathLineData as PathLineData).data); + } else if (TrainWindow.Type === g.type) { + const trainWindowData = (g as TrainWindow).saveData(); + storage.trainWindows.push((trainWindowData as TrainWindowData).data); + } else if (AxleCounting.Type === g.type) { + const axleCountingData = (g as AxleCounting).saveData(); + storage.axleCountings.push((axleCountingData as AxleCountingData).data); + } else if (Separator.Type === g.type) { + const separatorData = (g as Separator).saveData(); + storage.separators.push((separatorData as SeparatorData).data); + } + }); + const base64 = fromUint8Array(storage.serialize()); + console.log('保存数据', storage); + // localStorage.setItem(StorageKey, base64); + return base64; +} + +export async function loadDrawDatas(app: GraphicApp) { + // localStorage.removeItem(StorageKey); + // const base64 = localStorage.getItem(StorageKey); + // console.log('加载数据', base64); + const drawStore = useDrawStore(); + const id = drawStore.draftId; + if (!id) { + return; + } + const { proto: base64 } = await getDraft(id); + if (base64) { + const storage = graphicData.RtssGraphicStorage.deserialize( + toUint8Array(base64) + ); + console.log('加载数据', storage); + app.updateCanvas(storage.canvas); + const datas: GraphicData[] = []; + storage.links.forEach((link) => { + datas.push(new LinkData(link)); + }); + storage.rects.forEach((rect) => { + datas.push(new RectData(rect)); + }); + storage.iscsFans.forEach((fan) => { + datas.push(new IscsFanData(fan)); + }); + storage.Platforms.forEach((platform) => { + datas.push(new PlatformData(platform)); + }); + storage.stations.forEach((station) => { + datas.push(new StationData(station)); + }); + storage.train.forEach((train) => { + datas.push(new TrainData(train)); + }); + storage.turnouts.forEach((turnout) => { + datas.push(new TurnoutData(turnout)); + }); + storage.signals.forEach((signal) => { + datas.push(new SignalData(signal)); + }); + storage.runLines.forEach((runLine) => { + datas.push(new RunLineData(runLine)); + }); + storage.section.forEach((section) => { + datas.push(new SectionData(section)); + }); + storage.stationLines.forEach((stationLine) => { + datas.push(new StationLineData(stationLine)); + }); + storage.trainLines.forEach((trainLine) => { + datas.push(new TrainLineData(trainLine)); + }); + storage.pathLines.forEach((pathLine) => { + datas.push(new PathLineData(pathLine)); + }); + storage.trainWindows.forEach((trainWindow) => { + datas.push(new TrainWindowData(trainWindow)); + }); + storage.axleCountings.forEach((axleCounting) => { + datas.push(new AxleCountingData(axleCounting)); + }); + storage.separators.forEach((separator) => { + datas.push(new SeparatorData(separator)); + }); + app.loadGraphic(datas); + } else { + app.loadGraphic([]); + } +} diff --git a/src/drawApp/lineApp.ts b/src/drawApp/lineApp.ts new file mode 100644 index 0000000..c8ac63c --- /dev/null +++ b/src/drawApp/lineApp.ts @@ -0,0 +1,137 @@ +import { + GraphicApp, + GraphicData, + StompCli, + AppWsMsgBroker, + GraphicState, +} from 'src/jl-graphic'; +import { TrainData, TrainState } from './graphics/TrainInteraction'; +import { TrainTemplate } from 'src/graphics/train/Train'; +import { + SignalData, + SignalOperateInteraction, + SignalState, +} from './graphics/SignalInteraction'; +import { SignalTemplate, Signal } from 'src/graphics/signal/Signal'; +import { + PlatformData, + PlatformOperateInteraction, + PlatformState, +} from './graphics/PlatformInteraction'; +import { PlatformTemplate, Platform } from 'src/graphics/platform/Platform'; +import { StationData, StationState } from './graphics/StationInteraction'; +import { StationTemplate } from 'src/graphics/station/Station'; +import { TurnoutData } from './graphics/TurnoutInteraction'; +import { TurnoutTemplate } from 'src/graphics/turnout/Turnout'; +import { SectionData } from './graphics/SectionInteraction'; +import { SectionTemplate } from 'src/graphics/section/Section'; +import { getPublishMapInfoByLineId } from 'src/api/PublishApi'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { useLineStore } from 'src/stores/line-store'; +import { toUint8Array } from 'js-base64'; +import { getWebsocketUrl } from 'src/configs/UrlManage'; +import { getJwtToken } from 'src/configs/TokenManage'; +import { state } from 'src/protos/ws_message'; + +let lineApp: GraphicApp | null = null; +let msgBroker: AppWsMsgBroker | null = null; + +export function getLineApp(): GraphicApp | null { + return lineApp; +} + +export function destroyLineApp(): void { + if (lineApp) { + lineApp.destroy(); + lineApp = null; + } + if (msgBroker) { + msgBroker.close(); + } +} + +export function initLineApp(dom: HTMLElement): GraphicApp { + lineApp = new GraphicApp(dom); + const graphicTemplate = [ + new TrainTemplate(new TrainData(), new TrainState()), + new SignalTemplate(new SignalData(), new SignalState()), + new PlatformTemplate(new PlatformData(), new PlatformState()), + new StationTemplate(new StationData(), new StationState()), + new TurnoutTemplate(new TurnoutData()), + new SectionTemplate(new SectionData()), + ]; + lineApp.registerGraphicTemplates(...graphicTemplate); + lineApp.setOptions({ + mouseToolOptions: { + boxSelect: false, + viewportDrag: true, + wheelZoom: true, + }, + interactiveTypeOptions: { + interactiveGraphicTypeIncludes: [Signal.Type, Platform.Type], + }, + }); + SignalOperateInteraction.init(lineApp); + PlatformOperateInteraction.init(lineApp); + return lineApp; +} + +export async function loadLineDatas(app: GraphicApp) { + const lineStore = useLineStore(); + const lineId = lineStore.lineId; + if (!lineId) { + return; + } + const { proto: base64, name: lineName } = await getPublishMapInfoByLineId( + lineId, + 'line' + ); + lineStore.setLineName(lineName); + if (base64) { + const storage = graphicData.RtssGraphicStorage.deserialize( + toUint8Array(base64) + ); + console.log('加载数据', storage); + app.updateCanvas(storage.canvas); + const datas: GraphicData[] = []; + storage.Platforms.forEach((platform) => { + const g = new PlatformData(platform); + datas.push(g); + }); + storage.stations.forEach((station) => { + datas.push(new StationData(station)); + }); + storage.train.forEach((train) => { + datas.push(new TrainData(train)); + }); + storage.turnouts.forEach((turnout) => { + datas.push(new TurnoutData(turnout)); + }); + storage.signals.forEach((signal) => { + datas.push(new SignalData(signal)); + }); + storage.section.forEach((section) => { + datas.push(new SectionData(section)); + }); + await app.loadGraphic(datas); + + StompCli.new({ + wsUrl: `${getWebsocketUrl()}`, + token: getJwtToken() as string, + }); + msgBroker = new AppWsMsgBroker(app); + const states: GraphicState[] = []; + msgBroker.subscribe({ + destination: `/queue/line/${lineId}/device`, + messageConverter: (message: Uint8Array) => { + const storage = state.WsLineMessage.deserialize(message); + storage.signal.forEach((item) => { + states.push(new SignalState(item)); + }); + return states; + }, + }); + } else { + app.loadGraphic([]); + } +} diff --git a/src/drawApp/lineNetApp.ts b/src/drawApp/lineNetApp.ts new file mode 100644 index 0000000..1b950dd --- /dev/null +++ b/src/drawApp/lineNetApp.ts @@ -0,0 +1,132 @@ +import { + GraphicApp, + GraphicData, + StompCli, + AppWsMsgBroker, + GraphicState, +} from 'src/jl-graphic'; +import { getPublishLineNet } from 'src/api/PublishApi'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { state } from 'src/protos/ws_message'; + +import { RunLine, RunLineTemplate } from 'src/graphics/runLine/RunLine'; +import { + RunLineData, + RunLineOperateInteraction, +} from './graphics/RunLineInteraction'; +import { PathLineTemplate, PathLine } from 'src/graphics/pathLine/PathLine'; +import { PathLineData } from './graphics/PathLineInteraction'; +import { + StationLineTemplate, + StationLine, +} from 'src/graphics/stationLine/StationLine'; +import { StationLineData } from './graphics/StationLineInteraction'; +import { ItrainLineTemplate } from 'src/graphics/trainLine/TrainLine'; +import { TrainLineData, TrainLineState } from './graphics/TrainLineInteraction'; +import { RectTemplate } from 'src/graphics/rect/Rect'; +import { RectData } from './graphics/RectInteraction'; + +import { useLineNetStore } from 'src/stores/line-net-store'; +import { toUint8Array } from 'js-base64'; +import { getWebsocketUrl } from 'src/configs/UrlManage'; +import { getJwtToken } from 'src/configs/TokenManage'; + +let lineNetApp: GraphicApp | null = null; +let msgBroker: AppWsMsgBroker | null = null; + +export function getLineNetApp(): GraphicApp | null { + return lineNetApp; +} + +export function destroyLineNetApp(): void { + if (lineNetApp) { + lineNetApp.destroy(); + lineNetApp = null; + } + if (msgBroker) { + msgBroker.close(); + } +} + +export function initLineNetApp(dom: HTMLElement): GraphicApp { + lineNetApp = new GraphicApp(dom); + const graphicTemplate = [ + new RunLineTemplate(new RunLineData()), + new PathLineTemplate(new PathLineData()), + new StationLineTemplate(new StationLineData()), + new ItrainLineTemplate(new TrainLineData(), new TrainLineState()), + new RectTemplate(new RectData()), + ]; + lineNetApp.registerGraphicTemplates(...graphicTemplate); + lineNetApp.setOptions({ + mouseToolOptions: { + boxSelect: false, + viewportDrag: true, + wheelZoom: true, + }, + interactiveTypeOptions: { + interactiveGraphicTypeIncludes: [RunLine.Type, StationLine.Type], + }, + }); + RunLineOperateInteraction.init(lineNetApp); + return lineNetApp; +} + +export async function loadLineNetDatas(app: GraphicApp) { + const lineNetStore = useLineNetStore(); + const { proto: base64, name: lineNetName } = await getPublishLineNet(); + lineNetStore.setLineNetName(lineNetName); + if (base64) { + const storage = graphicData.RtssGraphicStorage.deserialize( + toUint8Array(base64) + ); + console.log('加载数据', storage); + app.updateCanvas(storage.canvas); + const datas: GraphicData[] = []; + storage.runLines.forEach((runLine) => { + const g = new RunLineData(runLine); + datas.push(g); + }); + storage.pathLines.forEach((pathLine) => { + const g = new PathLineData(pathLine); + datas.push(g); + }); + storage.stationLines.forEach((stationLine) => { + const g = new StationLineData(stationLine); + datas.push(g); + }); + storage.trainLines.forEach((trainLine) => { + const g = new TrainLineData(trainLine); + datas.push(g); + }); + storage.rects.forEach((rect) => { + const g = new RectData(rect); + datas.push(g); + }); + await app.loadGraphic(datas); + const pathLineList = app.queryStore.queryByType(PathLine.Type); + pathLineList.forEach((pathLine) => { + pathLine.visible = false; + }); + + StompCli.new({ + wsUrl: `${getWebsocketUrl()}`, + token: getJwtToken() as string, + }); + msgBroker = new AppWsMsgBroker(app); + const states: GraphicState[] = []; + msgBroker.subscribe({ + destination: '/queue/lineNet', + messageConverter: (message: Uint8Array) => { + const storage = state.WsLineNetMessage.deserialize(message); + console.log(storage, 'storage'); + storage.offset.forEach((item) => { + states.push(new TrainLineState(item)); + }); + return states; + }, + }); + } else { + app.loadGraphic([]); + } +} diff --git a/src/env.d.ts b/src/env.d.ts new file mode 100644 index 0000000..dd757b1 --- /dev/null +++ b/src/env.d.ts @@ -0,0 +1,9 @@ +/* eslint-disable */ + +declare namespace NodeJS { + interface ProcessEnv { + NODE_ENV: string; + VUE_ROUTER_MODE: 'hash' | 'history' | 'abstract' | undefined; + VUE_ROUTER_BASE: string | undefined; + } +} diff --git a/src/graphics/CommonGraphics.ts b/src/graphics/CommonGraphics.ts new file mode 100644 index 0000000..58777ff --- /dev/null +++ b/src/graphics/CommonGraphics.ts @@ -0,0 +1,116 @@ +import { Graphics } from 'pixi.js'; +import { calculateMirrorPoint } from 'src/jl-graphic'; +import { graphicData } from 'src/protos/stationLayoutGraphics'; +import { Turnout, TurnoutPort } from './turnout/Turnout'; +import { Section, SectionPort } from './section/Section'; +import { TrainWindow } from './trainWindow/TrainWindow'; +import { AxleCounting } from './axleCounting/AxleCounting'; +/** + * + * @param polygon + * @param x 箭头顶点x坐标 + * @param y 箭头顶点y坐标 + * @param length 箭头长度 + * @param radius 箭头三角半径 + * @param lineWidth 箭头线宽 + * @param mirror 是否镜像翻转 (基于箭头顶点) + */ +export function drawArrow( + polygon: Graphics, + x: number, + y: number, + length: number, + radius: number, + lineWidth: number, + mirror: boolean +) { + const trianglAcme = { x, y }; + let triangleP1 = { + x: x - radius - Math.sin(Math.PI / 6), + y: y + Math.cos(Math.PI / 6) * radius, + }; + let triangleP2 = { + x: x - radius - Math.sin(Math.PI / 6), + y: y - Math.cos(Math.PI / 6) * radius, + }; + let lineP1 = { + x: x - radius - Math.sin(Math.PI / 6), + y: y + lineWidth / 2, + }; + let lineP2 = { + x: x - length, + y: y + lineWidth / 2, + }; + let lineP3 = { + x: x - length, + y: y - lineWidth / 2, + }; + let lineP4 = { + x: x - radius - Math.sin(Math.PI / 6), + y: y - lineWidth / 2, + }; + if (mirror) { + triangleP1 = calculateMirrorPoint(trianglAcme, triangleP1); + triangleP2 = calculateMirrorPoint(trianglAcme, triangleP2); + lineP1 = calculateMirrorPoint(trianglAcme, lineP1); + lineP2 = calculateMirrorPoint(trianglAcme, lineP2); + lineP3 = calculateMirrorPoint(trianglAcme, lineP3); + lineP4 = calculateMirrorPoint(trianglAcme, lineP4); + } + polygon.drawPolygon( + trianglAcme.x, + trianglAcme.y, + triangleP1.x, + triangleP1.y, + lineP1.x, + lineP1.y, + lineP2.x, + lineP2.y, + lineP3.x, + lineP3.y, + lineP4.x, + lineP4.y, + triangleP2.x, + triangleP2.y + ); +} + +export function createRelatedRefProto( + type: string, + id: string, + port?: TurnoutPort | SectionPort +) { + const typeMap = new Map([ + [Section.Type, graphicData.RelatedRef.DeviceType.Section], + [Turnout.Type, graphicData.RelatedRef.DeviceType.Turnout], + [TrainWindow.Type, graphicData.RelatedRef.DeviceType.TrainWindow], + [AxleCounting.Type, graphicData.RelatedRef.DeviceType.AxleCounting], + ]); + const protoDeviceType = typeMap.get(type); + if (protoDeviceType === undefined) throw Error(`输入的type有误: ${type}`); + const protoData = new graphicData.RelatedRef({ + deviceType: protoDeviceType, + id, + }); + if (port) { + if (port === 'A') + protoData.devicePort = graphicData.RelatedRef.DevicePort.A; + if (port === 'B') + protoData.devicePort = graphicData.RelatedRef.DevicePort.B; + if (port === 'C') + protoData.devicePort = graphicData.RelatedRef.DevicePort.C; + } + return protoData; +} + +export function protoPort2Data(port: graphicData.RelatedRef.DevicePort) { + if (port === graphicData.RelatedRef.DevicePort.A) return 'A'; + if (port === graphicData.RelatedRef.DevicePort.B) return 'B'; + if (port === graphicData.RelatedRef.DevicePort.C) return 'C'; +} + +export interface IRelatedRefData { + deviceType: graphicData.RelatedRef.DeviceType; //关联的设备类型 + id: string; //关联的设备ID + devicePort: graphicData.RelatedRef.DevicePort; //关联的设备端口 +} diff --git a/src/graphics/axleCounting/AxleCounting.ts b/src/graphics/axleCounting/AxleCounting.ts new file mode 100644 index 0000000..5538fb9 --- /dev/null +++ b/src/graphics/axleCounting/AxleCounting.ts @@ -0,0 +1,116 @@ +import { Color, Container, Graphics } from 'pixi.js'; +import { + GraphicData, + GraphicRelationParam, + JlGraphic, + JlGraphicTemplate, + VectorText, +} from 'src/jl-graphic'; +import { IRelatedRefData, protoPort2Data } from '../CommonGraphics'; +import { KilometerSystem } from '../signal/Signal'; + +export interface IAxleCountingData extends GraphicData { + get code(): string; // 编号 + set code(v: string); + get kilometerSystem(): KilometerSystem; + set kilometerSystem(v: KilometerSystem); + get axleCountingRef(): IRelatedRefData[]; //关联的设备 + set axleCountingRef(ref: IRelatedRefData[]); + clone(): IAxleCountingData; + copyFrom(data: IAxleCountingData): void; + eq(other: IAxleCountingData): boolean; +} + +export const AxleCountingConsts = { + radius: 6, + borderWidth: 1, + circleColorBlue: '0x08F80D', + codeColor: '0xF48815', + codeFontSize: 22, + codeOffsetY: 30, + kilometerCodeColor: '0xFFFFFF', + kilometerCodeFontSize: 14, + kilometerCodeOffsetY: 95, + offsetSection: 50, +}; +class TwoCircleGraphic extends Container { + circleA: Graphics = new Graphics(); + circleB: Graphics = new Graphics(); + line: Graphics = new Graphics(); + constructor() { + super(); + this.addChild(this.circleA); + this.addChild(this.circleB); + this.addChild(this.line); + } + draw(): void { + this.drawCircle(this.circleA); + this.drawCircle(this.circleB); + this.circleA.position.set(-12, 0); + this.circleB.position.set(12, 0); + this.line.clear(); + this.line.lineStyle(1, new Color(AxleCountingConsts.circleColorBlue)); + this.line.moveTo(-24, 0); + this.line.lineTo(24, 0); + } + drawCircle(circle: Graphics): void { + circle.clear(); + circle.lineStyle( + AxleCountingConsts.borderWidth, + new Color(AxleCountingConsts.circleColorBlue) + ); + circle.beginFill(AxleCountingConsts.circleColorBlue, 1); + circle.drawCircle(0, 0, AxleCountingConsts.radius); + circle.endFill; + } + clear(): void { + this.circleA.clear(); + this.circleB.clear(); + } +} +export class AxleCounting extends JlGraphic { + static Type = 'AxleCounting'; + twoCircle: TwoCircleGraphic = new TwoCircleGraphic(); + kilometerGraph: VectorText = new VectorText(''); //公里标 + direction: number; + constructor(direction: number) { + super(AxleCounting.Type); + this.addChild(this.twoCircle); + this.addChild(this.kilometerGraph); + this.kilometerGraph.name = 'kilometer'; + this.direction = direction; + } + + get datas(): IAxleCountingData { + return this.getDatas(); + } + doRepaint(): void { + this.twoCircle.draw(); + } + loadRelations(): void { + if (this.datas.axleCountingRef.length) { + this.datas.axleCountingRef.forEach((device) => { + this.relationManage.addRelation( + new GraphicRelationParam(this, 'A'), + new GraphicRelationParam( + this.queryStore.queryById(device.id), + protoPort2Data(device.devicePort) + ) + ); + }); + } + } +} + +export class AxleCountingTemplate extends JlGraphicTemplate { + constructor(dataTemplate: IAxleCountingData) { + super(AxleCounting.Type, { + dataTemplate, + }); + } + new(): AxleCounting { + const axleCounting = new AxleCounting(1); + axleCounting.loadData(this.datas); + return axleCounting; + } +} diff --git a/src/graphics/axleCounting/AxleCountingDrawAssistant.ts b/src/graphics/axleCounting/AxleCountingDrawAssistant.ts new file mode 100644 index 0000000..b7b38b7 --- /dev/null +++ b/src/graphics/axleCounting/AxleCountingDrawAssistant.ts @@ -0,0 +1,394 @@ +import { FederatedPointerEvent, IPoint, Point } from 'pixi.js'; +import { + AbsorbableLine, + AbsorbablePosition, + GraphicDrawAssistant, + GraphicIdGenerator, + GraphicInteractionPlugin, + JlDrawApp, + JlGraphic, + distance2, +} from 'src/jl-graphic'; + +import { + IAxleCountingData, + AxleCounting, + AxleCountingTemplate, + AxleCountingConsts, +} from './AxleCounting'; +import { Section, SectionPort, SectionType } from '../section/Section'; +import { Turnout, TurnoutPort } from '../turnout/Turnout'; +import { IRelatedRefData, createRelatedRefProto } from '../CommonGraphics'; +import { Signal } from '../signal/Signal'; + +export interface IAxleCountingDrawOptions { + newData: () => IAxleCountingData; +} + +enum DevicePort { + A = 0, + B = 1, + C = 2, +} + +enum DevicePortN { + A, + B, + C, +} + +export class AxleCountingDraw extends GraphicDrawAssistant< + AxleCountingTemplate, + IAxleCountingData +> { + codeGraph: AxleCounting; + constructor(app: JlDrawApp, template: AxleCountingTemplate) { + super(app, template, 'sym_o_circle', '不展示'); + this.codeGraph = this.graphicTemplate.new(); + this.container.addChild(this.codeGraph); + AxleCountingInteraction.init(app); + } + + bind(): void { + super.bind(); + this.codeGraph.loadData(this.graphicTemplate.datas); + this.codeGraph.doRepaint(); + } + + clearCache(): void { + //this.codeGraph.destroy(); + } + onLeftDown(e: FederatedPointerEvent): void { + this.container.position.copyFrom(this.toCanvasCoordinates(e.global)); + this.createAndStore(true); + } + + redraw(p: Point): void { + this.container.position.copyFrom(p); + } + prepareData(data: IAxleCountingData): boolean { + data.transform = this.container.saveTransform(); + return true; + } + draw( + ps: IPoint, + direction: number, + graphic: Section | Turnout, + port: TurnoutPort | SectionPort, + map: Map, + reftype: string, + refGraphic: Section | Turnout, + refPort: TurnoutPort | SectionPort + ) { + if ( + graphic.type == 'Turnout' && + reftype == 'Turnout' && + port == TurnoutPort.B && + refPort == TurnoutPort.B + ) { + const points = (graphic as Turnout).getPortPoints(); + const portPs = graphic.localToCanvasPoints(points[1][0])[0]; + let hasSingle = false; + const singles = this.app.queryStore.queryByType(Signal.Type); + singles.forEach((single) => { + if (distance2(portPs, single.position) < 50) { + hasSingle = true; + } + }); + if (!hasSingle) { + map.set(`${graphic.id}-${port}`, 1); + map.set(`${refGraphic.id}-${refPort}`, 1); + return; + } + } + + if ( + !map.has(`${refGraphic.id}-${refPort}`) && + !map.has(`${graphic.id}-${port}`) + ) { + map.set(`${graphic.id}-${port}`, 1); + map.set(`${refGraphic.id}-${refPort}`, 1); + const refData1 = createRelatedRefProto(reftype, refGraphic.id, refPort); + const refData2 = createRelatedRefProto(graphic.type, graphic.id, port); + const axleCounting = new AxleCounting(direction); + axleCounting.loadData(this.graphicTemplate.datas); + if (graphic.type == 'Turnout') { + axleCounting.position.set(ps.x, ps.y); + } else { + axleCounting.position.set( + ps.x, + ps.y - AxleCountingConsts.offsetSection * direction + ); + } + axleCounting.id = GraphicIdGenerator.next(); + axleCounting.datas.axleCountingRef = [refData2, refData1]; + axleCounting.datas.code = `${graphic.datas.code}-${port}+${refGraphic.datas.code}-${refPort}`; + this.storeGraphic(axleCounting); + axleCounting.loadRelations(); + } + } + drawAdd( + ps: IPoint, + direction: number, + graphic: Section | Turnout, + port: TurnoutPort | SectionPort, + map: Map + ) { + if (!map.has(`${graphic.id}-${port}`)) { + map.set(`${graphic.id}-${port}`, 1); + const refData = createRelatedRefProto(graphic.type, graphic.id, port); + const axleCounting = new AxleCounting(direction); + axleCounting.loadData(this.graphicTemplate.datas); + if (graphic.type == 'Turnout') { + axleCounting.position.set(ps.x, ps.y); + } else { + axleCounting.position.set( + ps.x, + ps.y - AxleCountingConsts.offsetSection * direction + ); + } + axleCounting.id = GraphicIdGenerator.next(); + axleCounting.datas.axleCountingRef = [refData]; + axleCounting.datas.code = `${graphic.datas.code}-${port}`; + this.storeGraphic(axleCounting); + axleCounting.loadRelations(); + } + } + oneGenerates(height: Point) { + const map = new Map(); + const axleCountings = this.app.queryStore.queryByType( + AxleCounting.Type + ); + const axleCountingRefs: IRelatedRefData[] = []; + axleCountings.forEach((axleCounting) => { + axleCountingRefs.push(...axleCounting.datas.axleCountingRef); + }); + axleCountingRefs.forEach((axleCountingRef) => { + map.set( + `${axleCountingRef.id}-${DevicePortN[axleCountingRef.devicePort]}`, + 1 + ); + }); + //由区段生成计轴--区段和区段 + const sections = this.app.queryStore + .queryByType
(Section.Type) + .filter((section) => { + return ( + section.relationManage.getRelationsOfGraphicAndOtherType( + section, + AxleCounting.Type + ).length < 2 + ); + }); + + sections.forEach((section) => { + const sectionRelations = + section.relationManage.getRelationsOfGraphic(section); + const ps = section.localToCanvasPoint(section.getStartPoint()); + const pe = section.localToCanvasPoint(section.getEndPoint()); + sectionRelations.forEach((relation) => { + const port = relation.getRelationParam(section).param; + const refDevice = relation.getOtherGraphic
(section); + const refDevicePort = relation.getOtherRelationParam(section).param; + let direction = 1; + let axleCountingPs = ps; + if (port == 'B') { + axleCountingPs = pe; + } + if (axleCountingPs.y > height.y) { + direction = -1; + } + if ( + section.datas.sectionType === SectionType.Logic || + section.datas.children.includes(refDevice.id) + ) { + return; + } + if (refDevice.type == Section.Type || refDevice.type == Turnout.Type) + this.draw( + axleCountingPs, + direction, + section, + port, + map, + refDevice.type, + refDevice, + refDevicePort + ); + }); + }); + //由区段生成计轴--单独区段 + sections.forEach((section) => { + const axleCountingRelations = + section.relationManage.getRelationsOfGraphicAndOtherType( + section, + AxleCounting.Type + ); + const ps = section.localToCanvasPoint(section.getStartPoint()); + const pe = section.localToCanvasPoint(section.getEndPoint()); + if (axleCountingRelations.length < 2) { + axleCountingRelations.forEach((relation) => { + const port = relation.getRelationParam(section).param; + let addPort = SectionPort.A; + let direction = 1; + let axleCountingPs = ps; + if (port == 'A') { + axleCountingPs = pe; + addPort = SectionPort.B; + } + if (axleCountingPs.y > height.y) { + direction = -1; + } + if (axleCountingPs.y > height.y) { + direction = -1; + } + this.drawAdd(axleCountingPs, direction, section, addPort, map); + }); + } + }); + + //由道岔生成计轴--道岔和道岔 + const turnouts = this.app.queryStore + .queryByType(Turnout.Type) + .filter((turnout) => { + return ( + turnout.relationManage.getRelationsOfGraphicAndOtherType( + turnout, + AxleCounting.Type + ).length < 3 + ); + }); + turnouts.forEach((turnout) => { + const points = turnout.getPortPoints(); + //道岔关联的道岔 + const turnoutRelations = + turnout.relationManage.getRelationsOfGraphicAndOtherType( + turnout, + Turnout.Type + ); + turnoutRelations.forEach((relation) => { + const port = relation.getRelationParam(turnout).param; + const portIndex = DevicePort[port] as unknown as number; + const refTurnout = relation.getOtherGraphic(turnout); + const refTurnoutPort = relation.getOtherRelationParam(turnout).param; + const portPs = turnout.localToCanvasPoints(...points[portIndex])[ + points[portIndex].length - 1 + ]; + this.draw( + portPs, + 1, + turnout, + port, + map, + Turnout.Type, + refTurnout, + refTurnoutPort + ); + }); + }); + //由道岔生成计轴--单独道岔 + turnouts.forEach((turnout) => { + const axleCountingRelations = + turnout.relationManage.getRelationsOfGraphicAndOtherType( + turnout, + AxleCounting.Type + ); + const points = turnout.getPortPoints(); + const turnoutPort = [TurnoutPort.A, TurnoutPort.B, TurnoutPort.C]; + if (axleCountingRelations.length == 1) { + const port = axleCountingRelations[0].getRelationParam(turnout).param; + const otherPort = turnoutPort.filter((p) => { + return p !== port && p; + }); + otherPort.forEach((port) => { + const portIndex = DevicePort[port] as unknown as number; + const axleCountingPs1 = turnout.localToCanvasPoints( + ...points[portIndex] + )[points[portIndex].length - 1]; + this.drawAdd(axleCountingPs1, 1, turnout, port, map); + }); + } else if (axleCountingRelations.length == 2) { + const port = axleCountingRelations.map( + (item) => item.getRelationParam(turnout).param + ); + const otherPort = turnoutPort.filter((p) => { + return p !== port[0] && p !== port[1] && p; + }); + if (otherPort.length) { + const portIndex = DevicePort[otherPort[0]] as unknown as number; + const axleCountingPs1 = turnout.localToCanvasPoints( + ...points[portIndex] + )[points[portIndex].length - 1]; + this.drawAdd(axleCountingPs1, 1, turnout, otherPort[0], map); + } + } else if (axleCountingRelations.length == 0) { + const axleCountingPsA = turnout.localToCanvasPoints(points[0][0])[0]; + const axleCountingPsC = turnout.localToCanvasPoints(points[2][0])[0]; + this.drawAdd(axleCountingPsA, 1, turnout, TurnoutPort.A, map); + this.drawAdd(axleCountingPsC, 1, turnout, TurnoutPort.C, map); + } + }); + } +} + +function buildAbsorbablePositions( + axleCounting: AxleCounting +): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + const axleCountings = axleCounting.queryStore.queryByType( + AxleCounting.Type + ); + const { width } = axleCounting.getGraphicApp().canvas; + axleCountings.forEach((other) => { + if (other.id == axleCounting.id) { + return; + } + const ps = other.datas.transform.position; + const xs = new AbsorbableLine({ x: 0, y: ps.y }, { x: width, y: ps.y }); + aps.push(xs); + }); + return aps; +} + +export class AxleCountingInteraction extends GraphicInteractionPlugin { + static Name = 'AxleCounting_transform'; + constructor(app: JlDrawApp) { + super(AxleCountingInteraction.Name, app); + } + static init(app: JlDrawApp) { + return new AxleCountingInteraction(app); + } + filter(...grahpics: JlGraphic[]): AxleCounting[] | undefined { + return grahpics + .filter((g) => g.type === AxleCounting.Type) + .map((g) => g as AxleCounting); + } + bind(g: AxleCounting): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.scalable = true; + g.rotatable = true; + g.kilometerGraph.eventMode = 'static'; + g.kilometerGraph.cursor = 'pointer'; + g.kilometerGraph.draggable = true; + g.kilometerGraph.selectable = true; + g.kilometerGraph.transformSave = true; + g.on('selected', this.onSelected, this); + } + unbind(g: AxleCounting): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + g.kilometerGraph.eventMode = 'none'; + g.kilometerGraph.draggable = false; + g.kilometerGraph.selectable = false; + g.kilometerGraph.transformSave = false; + g.off('selected', this.onSelected, this); + } + onSelected(): void { + const AxleCounting = this.app.selectedGraphics[0] as AxleCounting; + this.app.setOptions({ + absorbablePositions: buildAbsorbablePositions(AxleCounting), + }); + } +} diff --git a/src/graphics/iscs-fan/IscsFan.ts b/src/graphics/iscs-fan/IscsFan.ts new file mode 100644 index 0000000..1c2df37 --- /dev/null +++ b/src/graphics/iscs-fan/IscsFan.ts @@ -0,0 +1,125 @@ +import { + GraphicAnimation, + GraphicData, + JlGraphic, + JlGraphicTemplate, +} from 'src/jl-graphic'; +import ISCS_FAN_Assets from './iscs-fan-spritesheet.png'; +import ISCS_FAN_JSON from './iscs-fan-data.json'; + +import { Assets, Sprite, Spritesheet, Texture } from 'pixi.js'; + +interface FanTextures { + border: Texture; + blue: Texture; + gray: Texture; + green: Texture; + red: Texture; + yellow: Texture; +} + +export interface IIscsFanData extends GraphicData { + get code(): string; + set code(v: string); +} + +export class IscsFan extends JlGraphic { + static Type = 'IscsFan'; + _border: Sprite; + _fan: Sprite; + fanTextures: FanTextures; + __state = 0; + + constructor(fanTextures: FanTextures) { + super(IscsFan.Type); + this.fanTextures = fanTextures; + this._border = new Sprite(); + this._border.texture = this.fanTextures.border; + this._border.anchor.set(0.5); + this._fan = new Sprite(); + this._fan.texture = this.fanTextures.gray; + this._fan.anchor.set(0.5); + this.addChild(this._border); + this.addChild(this._fan); + } + doRepaint(): void { + if (this.__state === 0) { + // 停止 + this.stopFanRun(); + this._fan.rotation = 0; + this._fan.texture = this.fanTextures.gray; + } else if (this.__state === 1) { + // 正常运行 + this._fan.texture = this.fanTextures.green; + // 动画 + this.initFanRun(); + } else if (this.__state === 2) { + // 报警运行 + this._fan.texture = this.fanTextures.yellow; + // 动画 + this.initFanRun(); + } else if (this.__state === 3) { + // 故障 + this.stopFanRun(); + this._fan.rotation = 0; + this._fan.texture = this.fanTextures.red; + } else if (this.__state === 4) { + // 通信故障 + // 停止 + this.stopFanRun(); + this._fan.rotation = 0; + this._fan.texture = this.fanTextures.blue; + } + } + initFanRun() { + // 动画 + const name = 'fan_run'; + let fanRun = this.animation(name); + if (!fanRun) { + fanRun = GraphicAnimation.init({ + name: 'fan_run', + run: (dt: number) => { + this._fan.angle = (this._fan.angle + dt) % 360; + }, + }); + this.addAnimation(fanRun); + } + const speed = Math.round(Math.random() * 10) + 1; + fanRun.xSpeed = speed; + fanRun.resume(); + } + stopFanRun() { + const name = 'fan_run'; + const fanRun = this.animation(name); + if (fanRun) { + fanRun.pause(); + } + } +} + +export class IscsFanTemplate extends JlGraphicTemplate { + fanTextures?: FanTextures; + constructor() { + super(IscsFan.Type, {}); + } + new(): IscsFan { + if (this.fanTextures) { + return new IscsFan(this.fanTextures); + } + throw new Error('资源未加载/加载失败'); + } + async loadAssets(): Promise { + const texture = await Assets.load(ISCS_FAN_Assets); + const iscsFanSheet = new Spritesheet(texture, ISCS_FAN_JSON); + const result = await iscsFanSheet.parse(); + this.fanTextures = { + border: result['fan-border.png'], + blue: result['fan-blue.png'], + gray: result['fan-gray.png'], + green: result['fan-green.png'], + red: result['fan-red.png'], + yellow: result['fan-yellow.png'], + }; + return this.fanTextures as FanTextures; + } +} diff --git a/src/graphics/iscs-fan/IscsFanDrawAssistant.ts b/src/graphics/iscs-fan/IscsFanDrawAssistant.ts new file mode 100644 index 0000000..709a37a --- /dev/null +++ b/src/graphics/iscs-fan/IscsFanDrawAssistant.ts @@ -0,0 +1,77 @@ +import { FederatedMouseEvent, Point } from 'pixi.js'; +import { + GraphicDrawAssistant, + GraphicInteractionPlugin, + JlDrawApp, + JlGraphic, +} from 'src/jl-graphic'; +import { IIscsFanData, IscsFan, IscsFanTemplate } from './IscsFan'; + +export class IscsFanDraw extends GraphicDrawAssistant< + IscsFanTemplate, + IIscsFanData +> { + _iscsFan: IscsFan | null = null; + + constructor(app: JlDrawApp) { + const template = new IscsFanTemplate(); + super(app, template, 'svguse:../drawIcon.svg#icon-fans', '风机'); + IscsFanInteraction.init(app); + } + + bind(): void { + super.bind(); + if (!this._iscsFan) { + this._iscsFan = this.graphicTemplate.new(); + this.container.addChild(this._iscsFan); + } + } + + public get iscsFan(): IscsFan { + if (!this._iscsFan) { + throw new Error('风机绘制逻辑异常'); + } + return this._iscsFan; + } + + redraw(cp: Point): void { + this.iscsFan.position.copyFrom(cp); + } + onLeftUp(e: FederatedMouseEvent): void { + this.iscsFan.position.copyFrom(this.toCanvasCoordinates(e.global)); + this.createAndStore(false); + } + prepareData(data: IIscsFanData): boolean { + data.transform = this.iscsFan.saveTransform(); + return true; + } + onEsc(): void { + this.finish(); + } +} + +export class IscsFanInteraction extends GraphicInteractionPlugin { + static Name = 'iscs_fan_transform'; + constructor(app: JlDrawApp) { + super(IscsFanInteraction.Name, app); + } + static init(app: JlDrawApp) { + return new IscsFanInteraction(app); + } + filter(...grahpics: JlGraphic[]): IscsFan[] | undefined { + return grahpics + .filter((g) => g.type === IscsFan.Type) + .map((g) => g as IscsFan); + } + bind(g: IscsFan): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.scalable = true; + g.rotatable = true; + } + unbind(g: IscsFan): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + } +} diff --git a/src/graphics/iscs-fan/iscs-fan-data.json b/src/graphics/iscs-fan/iscs-fan-data.json new file mode 100644 index 0000000..5d2c674 --- /dev/null +++ b/src/graphics/iscs-fan/iscs-fan-data.json @@ -0,0 +1,66 @@ +{"frames": { + +"fan-blue.png": +{ + "frame": {"x":0,"y":0,"w":41,"h":41}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":41,"h":41}, + "sourceSize": {"w":41,"h":41}, + "anchor": {"x":0.5,"y":0.5} +}, +"fan-border.png": +{ + "frame": {"x":41,"y":0,"w":41,"h":41}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":41,"h":41}, + "sourceSize": {"w":41,"h":41}, + "anchor": {"x":0.5,"y":0.5} +}, +"fan-gray.png": +{ + "frame": {"x":82,"y":0,"w":41,"h":41}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":41,"h":41}, + "sourceSize": {"w":41,"h":41}, + "anchor": {"x":0.5,"y":0.5} +}, +"fan-green.png": +{ + "frame": {"x":123,"y":0,"w":41,"h":41}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":41,"h":41}, + "sourceSize": {"w":41,"h":41}, + "anchor": {"x":0.5,"y":0.5} +}, +"fan-red.png": +{ + "frame": {"x":164,"y":0,"w":41,"h":41}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":41,"h":41}, + "sourceSize": {"w":41,"h":41}, + "anchor": {"x":0.5,"y":0.5} +}, +"fan-yellow.png": +{ + "frame": {"x":205,"y":0,"w":41,"h":41}, + "rotated": false, + "trimmed": false, + "spriteSourceSize": {"x":0,"y":0,"w":41,"h":41}, + "sourceSize": {"w":41,"h":41}, + "anchor": {"x":0.5,"y":0.5} +}}, +"meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "1.1", + "image": "test-iscs-fan.png", + "format": "RGBA8888", + "size": {"w":246,"h":41}, + "scale": "1", + "smartupdate": "$TexturePacker:SmartUpdate:e7620bd2d73cc0b3e2deea9704e7eefc:f129a1d9e4b9ba57720b3861c22b155b:eb2d421f7759984b7713aa4aa5354134$" +} +} diff --git a/src/graphics/iscs-fan/iscs-fan-spritesheet.png b/src/graphics/iscs-fan/iscs-fan-spritesheet.png new file mode 100644 index 0000000..adec75a Binary files /dev/null and b/src/graphics/iscs-fan/iscs-fan-spritesheet.png differ diff --git a/src/graphics/link/Link.ts b/src/graphics/link/Link.ts new file mode 100644 index 0000000..e1290f7 --- /dev/null +++ b/src/graphics/link/Link.ts @@ -0,0 +1,102 @@ +import { Color, Graphics, IPointData } from 'pixi.js'; +import { + GraphicData, + JlGraphic, + JlGraphicTemplate, + convertToBezierParams, +} from 'src/jl-graphic'; +import { ILineGraphic } from 'src/jl-graphic/plugins/GraphicEditPlugin'; + +export interface ILinkData extends GraphicData { + get code(): string; // 编号 + set code(v: string); + get curve(): boolean; // 是否曲线 + set curve(v: boolean); + get segmentsCount(): number; // 曲线分段数 + set segmentsCount(v: number); + get points(): IPointData[]; // 线坐标点 + set points(points: IPointData[]); + get lineWidth(): number; // 线宽 + set lineWidth(v: number); + get lineColor(): string; // 线色 + set lineColor(v: string); + clone(): ILinkData; + copyFrom(data: ILinkData): void; + eq(other: ILinkData): boolean; +} + +export class Link extends JlGraphic implements ILineGraphic { + static Type = 'Link'; + lineGraphic: Graphics; + constructor() { + super(Link.Type); + this.lineGraphic = new Graphics(); + this.addChild(this.lineGraphic); + } + + get datas(): ILinkData { + return this.getDatas(); + } + doRepaint(): void { + if (this.datas.points.length < 2) { + throw new Error('Link坐标数据异常'); + } + this.lineGraphic.clear(); + this.lineGraphic.lineStyle( + this.datas.lineWidth, + new Color(this.datas.lineColor) + ); + if (this.datas.curve) { + // 曲线 + const bps = convertToBezierParams(this.datas.points); + bps.forEach((bp) => { + this.lineGraphic.drawBezierCurve( + bp.p1, + bp.p2, + bp.cp1, + bp.cp2, + this.datas.segmentsCount + ); + }); + } else { + // 直线 + const start = this.getStartPoint(); + this.lineGraphic.moveTo(start.x, start.y); + for (let i = 0; i < this.datas.points.length; i++) { + const p = this.datas.points[i]; + this.lineGraphic.lineTo(p.x, p.y); + } + } + } + get linePoints(): IPointData[] { + return this.datas.points; + } + set linePoints(points: IPointData[]) { + const old = this.datas.clone(); + old.points = points; + this.updateData(old); + } + getStartPoint(): IPointData { + return this.datas.points[0]; + } + getEndPoint(): IPointData { + return this.datas.points[this.datas.points.length - 1]; + } +} + +export class LinkTemplate extends JlGraphicTemplate { + curve: boolean; + lineWidth: number; + lineColor: string; + segmentsCount: number; + constructor() { + super(Link.Type, {}); + this.lineWidth = 2; + this.lineColor = '#000000'; + this.curve = false; + this.segmentsCount = 10; + } + new(): Link { + return new Link(); + } +} diff --git a/src/graphics/link/LinkDrawAssistant.ts b/src/graphics/link/LinkDrawAssistant.ts new file mode 100644 index 0000000..353af5f --- /dev/null +++ b/src/graphics/link/LinkDrawAssistant.ts @@ -0,0 +1,336 @@ +import { + Color, + DisplayObject, + FederatedMouseEvent, + FederatedPointerEvent, + Graphics, + IHitArea, + Point, +} from 'pixi.js'; +import { + AbsorbablePosition, + DraggablePoint, + GraphicApp, + GraphicDrawAssistant, + GraphicInteractionPlugin, + GraphicTransformEvent, + JlDrawApp, + JlGraphic, + KeyListener, + calculateMirrorPoint, + convertToBezierParams, + linePoint, + pointPolygon, +} from 'src/jl-graphic'; +import AbsorbablePoint, { + AbsorbableCircle, +} from 'src/jl-graphic/graphic/AbsorbablePosition'; +import { + BezierCurveEditPlugin, + ILineGraphic, + PolylineEditPlugin, +} from 'src/jl-graphic/plugins/GraphicEditPlugin'; +import { ILinkData, Link, LinkTemplate } from './Link'; + +export interface ILinkDrawOptions { + newData: () => ILinkData; +} + +export class LinkDraw extends GraphicDrawAssistant { + points: Point[] = []; + graphic: Graphics = new Graphics(); + + // 快捷切曲线绘制 + keyqListener: KeyListener = new KeyListener({ + value: 'KeyQ', + global: true, + onPress: () => { + if (this.points.length == 0) { + this.graphicTemplate.curve = true; + } + }, + }); + // 快捷切直线绘制 + keyzListener: KeyListener = new KeyListener({ + value: 'KeyZ', + global: true, + onPress: () => { + if (this.points.length == 0) { + this.graphicTemplate.curve = false; + } + }, + }); + + constructor(app: JlDrawApp) { + super(app, new LinkTemplate(), 'sym_o_horizontal_rule', '轨道Link'); + this.container.addChild(this.graphic); + this.graphicTemplate.curve = true; + + LinkPointsEditPlugin.init(app); + } + + bind(): void { + super.bind(); + this.app.addKeyboardListener(this.keyqListener, this.keyzListener); + } + unbind(): void { + super.unbind(); + this.app.removeKeyboardListener(this.keyqListener, this.keyzListener); + } + + clearCache(): void { + this.points = []; + this.graphic.clear(); + } + onRightClick(): void { + this.createAndStore(true); + } + onLeftDown(e: FederatedPointerEvent): void { + const { x, y } = this.toCanvasCoordinates(e.global); + const p = new Point(x, y); + if (this.graphicTemplate.curve) { + if (this.points.length == 0) { + this.points.push(p); + } else { + this.points.push(p, p.clone()); + } + } else { + this.points.push(p); + } + } + onLeftUp(e: FederatedMouseEvent): void { + const template = this.graphicTemplate; + if (template.curve) { + const mp = this.toCanvasCoordinates(e.global); + if (this.points.length == 1) { + this.points.push(new Point(mp.x, mp.y)); + } else if (this.points.length > 1) { + const cp2 = this.points[this.points.length - 2]; + const p = this.points[this.points.length - 1]; + cp2.copyFrom(calculateMirrorPoint(p, mp)); + this.points.push(mp); + } + } + } + + redraw(p: Point): void { + if (this.points.length < 1) return; + this.graphic.clear(); + const template = this.graphicTemplate; + this.graphic.lineStyle(template.lineWidth, new Color(template.lineColor)); + const ps = [...this.points]; + if (template.curve) { + // 曲线 + if (ps.length == 1) { + this.graphic.moveTo(ps[0].x, ps[0].y); + this.graphic.lineTo(p.x, p.y); + } else { + if ((ps.length + 1) % 3 == 0) { + ps.push(p.clone(), p.clone()); + } else { + const cp = ps[ps.length - 2]; + const p1 = ps[ps.length - 1]; + const mp = calculateMirrorPoint(p1, p); + cp.copyFrom(mp); + } + + const bps = convertToBezierParams(ps); + bps.forEach((bp) => + this.graphic.drawBezierCurve( + bp.p1, + bp.p2, + bp.cp1, + bp.cp2, + template.segmentsCount + ) + ); + } + } else { + ps.push(p); + // 直线 + this.graphic.moveTo(ps[0].x, ps[0].y); + for (let i = 1; i < ps.length; i++) { + const p = ps[i]; + this.graphic.lineTo(p.x, p.y); + } + } + } + prepareData(data: ILinkData): boolean { + const template = this.graphicTemplate; + if ( + (!template.curve && this.points.length < 2) || + (template.curve && this.points.length < 4) + ) { + console.log('Link绘制因点不够取消绘制'); + return false; + } + if (template.curve) { + this.points.pop(); + } + data.curve = template.curve; + data.segmentsCount = template.segmentsCount; + data.points = this.points; + data.lineWidth = template.lineWidth; + data.lineColor = template.lineColor; + data.segmentsCount = template.segmentsCount; + return true; + } +} + +export class LinkGraphicHitArea implements IHitArea { + link: Link; + constructor(link: Link) { + this.link = link; + } + contains(x: number, y: number): boolean { + const p = new Point(x, y); + if (this.link.datas.curve) { + // 曲线 + const bps = convertToBezierParams(this.link.datas.points); + for (let i = 0; i < bps.length; i++) { + const bp = bps[i]; + if ( + pointPolygon( + p, + [bp.p1, bp.cp1, bp.cp2, bp.p2], + this.link.datas.lineWidth + ) + ) { + return true; + } + } + } else { + // 直线 + for (let i = 1; i < this.link.datas.points.length; i++) { + const p1 = this.link.datas.points[i - 1]; + const p2 = this.link.datas.points[i]; + if (linePoint(p1, p2, p, this.link.datas.lineWidth)) { + return true; + } + } + } + return false; + } +} + +/** + * 构建吸附位置 + * @param link + * @returns + */ +function buildAbsorbablePositions(link: Link): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + const links = link.queryStore.queryByType(Link.Type); + links.forEach((other) => { + if (other.id == link.id) { + return; + } + const apa = new AbsorbablePoint( + other.localToCanvasPoint(other.getStartPoint()) + ); + const apb = new AbsorbablePoint( + other.localToCanvasPoint(other.getEndPoint()) + ); + aps.push(apa, apb); + }); + + aps.push(new AbsorbableCircle(new Point(450, 410), 30)); + + return aps; +} + +/** + * 端点拖拽添加吸附位置 + * @param g + * @param dp + * @param index + */ +function onEditPointCreate( + g: ILineGraphic, + dp: DraggablePoint, + index: number +): void { + const link = g as Link; + if (index === 0 || index == link.datas.points.length - 1) { + // 端点 + dp.on('transformstart', (e: GraphicTransformEvent) => { + if (e.isShift()) { + link.getGraphicApp().setOptions({ + absorbablePositions: buildAbsorbablePositions(link), + }); + } + }); + } +} + +/** + * link路径编辑 + */ +export class LinkPointsEditPlugin extends GraphicInteractionPlugin { + static Name = 'LinkPointsDrag'; + constructor(app: GraphicApp) { + super(LinkPointsEditPlugin.Name, app); + } + static init(app: GraphicApp): LinkPointsEditPlugin { + return new LinkPointsEditPlugin(app); + } + filter(...grahpics: JlGraphic[]): Link[] | undefined { + return grahpics.filter((g) => g.type == Link.Type) as Link[]; + } + bind(g: Link): void { + g.lineGraphic.eventMode = 'static'; + g.lineGraphic.cursor = 'pointer'; + g.lineGraphic.hitArea = new LinkGraphicHitArea(g); + g.on('selected', this.onSelected, this); + g.on('unselected', this.onUnselected, this); + } + unbind(g: Link): void { + g.off('selected', this.onSelected, this); + g.off('unselected', this.onUnselected, this); + } + + onSelected(g: DisplayObject): void { + const link = g as Link; + let lep; + if (link.datas.curve) { + // 曲线 + lep = link.getAssistantAppend( + BezierCurveEditPlugin.Name + ); + if (!lep) { + lep = new BezierCurveEditPlugin(link, { + onEditPointCreate, + }); + link.addAssistantAppend(lep); + } + } else { + // 直线 + lep = link.getAssistantAppend( + PolylineEditPlugin.Name + ); + if (!lep) { + lep = new PolylineEditPlugin(link, { onEditPointCreate }); + link.addAssistantAppend(lep); + } + } + lep.showAll(); + } + onUnselected(g: DisplayObject): void { + const link = g as Link; + let lep; + if (link.datas.curve) { + // 曲线 + lep = link.getAssistantAppend( + BezierCurveEditPlugin.Name + ); + } else { + // 直线 + lep = link.getAssistantAppend( + PolylineEditPlugin.Name + ); + } + if (lep) { + lep.hideAll(); + } + } +} diff --git a/src/graphics/pathLine/PathLine.ts b/src/graphics/pathLine/PathLine.ts new file mode 100644 index 0000000..edfafd7 --- /dev/null +++ b/src/graphics/pathLine/PathLine.ts @@ -0,0 +1,159 @@ +import { JlGraphic, GraphicData, JlGraphicTemplate } from 'src/jl-graphic'; +import { Graphics, IPointData, Point } from 'pixi.js'; +import { RunLine } from '../runLine/RunLine'; +import { getDrawApp } from 'src/drawApp'; +// calculateDistanceFromPointToLine +import { calculateFootPointFromPointToLine, distance } from 'src/jl-graphic'; +import { StationLine } from '../stationLine/StationLine'; +export interface KilometerPoint { + get point(): IPointData; + set point(point: IPointData); + get kilometer(): number; + set kilometer(kilometer: number); + get stName(): string; + set stName(stName: string); +} +export interface IPathLineData extends GraphicData { + get code(): string; + set code(v: string); + get points(): IPointData[]; // 线坐标点 + set points(points: IPointData[]); + get isUp(): boolean; + set isUp(v: boolean); + get kilometerPoints(): KilometerPoint[]; + set kilometerPoints(kilometerPoints: KilometerPoint[]); + clone(): IPathLineData; + copyFrom(data: IPathLineData): void; + eq(other: IPathLineData): boolean; +} + +export const pathLineConsts = { + pathLineWidth: 1, + pathLineColor: '0Xff0000', +}; + +export class PathLine extends JlGraphic { + static Type = 'PathLine'; + pathLine: Graphics = new Graphics(); + constructor() { + super(PathLine.Type); + this.addChild(this.pathLine); + } + + get datas(): IPathLineData { + return this.getDatas(); + } + doRepaint(): void { + if (this.datas.points.length < 2) { + throw new Error('RunLine坐标数据异常'); + } + this.pathLine.clear(); + this.pathLine.lineStyle({ + width: pathLineConsts.pathLineWidth, + color: pathLineConsts.pathLineColor, + }); + const start = this.getStartPoint(); + this.pathLine.moveTo(start.x, start.y); + for (let i = 0; i < this.datas.points.length; i++) { + const p = this.datas.points[i]; + this.pathLine.lineTo(p.x, p.y); + } + } + + get linePoints(): IPointData[] { + return this.datas.points; + } + set linePoints(points: IPointData[]) { + const old = this.datas.clone(); + old.points = points; + this.updateData(old); + } + getStartPoint(): IPointData { + return this.datas.points[0]; + } + getEndPoint(): IPointData { + return this.datas.points[this.datas.points.length - 1]; + } + onDelete(): void { + super.onDelete(); + const pathLineId = this.datas.id; + const app = getDrawApp(); + if (!app) return; + const runLineList = app.queryStore.queryByType(RunLine.Type) as RunLine[]; + runLineList.find((runLine) => { + if (runLine.datas.linkPathLines.includes(pathLineId)) { + const list = [...runLine.datas.linkPathLines]; + const index = list.findIndex((item) => item === pathLineId); + list.splice(index, 1); + runLine.datas.linkPathLines = list; + return true; + } + }); + } + /** + * 计算stationLine在轨迹线上的垂足距离,计算stationLine与轨迹点距离,寻求最短且垂足在线段上 + * @param stas stationLine列表 + */ + generatePathLineKilometerPoints(stas: string[]) { + const kilometerPoints: KilometerPoint[] = []; + stas.forEach((stasId) => { + const sta = this.queryStore.queryById(stasId) as StationLine; + let fp: IPointData | null = null; + const sp = sta.position; + let minDistance = Number.MAX_SAFE_INTEGER; + this.datas.points.forEach((p, index) => { + if (index) { + const prep = this.datas.points[index - 1]; + const fpn = calculateFootPointFromPointToLine(prep, p, sp); + const distanceS = distance(prep.x, prep.y, p.x, p.y); + const fln = distance(fpn.x, fpn.y, sp.x, sp.y); + const distanceP = distance(p.x, p.y, sp.x, sp.y); + if ( + distance(fpn.x, fpn.y, prep.x, prep.y) <= distanceS && + distance(fpn.x, fpn.y, p.x, p.y) <= distanceS && + fln <= minDistance + ) { + minDistance = fln; + fp = fpn; + } + if (distanceP < minDistance) { + if (distanceP < minDistance) { + minDistance = distanceP; + fp = p; + } + } + } else { + const distanceP = distance(p.x, p.y, sp.x, sp.y); + if (distanceP < minDistance) { + minDistance = distanceP; + fp = p; + } + } + }); + if (sta.datas.code === '延平门') { + console.log(fp); + } + if (fp) { + kilometerPoints.push({ + point: new Point(fp?.['x'], fp?.['y']), + kilometer: 0, + stName: sta.datas.code, + }); + } + }); + this.datas.kilometerPoints = kilometerPoints; + } +} + +export class PathLineTemplate extends JlGraphicTemplate { + pathLineColor: string; + pathLineWidth: number; + constructor(dataTemplate: IPathLineData) { + super(PathLine.Type, { dataTemplate }); + this.pathLineColor = pathLineConsts.pathLineColor; + this.pathLineWidth = pathLineConsts.pathLineWidth; + } + new(): PathLine { + return new PathLine(); + } +} diff --git a/src/graphics/pathLine/PathLineDrawAssistant.ts b/src/graphics/pathLine/PathLineDrawAssistant.ts new file mode 100644 index 0000000..f1e000d --- /dev/null +++ b/src/graphics/pathLine/PathLineDrawAssistant.ts @@ -0,0 +1,219 @@ +import { + GraphicDrawAssistant, + JlDrawApp, + linePoint, + GraphicInteractionPlugin, + GraphicApp, + JlGraphic, + DraggablePoint, + GraphicTransformEvent, + calculateFootPointFromPointToLine, + calculateDistanceFromPointToLine, + distance, +} from 'src/jl-graphic'; +import { + IPathLineData, + PathLineTemplate, + PathLine, + pathLineConsts, +} from './PathLine'; +import { + Point, + Graphics, + LINE_JOIN, + IHitArea, + DisplayObject, + IPointData, +} from 'pixi.js'; +export interface IPathLineDrawOptions { + newData: () => IPathLineData; +} + +export class PathLineDraw extends GraphicDrawAssistant< + PathLineTemplate, + IPathLineData +> { + points: Point[] = []; + code = ''; + graphic: Graphics = new Graphics(); + + constructor(app: JlDrawApp, template: PathLineTemplate) { + super(app, template, 'sym_o_horizontal_rule', '不展示'); + this.container.addChild(this.graphic); + PathLinePointsEditPlugin.init(app); + } + clearCache(): void { + this.points = []; + this.code = ''; + this.graphic.clear(); + } + // onRightClick(): void { + // this.createAndStore(true); + // } + + // onLeftDown(e: FederatedPointerEvent): void { + // const { x, y } = this.toCanvasCoordinates(e.global); + // const p = new Point(x, y); + // this.points.push(p); + // } + quickCreate(points: Point[], lineId: string) { + this.points = [...points]; + this.code = lineId; + return this.createAndStore(true); + } + + redraw(p: Point): void { + if (this.points.length < 1) return; + this.graphic.clear(); + const template = this.graphicTemplate; + this.graphic.lineStyle({ + width: template.pathLineWidth, + color: template.pathLineColor, + join: LINE_JOIN.ROUND, + }); + const ps = [...this.points]; + ps.push(p); + // 直线 + this.graphic.moveTo(ps[0].x, ps[0].y); + for (let i = 1; i < ps.length; i++) { + const p = ps[i]; + this.graphic.lineTo(p.x, p.y); + } + } + prepareData(data: IPathLineData): boolean { + data.points = this.points; + return true; + } +} + +export class PathLineGraphicHitArea implements IHitArea { + pathLine: PathLine; + constructor(pathLine: PathLine) { + this.pathLine = pathLine; + } + contains(x: number, y: number): boolean { + const p = new Point(x, y); + for (let i = 1; i < this.pathLine.datas.points.length; i++) { + const p1 = this.pathLine.datas.points[i - 1]; + const p2 = this.pathLine.datas.points[i]; + if (linePoint(p1, p2, p, pathLineConsts.pathLineWidth)) { + return true; + } + } + return false; + } +} + +export class PathLinePointsEditPlugin extends GraphicInteractionPlugin { + static Name = 'LinkPointsDrag'; + constructor(app: GraphicApp) { + super(PathLinePointsEditPlugin.Name, app); + } + static init(app: GraphicApp): PathLinePointsEditPlugin { + return new PathLinePointsEditPlugin(app); + } + filter(...grahpics: JlGraphic[]): PathLine[] | undefined { + return grahpics.filter((g) => g.type == PathLine.Type) as PathLine[]; + } + bind(g: PathLine): void { + g.pathLine.eventMode = 'static'; + g.pathLine.cursor = 'pointer'; + g.pathLine.draggable = false; + g.pathLine.scalable = false; + g.pathLine.rotatable = false; + g.pathLine.hitArea = new PathLineGraphicHitArea(g); + g.on('selected', this.onSelected, this); + g.on('unselected', this.onUnselected, this); + } + unbind(g: PathLine): void { + g.off('selected', this.onSelected, this); + g.off('unselected', this.onUnselected, this); + } + + onSelected(g: DisplayObject): void { + const pathLine = g as PathLine; + pathLine.draggable = false; + pathLine.scalable = false; + pathLine.rotatable = false; + pathLine.datas.kilometerPoints.forEach((kp, index) => { + const dp = new DraggablePoint(kp.point); + dp.on( + 'transforming', + (e: GraphicTransformEvent) => { + this.movePointOnLine(pathLine.datas.points, e); + }, + this + ); + dp.on( + 'transformend', + (e: GraphicTransformEvent) => { + const kilometerPoints = [...pathLine.datas.kilometerPoints]; + kilometerPoints[index] = { + point: new Point(e.target.position.x, e.target.position.y), + kilometer: kilometerPoints[index].kilometer, + stName: kilometerPoints[index].stName, + }; + pathLine.datas.kilometerPoints = kilometerPoints; + }, + this + ); + pathLine.addChild(dp); + }); + } + onUnselected(g: DisplayObject): void { + const pathLine = g as PathLine; + if (pathLine.children.length > 1) { + pathLine.removeChildren(1); + } + } + kpTransforming(e: GraphicTransformEvent) { + console.log(e, '----'); + } + movePointOnLine(points: IPointData[], e: GraphicTransformEvent) { + let minDistance = Number.MAX_SAFE_INTEGER; + let fp = null; + const np = e.target.position; + for (let i = 0; i < points.length; i++) { + const distancep = distance(np.x, np.y, points[i].x, points[i].y); + if (i !== 0) { + const distanceF = calculateDistanceFromPointToLine( + points[i - 1], + points[i], + np + ); + const fpn = calculateFootPointFromPointToLine( + points[i - 1], + points[i], + np + ); + const distance1 = distance( + fpn.x, + fpn.y, + points[i - 1].x, + points[i - 1].y + ); + const distance2 = distance(fpn.x, fpn.y, points[i].x, points[i].y); + const distance3 = distance( + points[i - 1].x, + points[i - 1].y, + points[i].x, + points[i].y + ); + if (distancep < minDistance) { + minDistance = distancep; + fp = points[i]; + } + if (distanceF < minDistance && distance1 + distance2 <= distance3 + 1) { + minDistance = distanceF; + fp = fpn; + } + } else { + minDistance = distancep; + fp = points[i]; + } + } + if (fp) { + e.target.position.set(fp.x, fp.y); + } + } +} diff --git a/src/graphics/platform/Platform.ts b/src/graphics/platform/Platform.ts new file mode 100644 index 0000000..0b40a29 --- /dev/null +++ b/src/graphics/platform/Platform.ts @@ -0,0 +1,429 @@ +import { Color, Container, Graphics, Rectangle } from 'pixi.js'; +import { + GraphicData, + GraphicState, + JlGraphic, + JlGraphicTemplate, + VectorText, + getRectangleCenter, +} from 'src/jl-graphic'; + +export interface IPlatformData extends GraphicData { + get code(): string; // 编号 + set code(v: string); + get hasdoor(): boolean; // 是否有屏蔽门 + set hasdoor(v: boolean); + get direction(): string; // 屏蔽门上下 + set direction(v: string); + clone(): IPlatformData; + copyFrom(data: IPlatformData): void; + eq(other: IPlatformData): boolean; +} +export interface IPlatformState extends GraphicState { + get emergstop(): boolean; + set emergstop(v: boolean); + get trainberth(): boolean; + set trainberth(v: boolean); + get close(): boolean; + set close(v: boolean); + get upHold(): boolean; + set upHold(v: boolean); + get downHold(): boolean; + set downHold(v: boolean); + get upOccHold(): boolean; + set upOccHold(v: boolean); + get downOccHold(): boolean; + set downOccHold(v: boolean); + get psdOpen(): boolean; + set psdOpen(v: boolean); + get psdCut(): boolean; + set psdCut(v: boolean); + get upSkipstop(): boolean; + set upSkipstop(v: boolean); + get downSkipstop(): boolean; + set downSkipstop(v: boolean); + get upTrainSkipstop(): boolean; + set upTrainSkipstop(v: boolean); + get downTrainSkipstop(): boolean; + set downTrainSkipstop(v: boolean); + get nextSectionRunTime(): number; //下一区间运行时间 + set nextSectionRunTime(v: number); + get nextSectionRunLevel(): number; //下一区间运行等级 + set nextSectionRunLevel(v: number); + get stopTime(): number; //停站时间 + set stopTime(v: number); +} + +//站台颜色 +export enum PlatformColorEnum { + grey = '0x7F7F7F', //站台没有列车停站 + yellow = '0xfbff00', //列车在站台停站 + blue = '0xC0C0FE', //列车在站台跳停 + lozengeRed = '0xff0000', //站台旁的菱形图标 + whiteNumbers = '0xffffff', //站台旁白色数字 + whiteCircle = '0xffffff', //H字符旁的圆圈 + HCharYellow = '0xfbff00', //站台旁的H字符 + HCharWhite = '0xffffff', + HCharRed = '0xff0000', + doorGreen = '0x00FF00', //屏蔽门的颜色 + doorRed = '0xff0000', + doorBlue = '0x4048C4', +} + +const platformConsts = { + width: 90, + height: 20, + lineWidth: 3, + besideFontSize: 12, + doorOpenSpacing: 15, + doorPlatformSpacing: 10, + besideSpacing: 10, + circleRadius: 1, +}; + +//子元素--矩形 +export class rectGraphic extends Container { + static Type = 'RectPlatForm'; + rectGraphic: Graphics; + constructor() { + super(); + this.rectGraphic = new Graphics(); + this.addChild(this.rectGraphic); + } + draw(state: IPlatformState): void { + const rectGraphic = this.rectGraphic; + rectGraphic.clear(); + let fillColor = PlatformColorEnum.grey; + if (state.trainberth) { + fillColor = PlatformColorEnum.yellow; + } + if (state.upSkipstop || state.downSkipstop) { + fillColor = PlatformColorEnum.blue; + } + rectGraphic.lineStyle(platformConsts.lineWidth, new Color(fillColor)); + rectGraphic.beginFill(fillColor, 1); + rectGraphic.drawRect(0, 0, platformConsts.width, platformConsts.height); + rectGraphic.endFill; + const rectP = new Rectangle( + 0, + 0, + platformConsts.width, + platformConsts.height + ); + rectGraphic.pivot = getRectangleCenter(rectP); + } + clear(): void { + this.rectGraphic.clear(); + } +} +//子元素--门 +export class doorGraphic extends Container { + static Type = 'Door'; + doorGraphic: Graphics; + doorCloseGraphic: Graphics; + constructor() { + super(); + this.doorGraphic = new Graphics(); + this.doorCloseGraphic = new Graphics(); + this.addChild(this.doorGraphic); + this.addChild(this.doorCloseGraphic); + } + draw(stateData: IPlatformState): void { + const doorGraphic = this.doorGraphic; + const doorCloseGraphic = this.doorCloseGraphic; + doorGraphic.clear(); + doorCloseGraphic.clear(); + let lineColor = PlatformColorEnum.doorGreen; + if (stateData.psdCut) { + lineColor = PlatformColorEnum.doorRed; + } + doorGraphic.lineStyle(platformConsts.lineWidth, new Color(lineColor)); + doorGraphic.moveTo( + -platformConsts.width / 2 - platformConsts.lineWidth / 2, + 0 + ); + doorGraphic.lineTo(-platformConsts.doorOpenSpacing, 0); + doorGraphic.moveTo(platformConsts.doorOpenSpacing, 0); + doorGraphic.lineTo( + platformConsts.width / 2 + platformConsts.lineWidth / 2, + 0 + ); + //屏蔽门闭合 + doorCloseGraphic.lineStyle(platformConsts.lineWidth, new Color(lineColor)); + doorCloseGraphic.moveTo(-platformConsts.doorOpenSpacing, 0); + doorCloseGraphic.lineTo(platformConsts.doorOpenSpacing, 0); + doorGraphic.position.set( + 0, + -platformConsts.height / 2 - platformConsts.doorPlatformSpacing + ); + doorCloseGraphic.position.set( + 0, + -platformConsts.height / 2 - platformConsts.doorPlatformSpacing + ); + } + clear(): void { + this.doorGraphic.clear(); + this.doorCloseGraphic.clear(); + } + changeState(stateData: IPlatformState): void { + if (stateData.psdOpen) { + this.doorCloseGraphic.visible = false; + } else { + this.doorCloseGraphic.visible = true; + } + } +} +//子元素--字符 +class codeGraph extends Container { + static Type = 'Code'; + character: VectorText = new VectorText(''); //扣车H + runTime: VectorText = new VectorText(''); //运行时间 + stopTime: VectorText = new VectorText(''); //停站时间 + circle: Graphics = new Graphics(); + constructor() { + super(); + this.addChild(this.character); + this.addChild(this.runTime); + this.addChild(this.circle); + this.addChild(this.stopTime); + this.character.setVectorFontSize(platformConsts.besideFontSize); + this.runTime.setVectorFontSize(platformConsts.besideFontSize); + this.stopTime.setVectorFontSize(platformConsts.besideFontSize); + } + draw(): void { + //扣车 + const character = this.character; + character.text = 'H'; + character.anchor.set(0.5); + character.position.set( + -platformConsts.width / 2 - + platformConsts.lineWidth / 2 - + (platformConsts.besideSpacing * 2) / 3, + (platformConsts.height * 3) / 4 + ); + character.style.fill = PlatformColorEnum.whiteNumbers; + const circle = this.circle; + circle.clear(); + circle.lineStyle(0.5, PlatformColorEnum.whiteCircle); + circle.drawCircle(0, 0, platformConsts.circleRadius); + circle.position.set( + -platformConsts.width / 2 - + platformConsts.lineWidth / 2 - + (platformConsts.besideSpacing * 4) / 3, + (platformConsts.height * 3) / 5 + ); + //区间运行等级状态 + const runTime = this.runTime; + runTime.anchor.set(0.5); + runTime.position.set( + platformConsts.width / 2 + + platformConsts.lineWidth / 2 + + platformConsts.besideSpacing, + -platformConsts.besideSpacing + ); + runTime.style.fill = PlatformColorEnum.whiteNumbers; + //停站时间 + const stopTime = this.stopTime; + stopTime.anchor.set(0.5); + stopTime.position.set( + platformConsts.width / 2 + + platformConsts.lineWidth / 2 + + platformConsts.besideSpacing, + platformConsts.besideSpacing + ); + stopTime.style.fill = PlatformColorEnum.whiteNumbers; + character.visible = false; + circle.visible = false; + runTime.visible = false; + stopTime.visible = false; + } + clear(): void { + this.character.destroy(); + } + changeState(stateData: IPlatformState): void { + if ( + stateData.upHold || + stateData.upOccHold || + stateData.downHold || + stateData.downOccHold + ) { + this.character.text = 'H'; + this.character.visible = true; + this.circle.visible = true; + //上行扣车 + if (stateData.upHold) { + this.character.style.fill = PlatformColorEnum.HCharYellow; + } + if (stateData.upOccHold) { + this.character.style.fill = PlatformColorEnum.HCharWhite; + } + if (stateData.upHold && stateData.upOccHold) { + this.character.style.fill = PlatformColorEnum.HCharRed; + } + //下行扣车 + if (stateData.downHold) { + this.character.style.fill = PlatformColorEnum.HCharYellow; + } + if (stateData.downOccHold) { + this.character.style.fill = PlatformColorEnum.HCharWhite; + } + if (stateData.downHold && stateData.downOccHold) { + this.character.style.fill = PlatformColorEnum.HCharRed; + } + //运行等级 + if (stateData.nextSectionRunTime) { + this.runTime.visible = true; + this.runTime.text = stateData.nextSectionRunTime; + } + //停站时间 + if (stateData.stopTime) { + this.stopTime.visible = true; + this.stopTime.text = stateData.stopTime; + } + } + } +} +//子元素--站台旁菱形图标 +class besideGraphic extends Container { + static Type = 'BesideGraphic'; + besideGraphic: Graphics; + constructor() { + super(); + this.besideGraphic = new Graphics(); + this.addChild(this.besideGraphic); + } + draw(): void { + const besideGraphic = this.besideGraphic; + besideGraphic.clear(); + besideGraphic.lineStyle(1, new Color(PlatformColorEnum.lozengeRed)); + besideGraphic.beginFill(PlatformColorEnum.lozengeRed, 1); + besideGraphic.drawRect( + 0, + 0, + platformConsts.height / 4, + platformConsts.height / 4 + ); + besideGraphic.endFill(); + const rect = new Rectangle( + 0, + 0, + platformConsts.height / 4, + platformConsts.height / 4 + ); + besideGraphic.pivot = getRectangleCenter(rect); + besideGraphic.rotation = Math.PI / 4; + besideGraphic.position.set( + 0, + -platformConsts.height / 2 - + platformConsts.doorPlatformSpacing - + platformConsts.height / 3 + ); + besideGraphic.visible = false; + } + clear(): void { + this.besideGraphic.clear(); + } + changeState(stateData: IPlatformState): void { + if (stateData.emergstop) { + this.besideGraphic.visible = true; + } else { + this.besideGraphic.visible = false; + } + } +} + +export class Platform extends JlGraphic { + static Type = 'Platform'; + platformGraphic: rectGraphic = new rectGraphic(); + doorGraphic: doorGraphic = new doorGraphic(); + besideGraphic: besideGraphic = new besideGraphic(); + codeGraph: codeGraph = new codeGraph(); + constructor() { + super(Platform.Type); + this.addChild(this.platformGraphic); + this.addChild(this.doorGraphic); + this.addChild(this.besideGraphic); + this.addChild(this.codeGraph); + } + + get datas(): IPlatformData { + return this.getDatas(); + } + get states(): IPlatformState { + return this.getStates(); + } + doRepaint(): void { + this.doorGraphic.clear(); + if (this.datas.hasdoor) { + this.doorGraphic.draw(this.states); + } + this.platformGraphic.draw(this.states); + this.besideGraphic.draw(); + this.codeGraph.draw(); + this.doorGraphic.position.set(0, 0); + this.besideGraphic.position.set(0, 0); + this.codeGraph.position.set(0, 0); + //站台方向 + if (this.datas.direction == 'down') { + this.doorGraphic.position.set( + 0, + platformConsts.height + platformConsts.doorPlatformSpacing * 2 + ); + this.besideGraphic.position.set( + 0, + platformConsts.height + + platformConsts.doorPlatformSpacing * 2 + + (platformConsts.height * 2) / 3 + ); + this.codeGraph.children[0].position.set( + platformConsts.width / 2 + + platformConsts.lineWidth / 2 + + (platformConsts.besideSpacing * 2) / 3, + -(platformConsts.height * 3) / 4 + ); + this.codeGraph.children[1].position.set( + -platformConsts.width / 2 - + platformConsts.lineWidth / 2 - + platformConsts.besideSpacing, + platformConsts.besideSpacing + ); + this.codeGraph.children[2].position.set( + platformConsts.width / 2 + + platformConsts.lineWidth / 2 + + (platformConsts.besideSpacing * 4) / 3, + (-platformConsts.height * 10) / 11 + ); + this.codeGraph.children[3].position.set( + -platformConsts.width / 2 - + platformConsts.lineWidth / 2 - + platformConsts.besideSpacing, + -platformConsts.besideSpacing + ); + } + this.changeState(); + } + changeState(): void { + this.doorGraphic.changeState(this.states); + this.besideGraphic.changeState(this.states); + this.codeGraph.changeState(this.states); + } +} + +export class PlatformTemplate extends JlGraphicTemplate { + hasdoor: boolean; + direction: string; + constructor(dataTemplate: IPlatformData, stateTemplate: IPlatformState) { + super(Platform.Type, { + dataTemplate, + stateTemplate, + }); + this.hasdoor = true; + this.direction = 'up'; + } + new(): Platform { + const platform = new Platform(); + platform.loadData(this.datas); + platform.loadState(this.states); + return platform; + } +} diff --git a/src/graphics/platform/PlatformDrawAssistant.ts b/src/graphics/platform/PlatformDrawAssistant.ts new file mode 100644 index 0000000..b3dd181 --- /dev/null +++ b/src/graphics/platform/PlatformDrawAssistant.ts @@ -0,0 +1,119 @@ +import { FederatedPointerEvent, Point } from 'pixi.js'; +import { + AbsorbableLine, + AbsorbablePosition, + GraphicDrawAssistant, + GraphicInteractionPlugin, + JlDrawApp, + JlGraphic, +} from 'src/jl-graphic'; + +import { + IPlatformData, + Platform, + PlatformTemplate, + rectGraphic, + doorGraphic, + IPlatformState, +} from './Platform'; + +export interface IPlatformDrawOptions { + newData: () => IPlatformData; +} + +export class PlatformDraw extends GraphicDrawAssistant< + PlatformTemplate, + IPlatformData +> { + platformGraphic: rectGraphic = new rectGraphic(); + doorGraphic: doorGraphic = new doorGraphic(); + + constructor(app: JlDrawApp, template: PlatformTemplate) { + super( + app, + template, + 'svguse:../../drawIcon.svg#icon-platform', + '站台Platform' + ); + this.container.addChild(this.platformGraphic); + this.container.addChild(this.doorGraphic); + platformInteraction.init(app); + } + + bind(): void { + super.bind(); + this.platformGraphic.draw(this.graphicTemplate.states as IPlatformState); + this.doorGraphic.draw(this.graphicTemplate.states as IPlatformState); + } + + clearCache(): void { + this.platformGraphic.clear(); + this.doorGraphic.clear(); + } + onLeftDown(e: FederatedPointerEvent): void { + this.container.position.copyFrom(this.toCanvasCoordinates(e.global)); + this.createAndStore(true); + } + + redraw(p: Point): void { + this.container.position.copyFrom(p); + } + + prepareData(data: IPlatformData): boolean { + const template = this.graphicTemplate; + data.hasdoor = template.hasdoor; + data.direction = template.direction; + data.transform = this.container.saveTransform(); + return true; + } +} + +function buildAbsorbablePositions(platform: Platform): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + const platforms = platform.queryStore.queryByType(Platform.Type); + const { width, height } = platform.getGraphicApp().canvas; + platforms.forEach((other) => { + if (other.id == platform.id) { + return; + } + const ps = other.datas.transform.position; + const xs = new AbsorbableLine({ x: 0, y: ps.y }, { x: width, y: ps.y }); + const ys = new AbsorbableLine({ x: ps.x, y: 0 }, { x: ps.x, y: height }); + aps.push(xs, ys); + }); + return aps; +} + +export class platformInteraction extends GraphicInteractionPlugin { + static Name = 'platform_transform'; + constructor(app: JlDrawApp) { + super(platformInteraction.Name, app); + } + static init(app: JlDrawApp) { + return new platformInteraction(app); + } + filter(...grahpics: JlGraphic[]): Platform[] | undefined { + return grahpics + .filter((g) => g.type === Platform.Type) + .map((g) => g as Platform); + } + bind(g: Platform): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.scalable = true; + g.rotatable = true; + g.on('selected', this.onSelected, this); + } + unbind(g: Platform): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + g.off('selected', this.onSelected, this); + } + onSelected(): void { + const platform = this.app.selectedGraphics[0] as Platform; + this.app.setOptions({ + absorbablePositions: buildAbsorbablePositions(platform), + }); + } +} diff --git a/src/graphics/polygon/Polygon.ts b/src/graphics/polygon/Polygon.ts new file mode 100644 index 0000000..2b7be19 --- /dev/null +++ b/src/graphics/polygon/Polygon.ts @@ -0,0 +1,72 @@ +import { Color, Graphics, IPointData } from 'pixi.js'; +import { GraphicData, JlGraphic, JlGraphicTemplate } from 'src/jl-graphic'; + +export interface IPolygonData extends GraphicData { + get code(): string; // 编号 + set code(v: string); + get lineWidth(): number; // 线宽 + set lineWidth(v: number); + get lineColor(): string; // 线色 + set lineColor(v: string); + get points(): IPointData[]; // 多边形坐标点 + set points(points: IPointData[]); + clone(): IPolygonData; + copyFrom(data: IPolygonData): void; + eq(other: IPolygonData): boolean; +} + +const polygonConsts = { + lineWidth: 2, + lineColor: '0xff0000', +}; + +export class Polygon extends JlGraphic { + static Type = 'Polygon'; + polygonGraphic: Graphics; + constructor() { + super(Polygon.Type); + this.polygonGraphic = new Graphics(); + this.addChild(this.polygonGraphic); + } + + get datas(): IPolygonData { + return this.getDatas(); + } + doRepaint(): void { + const polygonGraphic = this.polygonGraphic; + polygonGraphic.clear(); + polygonGraphic.lineStyle( + this.datas.lineWidth, + new Color(this.datas.lineColor) + ); + polygonGraphic.drawPolygon(this.datas.points); + } + get linePoints(): IPointData[] { + return this.datas.points; + } + set linePoints(points: IPointData[]) { + const old = this.datas.clone(); + old.points = points; + this.updateData(old); + } + addOnePoints(): IPointData[] { + const ps = [...this.datas.points]; + ps.push(this.datas.points[0]); + return ps; + } +} + +export class PolygonTemplate extends JlGraphicTemplate { + lineWidth: number; + lineColor: string; + constructor(dataTemplate: IPolygonData) { + super(Polygon.Type, { + dataTemplate, + }); + this.lineWidth = polygonConsts.lineWidth; + this.lineColor = polygonConsts.lineColor; + } + new(): Polygon { + return new Polygon(); + } +} diff --git a/src/graphics/polygon/PolygonDrawAssistant.ts b/src/graphics/polygon/PolygonDrawAssistant.ts new file mode 100644 index 0000000..34b853e --- /dev/null +++ b/src/graphics/polygon/PolygonDrawAssistant.ts @@ -0,0 +1,195 @@ +import { + FederatedPointerEvent, + Graphics, + Point, + IHitArea, + DisplayObject, +} from 'pixi.js'; +import { + DraggablePoint, + GraphicApp, + GraphicDrawAssistant, + GraphicInteractionPlugin, + GraphicTransformEvent, + JlDrawApp, + JlGraphic, + linePoint, +} from 'src/jl-graphic'; + +import AbsorbablePoint, { + AbsorbablePosition, +} from 'src/jl-graphic/graphic/AbsorbablePosition'; +import { + ILineGraphic, + PolylineEditPlugin, +} from 'src/jl-graphic/plugins/GraphicEditPlugin'; + +import { IPolygonData, Polygon, PolygonTemplate } from './Polygon'; + +export interface IPolygonDrawOptions { + newData: () => IPolygonData; +} + +export class PolygonDraw extends GraphicDrawAssistant< + PolygonTemplate, + IPolygonData +> { + points: Point[] = []; + polygonGraphic: Graphics = new Graphics(); + + constructor(app: JlDrawApp, template: PolygonTemplate) { + super(app, template, 'sym_o_square', '多边形Polygon'); + this.container.addChild(this.polygonGraphic); + PolygonPointsEditPlugin.init(app); + } + + clearCache(): void { + this.points = []; + this.polygonGraphic.clear(); + } + onLeftDown(e: FederatedPointerEvent): void { + const { x, y } = this.toCanvasCoordinates(e.global); + const p = new Point(x, y); + this.points.push(p); + } + onRightClick(): void { + this.createAndStore(true); + } + redraw(p: Point): void { + if (this.points.length < 1) return; + const polygonGraphic = this.polygonGraphic; + const template = this.graphicTemplate; + const ps = [...this.points]; + ps.push(p); + polygonGraphic.clear(); + polygonGraphic.lineStyle(template.lineWidth, template.lineColor); + polygonGraphic.drawPolygon(ps); + } + + prepareData(data: IPolygonData): boolean { + if (this.points.length < 2) { + console.log('Polygon绘制因点不够取消绘制'); + return false; + } + const template = this.graphicTemplate; + data.lineWidth = template.lineWidth; + data.lineColor = template.lineColor; + data.points = this.points; + return true; + } +} + +//碰撞检测 +export class PolygonGraphicHitArea implements IHitArea { + polygon: Polygon; + constructor(polygon: Polygon) { + this.polygon = polygon; + } + contains(x: number, y: number): boolean { + let contains = false; + const p = new Point(x, y); + const polygonData = this.polygon.datas; + //contains = pointPolygon(p, polygonData.points, polygonData.lineWidth);是否包含多边形内部 + const ps = this.polygon.addOnePoints(); + const tolerance = polygonData.lineWidth; + for (let i = 0; i < ps.length - 1; i++) { + const p1 = ps[i]; + const p2 = ps[i + 1]; + contains = contains || linePoint(p1, p2, p, tolerance); + if (contains) { + break; + } + } + return contains; + } +} + +/** + * 构建吸附位置 + * @param polygon + * @returns + */ +function buildAbsorbablePositions(polygon: Polygon): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + const polygons = polygon.queryStore.queryByType(Polygon.Type); + + polygons.forEach((other) => { + if (other.id == polygon.id) { + return; + } + other.linePoints.forEach((point) => { + const absorbablePoint = new AbsorbablePoint( + other.localToCanvasPoint(point) + ); + aps.push(absorbablePoint); + }); + }); + + return aps; +} + +/** + * 端点拖拽添加吸附位置 + * @param g + * @param dp + * @param index + */ +function onEditPointCreate(g: ILineGraphic, dp: DraggablePoint): void { + const polygon = g as Polygon; + // 端点 + dp.on('transformstart', (e: GraphicTransformEvent) => { + if (e.isShift()) { + polygon.getGraphicApp().setOptions({ + absorbablePositions: buildAbsorbablePositions(polygon), + }); + } + }); +} + +/** + * polygon路径编辑 + */ +export class PolygonPointsEditPlugin extends GraphicInteractionPlugin { + static Name = 'PolygonPointsDrag'; + constructor(app: GraphicApp) { + super(PolygonPointsEditPlugin.Name, app); + } + static init(app: GraphicApp): PolygonPointsEditPlugin { + return new PolygonPointsEditPlugin(app); + } + filter(...grahpics: JlGraphic[]): Polygon[] | undefined { + return grahpics.filter((g) => g.type == Polygon.Type) as Polygon[]; + } + bind(g: Polygon): void { + g.polygonGraphic.eventMode = 'static'; + g.polygonGraphic.cursor = 'pointer'; + g.polygonGraphic.hitArea = new PolygonGraphicHitArea(g); + g.on('selected', this.onSelected, this); + g.on('unselected', this.onUnselected, this); + } + unbind(g: Polygon): void { + g.off('selected', this.onSelected, this); + g.off('unselected', this.onUnselected, this); + } + + onSelected(g: DisplayObject): void { + const polygon = g as Polygon; + let lep = polygon.getAssistantAppend( + PolylineEditPlugin.Name + ); + if (!lep) { + lep = new PolylineEditPlugin(polygon, { onEditPointCreate }); + polygon.addAssistantAppend(lep); + } + lep.showAll(); + } + onUnselected(g: DisplayObject): void { + const polygon = g as Polygon; + const lep = polygon.getAssistantAppend( + PolylineEditPlugin.Name + ); + if (lep) { + lep.hideAll(); + } + } +} diff --git a/src/graphics/polygon/PolygonUtils.ts b/src/graphics/polygon/PolygonUtils.ts new file mode 100644 index 0000000..a98f92d --- /dev/null +++ b/src/graphics/polygon/PolygonUtils.ts @@ -0,0 +1,90 @@ +import { IPointData, Point } from 'pixi.js'; +import { + calculateDistanceFromPointToLine, + calculateFootPointFromPointToLine, +} from 'src/jl-graphic'; +import { Polygon } from './Polygon'; + +//计算线段细分坐标--线段分成几份 +export function getLineSegmentPoints( + startPoint: IPointData, + endPoint: IPointData, + knife: number +) { + const segmentLength = Math.sqrt( + Math.pow(endPoint.x - startPoint.x, 2) + + Math.pow(endPoint.y - startPoint.y, 2) + ); + const segmentIncrement = segmentLength / knife; + const segmentAngle = Math.atan2( + endPoint.y - startPoint.y, + endPoint.x - startPoint.x + ); + + const points: IPointData[] = []; + for (let i = 1; i < knife; i++) { + const segmentPosition = i * segmentIncrement; + const x = startPoint.x + segmentPosition * Math.cos(segmentAngle); + const y = startPoint.y + segmentPosition * Math.sin(segmentAngle); + points.push(new Point(x, y)); + } + + return points; +} + +//获取所选线段的索引 +export function getWayLineIndex( + points: IPointData[], + p: IPointData +): { start: number; end: number } { + let start = 0; + let end = 0; + let minDistance = 0; + for (let i = 1; i < points.length; i++) { + const sp = points[i - 1]; + const ep = points[i]; + let distance = calculateDistanceFromPointToLine(sp, ep, p); + distance = Math.round(distance * 100) / 100; + if (i == 1) { + minDistance = distance; + } + if (distance == minDistance) { + const minX = Math.min(sp.x, ep.x); + const maxX = Math.max(sp.x, ep.x); + const minY = Math.min(sp.y, ep.y); + const maxY = Math.max(sp.y, ep.y); + const point = calculateFootPointFromPointToLine(sp, ep, p); + if ( + point.x >= minX && + point.x <= maxX && + point.y >= minY && + point.y <= maxY + ) { + start = i - 1; + } + } + if (distance < minDistance) { + minDistance = distance; + start = i - 1; + } + } + end = start + 1; + return { start, end }; +} + +//添加细分的点的坐标 +export function addPolygonSegmentingPoint( + graphic: Polygon, + start: number, + end: number, + knife = 2 +) { + const linePoints = graphic.addOnePoints(); + const points = linePoints.slice(0, start + 1); + points.push( + ...getLineSegmentPoints(linePoints[start], linePoints[end], knife) + ); + points.push(...linePoints.slice(end)); + points.pop(); + graphic.linePoints = points; +} diff --git a/src/graphics/rect/Rect.ts b/src/graphics/rect/Rect.ts new file mode 100644 index 0000000..feac981 --- /dev/null +++ b/src/graphics/rect/Rect.ts @@ -0,0 +1,99 @@ +import { Color, Graphics, IPointData, Point, Rectangle } from 'pixi.js'; +import { + GraphicData, + JlGraphic, + JlGraphicTemplate, + getRectangleCenter, +} from 'src/jl-graphic'; + +export interface IRectData extends GraphicData { + get code(): string; // 编号 + set code(v: string); + get lineWidth(): number; // 线宽 + set lineWidth(v: number); + get lineColor(): string; // 线色 + set lineColor(v: string); + get point(): IPointData; // 位置坐标 + set point(point: IPointData); + get width(): number; // 宽度 + set width(v: number); + get height(): number; // 高度 + set height(v: number); + get radius(): number; // 圆角半径 + set radius(v: number); + clone(): IRectData; + copyFrom(data: IRectData): void; + eq(other: IRectData): boolean; +} + +const rectConsts = { + lineWidth: 2, + lineColor: '0xff0000', +}; + +export class Rect extends JlGraphic { + static Type = 'Rect'; + rectGraphic: Graphics = new Graphics(); + constructor() { + super(Rect.Type); + this.addChild(this.rectGraphic); + } + + get datas(): IRectData { + return this.getDatas(); + } + doRepaint(): void { + const rectGraphic = this.rectGraphic; + rectGraphic.clear(); + rectGraphic.lineStyle( + this.datas.lineWidth, + new Color(this.datas.lineColor) + ); + const radius = this.datas?.radius || 0; + rectGraphic.drawRoundedRect( + 0, + 0, + this.datas.width, + this.datas.height, + radius + ); + rectGraphic.pivot = getRectangleCenter( + new Rectangle(0, 0, this.datas.width, this.datas.height) + ); + const transformPos = this.datas.transform.position; + if (transformPos.x == 0 && transformPos.y == 0) { + this.position.set( + this.datas.point.x + this.datas.width / 2, + this.datas.point.y + this.datas.height / 2 + ); + } else { + this.position.set( + this.datas.transform.position.x, + this.datas.transform.position.y + ); + } + } + rectPoints(): IPointData[] { + const r1 = new Point(this.datas.point.x, this.datas.point.y); + const r2 = new Point(r1.x + this.datas.width, r1.y); + const r3 = new Point(r1.x + this.datas.width, r1.y + this.datas.height); + const r4 = new Point(r1.x, r1.y + this.datas.height); + const rectPoints = [r1, r2, r3, r4, r1]; + return rectPoints; + } +} + +export class RectTemplate extends JlGraphicTemplate { + lineWidth: number; + lineColor: string; + constructor(dataTemplate: IRectData) { + super(Rect.Type, { + dataTemplate, + }); + this.lineWidth = rectConsts.lineWidth; + this.lineColor = rectConsts.lineColor; + } + new(): Rect { + return new Rect(); + } +} diff --git a/src/graphics/rect/RectDrawAssistant.ts b/src/graphics/rect/RectDrawAssistant.ts new file mode 100644 index 0000000..ea454e4 --- /dev/null +++ b/src/graphics/rect/RectDrawAssistant.ts @@ -0,0 +1,120 @@ +import { FederatedPointerEvent, Graphics, Point, IHitArea } from 'pixi.js'; +import { + GraphicDrawAssistant, + GraphicInteractionPlugin, + JlDrawApp, + JlGraphic, + linePoint, +} from 'src/jl-graphic'; + +import { IRectData, Rect, RectTemplate } from './Rect'; + +export interface IRectDrawOptions { + newData: () => IRectData; +} + +export class RectDraw extends GraphicDrawAssistant { + point1: Point | null = null; + point2: Point | null = null; + rectGraphic: Graphics = new Graphics(); + + constructor(app: JlDrawApp, template: RectTemplate) { + super(app, template, 'sym_o_square', '矩形Rect'); + this.container.addChild(this.rectGraphic); + rectInteraction.init(app); + } + + clearCache(): void { + this.rectGraphic.clear(); + } + onLeftDown(e: FederatedPointerEvent): void { + const { x, y } = this.toCanvasCoordinates(e.global); + const p = new Point(x, y); + if (this.point1 === null) { + this.point1 = p; + } else { + this.point2 = p; + this.createAndStore(true); + this.point1 = null; + this.point2 = null; + } + } + + redraw(p: Point): void { + const template = this.graphicTemplate; + if (this.point1 === null) return; + const rectGraphic = this.rectGraphic; + rectGraphic.clear(); + rectGraphic.lineStyle(template.lineWidth, template.lineColor); + rectGraphic.drawRect(...this.normalize(this.point1, p)); + } + //根据画的两个点确定左上角的点的坐标和矩形宽高 + private normalize(p1: Point, p2: Point): [number, number, number, number] { + const { abs } = Math; + const x = p1.x < p2.x ? p1.x : p2.x; + const y = p1.y < p2.y ? p1.y : p2.y; + const w = abs(p1.x - p2.x); + const h = abs(p1.y - p2.y); + return [x, y, w, h]; + } + prepareData(data: IRectData): boolean { + const p1 = this.point1 as Point; + const p2 = this.point2 as Point; + const [x, y, width, height] = this.normalize(p1, p2); + const template = this.graphicTemplate; + data.point = new Point(x, y); + data.lineWidth = template.lineWidth; + data.lineColor = template.lineColor; + data.width = width; + data.height = height; + return true; + } +} + +//碰撞检测 +export class RectGraphicHitArea implements IHitArea { + rect: Rect; + constructor(rect: Rect) { + this.rect = rect; + } + contains(x: number, y: number): boolean { + let contains = false; + const datas = this.rect.datas; + const tolerance = datas.lineWidth; + const p1 = new Point(0, 0); + const p2 = new Point(p1.x + datas.width, p1.y); + const p3 = new Point(p1.x + datas.width, p1.y + datas.height); + const p4 = new Point(p1.x, p1.y + datas.height); + const p = new Point(x, y); + contains = contains || linePoint(p1, p2, p, tolerance); + contains = contains || linePoint(p2, p3, p, tolerance); + contains = contains || linePoint(p3, p4, p, tolerance); + contains = contains || linePoint(p4, p1, p, tolerance); + return contains; + } +} + +export class rectInteraction extends GraphicInteractionPlugin { + static Name = 'platform_transform'; + constructor(app: JlDrawApp) { + super(rectInteraction.Name, app); + } + static init(app: JlDrawApp) { + return new rectInteraction(app); + } + filter(...grahpics: JlGraphic[]): Rect[] | undefined { + return grahpics.filter((g) => g.type === Rect.Type).map((g) => g as Rect); + } + bind(g: Rect): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.scalable = true; + g.rotatable = true; + g.rectGraphic.hitArea = new RectGraphicHitArea(g); + } + unbind(g: Rect): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + } +} diff --git a/src/graphics/runLine/RunLine.ts b/src/graphics/runLine/RunLine.ts new file mode 100644 index 0000000..d202292 --- /dev/null +++ b/src/graphics/runLine/RunLine.ts @@ -0,0 +1,292 @@ +import { Graphics, IPointData, LINE_JOIN, Point } from 'pixi.js'; +import { + GraphicData, + JlGraphic, + JlGraphicTemplate, + getNormalVector, + movePointAlongNormal, + getIntersectionPoint, + distance, +} from 'src/jl-graphic'; +import { RunLineName } from './RunLineName'; +import { PathLine } from '../pathLine/PathLine'; +import { PathLineDraw } from '../pathLine/PathLineDrawAssistant'; +import { getDrawApp } from 'src/drawApp'; +import { StationLine } from '../stationLine/StationLine'; +import { calculateDistanceFromPointToLine } from 'src/jl-graphic'; + +export interface IRunLineData extends GraphicData { + get code(): string; + set code(v: string); + get points(): IPointData[]; // 线坐标点 + set points(points: IPointData[]); + get nameColor(): string; + set nameColor(v: string); + get nameBgColor(): string; + set nameBgColor(v: string); + get containSta(): string[]; + set containSta(v: string[]); + get linkPathLines(): string[]; + set linkPathLines(v: string[]); + get lineId(): string; + set lineId(v: string); + + clone(): IRunLineData; + copyFrom(data: IRunLineData): void; + eq(other: IRunLineData): boolean; +} + +export enum RunLineColorEnum { + runLineColor = '0XC1F467', +} + +export const runLineConsts = { + runLineWidth: 6, + nameFontSize: 16, + nameOffsetX: 40, + pathLineDistance: 10, +}; + +export class RunLine extends JlGraphic { + static Type = 'RunLine'; + lineBody: Graphics = new Graphics(); + leftRunLineName: RunLineName = new RunLineName(); + rightRunLineName: RunLineName = new RunLineName(); + + constructor() { + super(RunLine.Type); + this.leftRunLineName.name = 'leftRunLineName'; + this.rightRunLineName.name = 'rightRunLineName'; + this.addChild(this.lineBody); + this.addChild(this.leftRunLineName); + this.addChild(this.rightRunLineName); + } + get datas(): IRunLineData { + return this.getDatas(); + } + + doRepaint(): void { + if (this.datas.points.length < 2) { + throw new Error('RunLine坐标数据异常'); + } + this.lineBody.clear(); + this.lineBody.lineStyle({ + width: runLineConsts.runLineWidth, + color: RunLineColorEnum.runLineColor, + join: LINE_JOIN.ROUND, + }); + const start = this.getStartPoint(); + this.lineBody.moveTo(start.x, start.y); + for (let i = 0; i < this.datas.points.length; i++) { + const p = this.datas.points[i]; + this.lineBody.lineTo(p.x, p.y); + } + + this.leftRunLineName.paint( + this.getStartPoint().x - runLineConsts.nameOffsetX, + this.getStartPoint().y, + this.datas + ); + + this.rightRunLineName.paint( + this.getEndPoint().x + runLineConsts.nameOffsetX, + this.getEndPoint().y, + this.datas + ); + } + get linePoints(): IPointData[] { + return this.datas.points; + } + set linePoints(points: IPointData[]) { + const old = this.datas.clone(); + old.points = points; + this.updateData(old); + } + + generatePathLine(points: Point[]) { + const pointsUp: Point[] = []; + const pointsDown: Point[] = []; + points.forEach((p, index) => { + // 起始点终止点计算两点法向量 做平移计算,中间点做线段法向量平移就交点 + if (index === 0) { + const normalVector = getNormalVector(p, points[index + 1]); + const resverNormalVector = [-normalVector[0], -normalVector[1]]; + pointsUp.push( + movePointAlongNormal(p, normalVector, runLineConsts.pathLineDistance) + ); + pointsDown.push( + movePointAlongNormal( + p, + resverNormalVector, + runLineConsts.pathLineDistance + ) + ); + } else if (index === points.length - 1) { + const normalVector = getNormalVector(points[index - 1], p); + const resverNormalVector = [-normalVector[0], -normalVector[1]]; + pointsUp.push( + movePointAlongNormal(p, normalVector, runLineConsts.pathLineDistance) + ); + pointsDown.push( + movePointAlongNormal( + p, + resverNormalVector, + runLineConsts.pathLineDistance + ) + ); + } else { + const normalVector1 = getNormalVector(p, points[index + 1]); + const resverNormalVector1 = [-normalVector1[0], -normalVector1[1]]; + const curP1 = movePointAlongNormal( + p, + normalVector1, + runLineConsts.pathLineDistance + ); + const nextP1 = movePointAlongNormal( + points[index + 1], + normalVector1, + runLineConsts.pathLineDistance + ); + const resverCurP1 = movePointAlongNormal( + p, + resverNormalVector1, + runLineConsts.pathLineDistance + ); + const resverNextP1 = movePointAlongNormal( + points[index + 1], + resverNormalVector1, + runLineConsts.pathLineDistance + ); + + const normalVector2 = getNormalVector(points[index - 1], p); + const resverNormalVector2 = [-normalVector2[0], -normalVector2[1]]; + + const curP2 = movePointAlongNormal( + p, + normalVector2, + runLineConsts.pathLineDistance + ); + const nextP2 = movePointAlongNormal( + points[index - 1], + normalVector2, + runLineConsts.pathLineDistance + ); + const resverCurP2 = movePointAlongNormal( + p, + resverNormalVector2, + runLineConsts.pathLineDistance + ); + const resverNextP2 = movePointAlongNormal( + points[index - 1], + resverNormalVector2, + runLineConsts.pathLineDistance + ); + pointsUp.push( + getIntersectionPoint( + [curP1.x, curP1.y, nextP1.x, nextP1.y], + [curP2.x, curP2.y, nextP2.x, nextP2.y] + ) + ); + pointsDown.push( + getIntersectionPoint( + [resverCurP1.x, resverCurP1.y, resverNextP1.x, resverNextP1.y], + [resverCurP2.x, resverCurP2.y, resverNextP2.x, resverNextP2.y] + ) + ); + } + }); + const app = getDrawApp(); + if (!app) return; + const pathLineDrawAssistant = app.getDrawAssistant( + PathLine.Type + ) as PathLineDraw; + if (this.datas.linkPathLines.length) { + } + this.datas.linkPathLines.forEach((item) => { + const oldUp = app.queryStore.queryById(item); + if (oldUp) { + app.deleteGraphics(oldUp); + } + }); + const pathLineUp = pathLineDrawAssistant.quickCreate( + pointsUp, + this.datas.lineId + ); + const pathLineDown = pathLineDrawAssistant.quickCreate( + pointsDown, + this.datas.lineId + ); + this.datas.linkPathLines = [pathLineUp?.id || '', pathLineDown?.id || '']; + this.generatePathLineKilometerPoints(); + } + + getStartPoint(): IPointData { + return this.datas.points[0]; + } + getEndPoint(): IPointData { + return this.datas.points[this.datas.points.length - 1]; + } + onDelete(): void { + super.onDelete(); + const app = getDrawApp(); + if (!app) return; + this.datas.linkPathLines.forEach((item) => { + const oldUp = app.queryStore.queryById(item); + if (oldUp) { + app.deleteGraphics(oldUp); + } + }); + } + generateContainSta(): void { + const app = getDrawApp(); + if (!app) return; + const stations = app.queryStore.queryByType(StationLine.Type); + const containSta: string[] = []; + this.datas.points.forEach((p, index) => { + if (index) { + stations.forEach((station) => { + const sp = station.position; + const prep = this.datas.points[index - 1]; + const distanceF = calculateDistanceFromPointToLine( + p, + this.datas.points[index - 1], + station.position + ); + const distance1 = distance(sp.x, sp.y, prep.x, prep.y); + const distance2 = distance(sp.x, sp.y, p.x, p.y); + const distance3 = distance(p.x, p.y, prep.x, prep.y); + if ( + distanceF < 4 && + distance1 <= distance3 + distanceF && + distance2 <= distance3 + distanceF && + !containSta.includes(station.id) + ) { + containSta.push(station.id); + } + }); + } + }); + this.datas.containSta = containSta; + } + generatePathLineKilometerPoints(): void { + const app = getDrawApp(); + if (!app) return; + this.datas.linkPathLines.forEach((item) => { + const pathLine = app.queryStore.queryById(item) as PathLine; + pathLine.generatePathLineKilometerPoints(this.datas.containSta); + }); + } +} + +export class RunLineTemplate extends JlGraphicTemplate { + runLineColor: string; + runLineWidth: number; + constructor(dataTemplate: IRunLineData) { + super(RunLine.Type, { dataTemplate }); + this.runLineColor = RunLineColorEnum.runLineColor; + this.runLineWidth = runLineConsts.runLineWidth; + } + new(): RunLine { + return new RunLine(); + } +} diff --git a/src/graphics/runLine/RunLineDrawAssistant.ts b/src/graphics/runLine/RunLineDrawAssistant.ts new file mode 100644 index 0000000..914e690 --- /dev/null +++ b/src/graphics/runLine/RunLineDrawAssistant.ts @@ -0,0 +1,232 @@ +import { + GraphicDrawAssistant, + JlDrawApp, + JlGraphic, + GraphicInteractionPlugin, + linePoint, + GraphicApp, + AbsorbablePosition, + DraggablePoint, + GraphicTransformEvent, +} from 'src/jl-graphic'; +import { + IRunLineData, + RunLine, + RunLineTemplate, + runLineConsts, +} from './RunLine'; +import { + PolylineEditPlugin, + ILineGraphic, +} from 'src/jl-graphic/plugins/GraphicEditPlugin'; +import { + FederatedPointerEvent, + Point, + Graphics, + LINE_JOIN, + IHitArea, + DisplayObject, +} from 'pixi.js'; +import { AbsorbableLine } from 'src/jl-graphic/graphic/AbsorbablePosition'; + +export interface IRunLineDrawOptions { + newData: () => IRunLineData; +} + +export class RunLineDraw extends GraphicDrawAssistant< + RunLineTemplate, + IRunLineData +> { + points: Point[] = []; + graphic: Graphics = new Graphics(); + + constructor(app: JlDrawApp, template: RunLineTemplate) { + super(app, template, 'sym_o_horizontal_rule', '运行线RunLine'); + this.container.addChild(this.graphic); + RunLinePointsEditPlugin.init(app); + } + + clearCache(): void { + this.points = []; + this.graphic.clear(); + } + onRightClick(): void { + if (this.points.length > 1) this.createAndStore(true); + } + onEsc() { + if (this.points.length > 1) this.createAndStore(true); + } + // createAndStore(); + onLeftDown(e: FederatedPointerEvent): void { + const { x, y } = this.toCanvasCoordinates(e.global); + const p = new Point(x, y); + this.points.push(p); + } + redraw(p: Point): void { + if (this.points.length < 1) return; + this.graphic.clear(); + const template = this.graphicTemplate; + this.graphic.lineStyle({ + width: template.runLineWidth, + color: template.runLineColor, + join: LINE_JOIN.ROUND, + }); + const ps = [...this.points]; + ps.push(p); + // 直线 + this.graphic.moveTo(ps[0].x, ps[0].y); + for (let i = 1; i < ps.length; i++) { + const p = ps[i]; + this.graphic.lineTo(p.x, p.y); + } + } + prepareData(data: IRunLineData): boolean { + data.points = this.points; + return true; + } +} + +export class RunLineGraphicHitArea implements IHitArea { + runLine: RunLine; + constructor(runLine: RunLine) { + this.runLine = runLine; + } + contains(x: number, y: number): boolean { + const p = new Point(x, y); + for (let i = 1; i < this.runLine.datas.points.length; i++) { + const p1 = this.runLine.datas.points[i - 1]; + const p2 = this.runLine.datas.points[i]; + if (linePoint(p1, p2, p, runLineConsts.runLineWidth)) { + return true; + } + } + return false; + } +} + +function buildAbsorbablePositions( + runLine: RunLine, + dpIndex: number +): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + const canvas = runLine.getCanvas(); + if (runLine.linePoints[dpIndex - 1]) { + const preP = runLine.localToCanvasPoint(runLine.linePoints[dpIndex - 1]); + const ala = new AbsorbableLine( + new Point(preP.x, 0), + new Point(preP.x, canvas.height) + ); + const alb = new AbsorbableLine( + new Point(0, preP.y), + new Point(canvas.width, preP.y) + ); + aps.push(ala); + aps.push(alb); + } + if (runLine.linePoints[dpIndex + 1]) { + const nextP = runLine.localToCanvasPoint(runLine.linePoints[dpIndex + 1]); + const ala = new AbsorbableLine( + new Point(nextP.x, 0), + new Point(nextP.x, canvas.height) + ); + const alb = new AbsorbableLine( + new Point(0, nextP.y), + new Point(canvas.width, nextP.y) + ); + aps.push(ala); + aps.push(alb); + } + return aps; +} + +/** + * 端点拖拽添加吸附位置 + * @param g + * @param dp + * @param index + */ +function onEditPointCreate( + g: ILineGraphic, + dp: DraggablePoint, + index: number +): void { + const runLine = g as RunLine; + dp.on('transformstart', (e: GraphicTransformEvent) => { + if (e.isShift()) { + runLine.getGraphicApp().setOptions({ + absorbablePositions: buildAbsorbablePositions(runLine, index), + }); + } + }); +} + +export class RunLinePointsEditPlugin extends GraphicInteractionPlugin { + static Name = 'LinkPointsDrag'; + constructor(app: GraphicApp) { + super(RunLinePointsEditPlugin.Name, app); + } + static init(app: GraphicApp): RunLinePointsEditPlugin { + return new RunLinePointsEditPlugin(app); + } + filter(...grahpics: JlGraphic[]): RunLine[] | undefined { + return grahpics.filter((g) => g.type == RunLine.Type) as RunLine[]; + } + bind(g: RunLine): void { + g.lineBody.eventMode = 'static'; + g.lineBody.cursor = 'pointer'; + g.leftRunLineName.draggable = true; + g.leftRunLineName.selectable = true; + g.leftRunLineName.rotatable = true; + g.leftRunLineName.transformSave = true; + g.leftRunLineName.eventMode = 'static'; + g.leftRunLineName.cursor = 'pointer'; + + g.rightRunLineName.draggable = true; + g.rightRunLineName.selectable = true; + g.rightRunLineName.rotatable = true; + g.rightRunLineName.transformSave = true; + g.rightRunLineName.eventMode = 'static'; + g.rightRunLineName.cursor = 'pointer'; + g.lineBody.hitArea = new RunLineGraphicHitArea(g); + g.on('selected', this.onSelected, this); + g.on('unselected', this.onUnselected, this); + } + unbind(g: RunLine): void { + g.leftRunLineName.draggable = false; + g.leftRunLineName.selectable = false; + g.leftRunLineName.rotatable = false; + g.leftRunLineName.transformSave = false; + g.leftRunLineName.eventMode = 'none'; + + g.rightRunLineName.draggable = false; + g.rightRunLineName.selectable = false; + g.rightRunLineName.rotatable = false; + g.rightRunLineName.transformSave = false; + g.rightRunLineName.eventMode = 'none'; + + g.off('selected', this.onSelected, this); + g.off('unselected', this.onUnselected, this); + } + + onSelected(g: DisplayObject): void { + const runLine = g as RunLine; + let lep; + lep = runLine.getAssistantAppend( + PolylineEditPlugin.Name + ); + if (!lep) { + lep = new PolylineEditPlugin(runLine, { onEditPointCreate }); + runLine.addAssistantAppend(lep); + } + lep.showAll(); + } + onUnselected(g: DisplayObject): void { + const runLine = g as RunLine; + const lep = runLine.getAssistantAppend( + PolylineEditPlugin.Name + ); + if (lep) { + lep.hideAll(); + } + } +} diff --git a/src/graphics/runLine/RunLineName.ts b/src/graphics/runLine/RunLineName.ts new file mode 100644 index 0000000..6a60f06 --- /dev/null +++ b/src/graphics/runLine/RunLineName.ts @@ -0,0 +1,46 @@ +import { Container } from '@pixi/display'; +import { Graphics } from 'pixi.js'; +import { VectorText } from 'src/jl-graphic'; +import { IRunLineData } from './RunLine'; + +const nameConsts = { + padding: 8, + nameFontSize: 16, + defaultNameColor: '0X000000', + defaultBgColor: '0X0ff000', + bgRadius: 6, +}; + +export class RunLineName extends Container { + nameBg: Graphics = new Graphics(); + runLineName: VectorText = new VectorText(); + + constructor() { + super(); + this.addChild(this.nameBg); + this.addChild(this.runLineName); + } + paint(x: number, y: number, data: IRunLineData) { + this.runLineName.text = data.code || '运行线'; + this.runLineName.style.fill = data.nameColor || nameConsts.defaultNameColor; + this.runLineName.setVectorFontSize(nameConsts.nameFontSize); + this.runLineName.anchor.set(0.5); + this.runLineName.position.set(x, y); + + const nameRect = this.runLineName.getLocalBounds(); + this.nameBg.clear(); + if (!this.nameBg.drawRoundedRect) { + return; + } + this.nameBg.beginFill(data.nameBgColor || nameConsts.defaultBgColor, 1); + this.nameBg + .drawRoundedRect( + nameRect.x - nameConsts.padding / 2 + x, + nameRect.y - nameConsts.padding / 2 + y, + nameRect.width + nameConsts.padding, + nameRect.height + nameConsts.padding, + nameConsts.bgRadius + ) + .endFill(); + } +} diff --git a/src/graphics/section/Section.ts b/src/graphics/section/Section.ts new file mode 100644 index 0000000..7d0ade5 --- /dev/null +++ b/src/graphics/section/Section.ts @@ -0,0 +1,256 @@ +import { Graphics, IPointData } from 'pixi.js'; +import { + GraphicData, + GraphicRelationParam, + JlGraphic, + JlGraphicTemplate, + VectorText, + distance2, + splitLineEvenly, +} from 'src/jl-graphic'; +import { ILineGraphic } from 'src/jl-graphic/plugins/GraphicEditPlugin'; +import { epsilon } from 'src/jl-graphic/math'; +import { + IRelatedRefData, + createRelatedRefProto, + protoPort2Data, +} from '../CommonGraphics'; +import { Turnout } from '../turnout/Turnout'; +import { SectionData } from 'src/drawApp/graphics/SectionInteraction'; + +export enum SectionType { + Physical = 0, + Logic = 1, + TurnoutPhysical = 2, +} + +export enum SectionPort { + A = 'A', + B = 'B', +} + +export interface ISectionData extends GraphicData { + get code(): string; // 编号 + set code(v: string); + get points(): IPointData[]; // 线坐标点 + set points(points: IPointData[]); + get paRef(): IRelatedRefData | undefined; + set paRef(ref: IRelatedRefData | undefined); + get pbRef(): IRelatedRefData | undefined; + set pbRef(ref: IRelatedRefData | undefined); + get sectionType(): SectionType; + set sectionType(type: SectionType); + get children(): string[]; + set children(children: string[]); + clone(): ISectionData; + copyFrom(data: ISectionData): void; + eq(other: ISectionData): boolean; +} + +export const SectionConsts = { + lineColor: '#5578b6', + lineWidth: 5, +}; + +export class Section extends JlGraphic implements ILineGraphic { + static Type = 'Section'; + lineGraphic: Graphics; + labelGraphic: VectorText; + childSections: Section[] = []; + + constructor() { + super(Section.Type); + this.lineGraphic = new Graphics(); + this.labelGraphic = new VectorText(); + this.labelGraphic.setVectorFontSize(14); + this.labelGraphic.anchor.set(0.5); + this.labelGraphic.style.fill = '#0f0'; + this.labelGraphic.transformSave = true; + this.labelGraphic.name = 'label'; + this.transformSave = true; + this.addChild(this.lineGraphic); + this.addChild(this.labelGraphic); + } + + doRepaint() { + if (this.datas.points.length < 2) { + throw new Error('Link坐标数据异常'); + } + + this.lineGraphic.clear(); + if ( + (this.datas.sectionType === SectionType.Physical && + this.datas.children.length === 0) /* 未拆分的物理区段 */ || + this.datas.sectionType === SectionType.Logic /* 逻辑区段 */ + ) { + this.lineGraphic.lineStyle( + SectionConsts.lineWidth, + SectionConsts.lineColor + ); + + this.datas.points.forEach((p, i) => { + if (i !== 0) { + this.lineGraphic.lineTo(p.x, p.y); + } else { + this.lineGraphic.moveTo(p.x, p.y); + } + }); + } + + this.labelGraphic.text = this.datas.code; + const labelPosition = this.datas.childTransforms?.find( + (t) => t.name === this.labelGraphic.name + )?.transform.position; + if (labelPosition) { + this.labelGraphic.position.set(labelPosition.x, labelPosition.y); + } else { + this.labelGraphic.position.set( + this.datas.points[0].x, + this.datas.points[0].y + 20 + ); + } + } + + getStartPoint() { + return this.datas.points[0]; + } + getEndPoint(): IPointData { + return this.datas.points[this.datas.points.length - 1]; + } + + get datas(): ISectionData { + return this.getDatas(); + } + + get linePoints(): IPointData[] { + return this.datas.points; + } + set linePoints(points: IPointData[]) { + const old = this.datas.clone(); + old.points = points; + this.updateData(old); + } + + /** 获取拆分逻辑区段数据 */ + getSplitPoints(count: number): IPointData[][] { + if (this.datas.points.length !== 2) { + throw Error('多段分割待实现'); + } + return splitLineEvenly( + this.datas.points[0], + this.datas.points[this.datas.points.length - 1], + count + ); + } + + buildRelation() { + this.relationManage.deleteRelationOfGraphicAndOtherType(this, Section.Type); + /** 区段与区段 */ + this.queryStore.queryByType
(Section.Type).forEach((section) => { + if (section.id === this.id) return; + + let param: SectionPort[] = []; + if ( + distance2( + this.localToCanvasPoint(this.getStartPoint()), + section.localToCanvasPoint(section.getStartPoint()) + ) <= epsilon + ) { + param = [SectionPort.A, SectionPort.A]; + } + if ( + distance2( + this.localToCanvasPoint(this.getEndPoint()), + section.localToCanvasPoint(section.getStartPoint()) + ) <= epsilon + ) { + param = [SectionPort.B, SectionPort.A]; + } + if ( + distance2( + this.localToCanvasPoint(this.getStartPoint()), + section.localToCanvasPoint(section.getEndPoint()) + ) <= epsilon + ) { + param = [SectionPort.A, SectionPort.B]; + } + if ( + distance2( + this.localToCanvasPoint(this.getEndPoint()), + section.localToCanvasPoint(section.getEndPoint()) + ) <= epsilon + ) { + param = [SectionPort.B, SectionPort.B]; + } + if (param.length) { + this.relationManage.addRelation( + new GraphicRelationParam(this, param[0]), + new GraphicRelationParam(section, param[1]) + ); + } + }); + } + + saveRelations() { + const paRelation = this.relationManage + .getRelationsOfGraphic(this) + .find( + (relation) => relation.getRelationParam(this).param === SectionPort.A + ); + const paDevice = paRelation?.getOtherGraphic
(this); + if (paDevice) { + this.datas.paRef = createRelatedRefProto( + paDevice.type, + paDevice.id, + paRelation?.getOtherRelationParam(this).param + ); + } else { + this.datas.paRef = undefined; + } + const pbRelation = this.relationManage + .getRelationsOfGraphic(this) + .find( + (relation) => relation.getRelationParam(this).param === SectionPort.B + ); + const pbDevice = pbRelation?.getOtherGraphic
(this); + if (pbDevice) { + this.datas.pbRef = createRelatedRefProto( + pbDevice.type, + pbDevice.id, + pbRelation?.getOtherRelationParam(this).param + ); + } else { + this.datas.pbRef = undefined; + } + } + + loadRelations() { + if (this.datas?.paRef?.id) { + this.relationManage.addRelation( + new GraphicRelationParam(this, SectionPort.A), + new GraphicRelationParam( + this.queryStore.queryById(this.datas.paRef.id), + protoPort2Data(this.datas.paRef.devicePort) + ) + ); + } + if (this.datas?.pbRef?.id) { + this.relationManage.addRelation( + new GraphicRelationParam(this, SectionPort.B), + new GraphicRelationParam( + this.queryStore.queryById(this.datas.pbRef.id), + protoPort2Data(this.datas.pbRef.devicePort) + ) + ); + } + } +} + +export class SectionTemplate extends JlGraphicTemplate
{ + constructor(dataTemplate: ISectionData) { + super(Section.Type, { dataTemplate }); + } + new() { + return new Section(); + } +} diff --git a/src/graphics/section/SectionDrawAssistant.ts b/src/graphics/section/SectionDrawAssistant.ts new file mode 100644 index 0000000..c27d8da --- /dev/null +++ b/src/graphics/section/SectionDrawAssistant.ts @@ -0,0 +1,261 @@ +import { + ChildTransform, + DraggablePoint, + GraphicApp, + GraphicDrawAssistant, + GraphicInteractionPlugin, + GraphicTransform, + GraphicTransformEvent, + JlDrawApp, + JlGraphic, + VectorText, + linePoint, +} from 'src/jl-graphic'; +import { + ISectionData, + Section, + SectionConsts, + SectionTemplate, +} from './Section'; +import { + DisplayObject, + FederatedMouseEvent, + Graphics, + IHitArea, + Point, +} from 'pixi.js'; +import { + IEditPointOptions, + ILineGraphic, + PolylineEditPlugin, +} from 'src/jl-graphic/plugins/GraphicEditPlugin'; +import AbsorbablePoint, { + AbsorbableLine, + AbsorbablePosition, +} from 'src/jl-graphic/graphic/AbsorbablePosition'; +import { Turnout } from '../turnout/Turnout'; + +export class SectionDraw extends GraphicDrawAssistant< + SectionTemplate, + ISectionData +> { + points: Point[] = []; + graphic = new Graphics(); + + constructor(app: JlDrawApp, template: SectionTemplate) { + super(app, template, 'sym_o_timeline', '区段Section'); + this.container.addChild(this.graphic); + + SectionPointEditPlugin.init(app); + } + + onLeftDown(e: FederatedMouseEvent): void { + const { x, y } = this.toCanvasCoordinates(e.global); + const p = new Point(x, y); + this.points.push(p); + } + + onRightClick(): void { + if (this.points.length < 2) { + this.finish(); + return; + } + this.createAndStore(true); + } + + onEsc(): void { + if (this.points.length < 2) { + this.finish(); + return; + } + this.createAndStore(true); + } + + redraw(cp: Point): void { + if (this.points.length < 1) return; + this.graphic.clear(); + this.graphic.lineStyle(SectionConsts.lineWidth, SectionConsts.lineColor); + this.points.forEach((p, i) => { + if (i !== 0) { + this.graphic.lineTo(p.x, p.y); + } else { + this.graphic.moveTo(p.x, p.y); + } + }); + this.graphic.lineTo(cp.x, cp.y); + } + + prepareData(data: ISectionData): boolean { + data.points = this.points; + data.code = 'G000'; + data.childTransforms?.push( + new ChildTransform( + 'label', + new GraphicTransform( + { + x: data.points[1].x - data.points[0].x, + y: data.points[1].y - data.points[0].y + 20, + }, + { x: 0, y: 0 }, + 0, + { x: 0, y: 0 } + ) + ) + ); + + return true; + } + + clearCache(): void { + this.points = []; + this.graphic.clear(); + } +} + +class SectionGraphicHitArea implements IHitArea { + section: Section; + constructor(section: Section) { + this.section = section; + } + contains(x: number, y: number): boolean { + for (let i = 1; i < this.section.datas.points.length; i++) { + const p1 = this.section.datas.points[i - 1]; + const p2 = this.section.datas.points[i]; + if (linePoint(p1, p2, { x, y }, SectionConsts.lineWidth)) { + return true; + } + } + return false; + } +} + +function buildAbsorbablePositions(section: Section): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + + const sections = section.queryStore.queryByType
(Section.Type); + sections.forEach((other) => { + const [ps, pe] = [ + other.localToCanvasPoint(other.getStartPoint()), + other.localToCanvasPoint(other.getEndPoint()), + ]; + const { width, height } = section.getGraphicApp().canvas; + const xs = new AbsorbableLine({ x: 0, y: ps.y }, { x: width, y: ps.y }); + const ys = new AbsorbableLine({ x: ps.x, y: 0 }, { x: ps.x, y: height }); + const xe = new AbsorbableLine({ x: 0, y: pe.y }, { x: width, y: pe.y }); + const ye = new AbsorbableLine({ x: pe.x, y: 0 }, { x: pe.x, y: height }); + aps.push(xs, ys, xe, ye); + }); + + const turnouts = section.queryStore.queryByType(Turnout.Type); + turnouts.forEach((turnout) => { + turnout.getPortPoints().forEach((points) => { + turnout.localToCanvasPoints(...points).forEach((p) => { + aps.push(new AbsorbablePoint(p)); + }); + }); + }); + + return aps; +} + +function onEditPointCreate( + g: ILineGraphic, + dp: DraggablePoint, + index: number +): void { + const section = g as Section; + dp.on('transformstart', (e: GraphicTransformEvent) => { + if (e.isShift()) { + section.getGraphicApp().setOptions({ + absorbablePositions: buildAbsorbablePositions(section), + }); + } + }); +} + +class SectionPolylineEditPlugin extends PolylineEditPlugin { + static Name = 'SectionPolylineEditPlugin'; + labels: VectorText[] = []; + constructor(g: ILineGraphic, options?: IEditPointOptions) { + super(g, options); + this.name = SectionPolylineEditPlugin.Name; + this.initLabels(); + } + + initLabels() { + this.labels = [new VectorText('A'), new VectorText('B')]; + this.labels.forEach((label) => { + label.setVectorFontSize(14); + this.addChild(label); + }); + this.updateEditedPointsPosition(); + } + + reset(): void { + super.reset(); + this.initLabels(); + } + + updateEditedPointsPosition() { + super.updateEditedPointsPosition(); + this.labels[0]?.position.set( + this.editedPoints[0].x, + this.editedPoints[0].y + 10 + ); + this.labels[1]?.position.set( + this.editedPoints[this.editedPoints.length - 1].x, + this.editedPoints[this.editedPoints.length - 1].y + 10 + ); + } +} + +export class SectionPointEditPlugin extends GraphicInteractionPlugin
{ + static Name = 'SectionPointDrag'; + + constructor(app: GraphicApp) { + super(SectionPointEditPlugin.Name, app); + } + static init(app: GraphicApp) { + return new SectionPointEditPlugin(app); + } + filter(...grahpics: JlGraphic[]): Section[] | undefined { + return grahpics.filter((g) => g.type == Section.Type) as Section[]; + } + bind(g: Section): void { + g.lineGraphic.eventMode = 'static'; + g.lineGraphic.cursor = 'pointer'; + g.lineGraphic.hitArea = new SectionGraphicHitArea(g); + g.transformSave = true; + g.labelGraphic.eventMode = 'static'; + g.labelGraphic.cursor = 'pointer'; + g.labelGraphic.selectable = true; + g.labelGraphic.draggable = true; + g.on('selected', this.onSelected, this); + g.on('unselected', this.onUnselected, this); + } + unbind(g: Section): void { + g.off('selected', this.onSelected, this); + g.off('unselected', this.onUnselected, this); + } + + onSelected(g: DisplayObject): void { + const section = g as Section; + let lep = section.getAssistantAppend( + SectionPolylineEditPlugin.Name + ); + if (!lep) { + lep = new SectionPolylineEditPlugin(section, { onEditPointCreate }); + section.addAssistantAppend(lep); + } + lep.showAll(); + } + onUnselected(g: DisplayObject): void { + const section = g as Section; + const lep = section.getAssistantAppend( + SectionPolylineEditPlugin.Name + ); + if (lep) { + lep.hideAll(); + } + } +} diff --git a/src/graphics/separator/Separator.ts b/src/graphics/separator/Separator.ts new file mode 100644 index 0000000..032ee1e --- /dev/null +++ b/src/graphics/separator/Separator.ts @@ -0,0 +1,94 @@ +import { Color, Graphics } from 'pixi.js'; +import { GraphicData, JlGraphic, JlGraphicTemplate } from 'src/jl-graphic'; + +export interface ISeparatorData extends GraphicData { + get code(): string; // 编号 + set code(v: string); + get separatorType(): string; // 类型 + set separatorType(v: string); + clone(): ISeparatorData; + copyFrom(data: ISeparatorData): void; + eq(other: ISeparatorData): boolean; +} + +export enum separatorTypeEnum { + turnout = 'turnout', // 道岔分隔符 + endA = 'endA', // A端尽头分隔符 + endB = 'endB', // B端尽头分隔符 + section = 'section', // 区段分隔符 +} + +export const SeparatorConsts = { + height: 15, + lineWidth: 2, + lineColor: '0x617799', + circleColor: '0xEF0200', + radius: 5, +}; + +export class Separator extends JlGraphic { + static Type = 'Separator'; + rectGraphic: Graphics = new Graphics(); + circleGraphic: Graphics = new Graphics(); + constructor() { + super(Separator.Type); + this.addChild(this.rectGraphic); + this.addChild(this.circleGraphic); + } + get datas(): ISeparatorData { + return this.getDatas(); + } + clear() { + this.rectGraphic.clear(); + this.circleGraphic.clear(); + } + doRepaint(): void { + this.clear(); + const rectGraphic = this.rectGraphic; + if (!this.datas.separatorType) { + this.datas.separatorType = separatorTypeEnum.endA; + } + const typeArr = ['section', 'turnout']; + if (typeArr.includes(this.datas.separatorType)) { + rectGraphic.lineStyle( + SeparatorConsts.lineWidth, + new Color(SeparatorConsts.lineColor) + ); + rectGraphic.moveTo(0, -SeparatorConsts.height / 2); + rectGraphic.lineTo(0, SeparatorConsts.height / 2); + if (this.datas.separatorType == 'turnout') { + this.circleGraphic.lineStyle(1, SeparatorConsts.circleColor); + this.circleGraphic.drawCircle(0, 0, SeparatorConsts.radius); + } + } + const endTypeArr = ['endA', 'endB']; + if (endTypeArr.includes(this.datas.separatorType)) { + let d = SeparatorConsts.radius; + if (this.datas.separatorType == 'endB') { + d = -d; + } + rectGraphic.lineStyle( + SeparatorConsts.lineWidth, + new Color(SeparatorConsts.lineColor) + ); + rectGraphic.moveTo(0, 0); + rectGraphic.lineTo(-d, 0); + rectGraphic.lineTo(-d, -d); + rectGraphic.lineTo(-d * 3, -d); + rectGraphic.moveTo(-d, 0); + rectGraphic.lineTo(-d, d); + rectGraphic.lineTo(-d * 3, d); + } + } +} + +export class SeparatorTemplate extends JlGraphicTemplate { + constructor(dataTemplate: ISeparatorData) { + super(Separator.Type, { + dataTemplate, + }); + } + new(): Separator { + return new Separator(); + } +} diff --git a/src/graphics/separator/SeparatorDrawAssistant.ts b/src/graphics/separator/SeparatorDrawAssistant.ts new file mode 100644 index 0000000..d1a1453 --- /dev/null +++ b/src/graphics/separator/SeparatorDrawAssistant.ts @@ -0,0 +1,269 @@ +import { FederatedPointerEvent, IHitArea, Point } from 'pixi.js'; +import { + GraphicDrawAssistant, + GraphicIdGenerator, + GraphicInteractionPlugin, + GraphicRelationParam, + JlDrawApp, + JlGraphic, + linePoint, +} from 'src/jl-graphic'; +import { Section, SectionType } from '../section/Section'; +import { + ISeparatorData, + Separator, + SeparatorConsts, + SeparatorTemplate, + separatorTypeEnum, +} from './Separator'; +import { SeparatorData } from 'src/drawApp/graphics/SeparatorInteraction'; +import { Turnout } from '../turnout/Turnout'; + +export class SeparatorDraw extends GraphicDrawAssistant< + SeparatorTemplate, + ISeparatorData +> { + SeparatorGraph: Separator; + constructor(app: JlDrawApp, template: SeparatorTemplate) { + super(app, template, 'sym_o_square', '不展示'); + this.SeparatorGraph = this.graphicTemplate.new(); + this.container.addChild(this.SeparatorGraph); + SeparatorInteraction.init(app); + } + + bind(): void { + super.bind(); + this.SeparatorGraph.loadData(this.graphicTemplate.datas); + this.SeparatorGraph.doRepaint(); + } + + onLeftDown(e: FederatedPointerEvent): void { + this.container.position.copyFrom(this.toCanvasCoordinates(e.global)); + this.createAndStore(true); + } + + redraw(p: Point): void { + this.container.position.copyFrom(p); + } + + prepareData(data: ISeparatorData): boolean { + data.transform = this.container.saveTransform(); + return true; + } + oneGenerates() { + const SeparatorAll = this.app.queryStore.queryByType( + Separator.Type + ); + this.app.deleteGraphics(...SeparatorAll); + const rMap = new Map(); + const sections = this.app.queryStore.queryByType
(Section.Type); + const turnouts = this.app.queryStore.queryByType(Turnout.Type); + function setKey(gr: GraphicRelationParam): string { + let key = ''; + key = `${gr.g.id}_${gr.param}`; + return key; + } + const arrType = [Section.Type, Turnout.Type]; // 只统计关联关系是道岔和区段的 + sections.forEach((section) => { + const allR = section.relationManage + .getRelationsOfGraphic(section) + .filter((ref) => { + return arrType.includes(ref.getOtherGraphic(section).type); + }); + const port: string[] = []; + allR.forEach((relation, index) => { + const r = relation.getRelationParam(section); + const other = relation.getOtherRelationParam(section); + if (!section.datas.children.includes(other.g.id)) { + // 排除物理区段和自身逻辑区段的关联关系 + port.push(r.param); + } + if (!rMap.has(setKey(r))) { + rMap.set(setKey(r), { ...r }); + } + if (!rMap.has(setKey(other))) { + rMap.set(setKey(other), { ...other, repetition: true }); + } + if (section.datas.sectionType === SectionType.Logic) { + // 逻辑区段没有断路分隔符 + return; + } + if (index == allR.length - 1) { + if (!port.includes('A')) { + rMap.set(`${section.id}_A`, { + g: section, + param: 'A', + separatorType: separatorTypeEnum.endA, + }); + } + if (!port.includes('B')) { + rMap.set(`${section.id}_B`, { + g: section, + param: 'B', + separatorType: separatorTypeEnum.endB, + }); + } + } + }); + }); + turnouts.forEach((turnout) => { + const allR = turnout.relationManage + .getRelationsOfGraphic(turnout) + .filter((ref) => { + return arrType.includes(ref.getOtherGraphic(turnout).type); + }); + const port: string[] = []; + allR.forEach((relation, index) => { + const r = relation.getRelationParam(turnout); + port.push(r.param); + const other = relation.getOtherRelationParam(turnout); + let t = separatorTypeEnum.section; + if ( + (r.param == 'C' && other.param == 'C') || + (r.g.type == Turnout.Type && + other.g.type == Turnout.Type && + (r.param == 'C' || other.param == 'C')) + ) { + t = separatorTypeEnum.turnout; + } + if (!rMap.has(setKey(r))) { + rMap.set(setKey(r), { + ...r, + separatorType: t, + }); + } + if (!rMap.has(setKey(other))) { + rMap.set(setKey(other), { + ...other, + separatorType: t, + repetition: true, + }); + } + if (index == allR.length - 1) { + const ps = turnout.getPortPoints(); + let isALeft = true; // 判断A端在左还是右 + if (ps[0][ps[0].length - 1].x > ps[1][ps[1].length - 1].x) { + isALeft = false; + } + if (!port.includes('A')) { + rMap.set(`${turnout.id}_A`, { + g: turnout, + param: 'A', + separatorType: isALeft + ? separatorTypeEnum.endA + : separatorTypeEnum.endB, + }); + } + if (!port.includes('B')) { + rMap.set(`${turnout.id}_B`, { + g: turnout, + param: 'B', + separatorType: isALeft + ? separatorTypeEnum.endB + : separatorTypeEnum.endA, + }); + } + } + }); + }); + rMap.forEach((item) => { + if (!item.repetition) { + let p; + if (item.g.type == Section.Type) { + p = item.g.getStartPoint(); + if (item.param == 'B') { + p = item.g.getEndPoint(); + } + } else if (item.g.type == Turnout.Type) { + const ps = item.g.getPortPoints(); + let l = 2; + if (item.param == 'A') { + l = 0; + } else if (item.param == 'B') { + l = 1; + } + const lps = ps[l]; + p = lps[lps.length - 1]; + } + const tps = item.g.localToCanvasPoint(p); + const sType = item.separatorType || separatorTypeEnum.section; + this.createSeparator(sType, tps); + } + }); + } + createSeparator(separatorType: separatorTypeEnum, tps: Point) { + const separator = new Separator(); + const data = new SeparatorData(); + data.separatorType = separatorType; + separator.loadData(data); + separator.position.set(tps.x, tps.y); + separator.id = GraphicIdGenerator.next(); + this.storeGraphic(separator); + } +} + +//碰撞检测 +export class SeparatorGraphicHitArea implements IHitArea { + separator: Separator; + constructor(separator: Separator) { + this.separator = separator; + } + contains(x: number, y: number): boolean { + let contains = false; + const p = new Point(x, y); + const typeArr = ['section', 'turnout']; + const endTypeArr = ['endA', 'endB']; + let d = SeparatorConsts.radius; + if (typeArr.includes(this.separator.datas.separatorType)) { + const tolerance = SeparatorConsts.lineWidth; + const p1 = new Point(0, -SeparatorConsts.height / 2); + const p2 = new Point(0, SeparatorConsts.height / 2); + contains = contains || linePoint(p1, p2, p, tolerance); + return contains; + } else if (endTypeArr.includes(this.separator.datas.separatorType)) { + if (this.separator.datas.separatorType == 'endB') { + d = -d; + } + const tolerance = SeparatorConsts.lineWidth; + const p1 = new Point(0, 0); + const p2 = new Point(-d, 0); + const p3 = new Point(-d, -d); + const p4 = new Point(-d * 3, -d); + const p5 = new Point(-d, d); + const p6 = new Point(-d * 3, d); + contains = contains || linePoint(p1, p2, p, tolerance); + contains = contains || linePoint(p2, p3, p, tolerance); + contains = contains || linePoint(p3, p4, p, tolerance); + contains = contains || linePoint(p2, p5, p, tolerance); + contains = contains || linePoint(p5, p6, p, tolerance); + } + return contains; + } +} + +export class SeparatorInteraction extends GraphicInteractionPlugin { + static Name = 'Separator_transform'; + constructor(app: JlDrawApp) { + super(SeparatorInteraction.Name, app); + } + static init(app: JlDrawApp) { + return new SeparatorInteraction(app); + } + filter(...grahpics: JlGraphic[]): Separator[] | undefined { + return grahpics + .filter((g) => g.type === Separator.Type) + .map((g) => g as Separator); + } + bind(g: Separator): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.scalable = true; + g.rotatable = true; + g.rectGraphic.hitArea = new SeparatorGraphicHitArea(g); + } + unbind(g: Separator): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + } +} diff --git a/src/graphics/signal/Lamp.ts b/src/graphics/signal/Lamp.ts new file mode 100644 index 0000000..fecb912 --- /dev/null +++ b/src/graphics/signal/Lamp.ts @@ -0,0 +1,73 @@ +import { Container } from '@pixi/display'; +import { Graphics } from 'pixi.js'; + +const lampConsts = { + lampRadius: 8, + logicModeLineWidth: 2, + logicModeDistance: 5, + logicModeColor: '0x000000', + lampLineWidth: 1, + lampLineColor: '0x3149c3', +}; + +export class Lamp extends Container { + circleLamp: Graphics = new Graphics(); + logicMode: Graphics = new Graphics(); + radiusX = 0; + radiusY = 0; + + constructor() { + super(); + this.addChild(this.circleLamp); + this.addChild(this.logicMode); + } + paint(radiusX: number, radiusY: number) { + this.radiusX = radiusX; + this.radiusY = radiusY; + this.createLamp(); + } + createLamp(color?: string) { + this.circleLamp.clear(); + this.circleLamp.lineStyle( + lampConsts.lampLineWidth, + lampConsts.lampLineColor + ); + if (!color) { + color = '0X' + this.getCanvas().backgroundColor.substring(1); + } + this.circleLamp.beginFill(color, 1); + this.circleLamp.drawCircle( + this.radiusX, + this.radiusY, + lampConsts.lampRadius + ); + this.circleLamp.endFill(); + } + createLogicMode() { + this.logicMode + .clear() + .lineStyle(lampConsts.logicModeLineWidth, lampConsts.logicModeColor) + .moveTo( + this.radiusX - lampConsts.logicModeDistance, + this.radiusY + lampConsts.logicModeDistance + ) + .lineTo( + this.radiusX + lampConsts.logicModeDistance, + this.radiusY - lampConsts.logicModeDistance + ) + .moveTo( + this.radiusX - lampConsts.logicModeDistance, + this.radiusY - lampConsts.logicModeDistance + ) + .lineTo( + this.radiusX + lampConsts.logicModeDistance, + this.radiusY + lampConsts.logicModeDistance + ); + } + logicModeClear() { + this.logicMode.clear(); + } + lampClear() { + this.circleLamp.clear(); + } +} diff --git a/src/graphics/signal/LampMainBody.ts b/src/graphics/signal/LampMainBody.ts new file mode 100644 index 0000000..b4c3b63 --- /dev/null +++ b/src/graphics/signal/LampMainBody.ts @@ -0,0 +1,204 @@ +import { Graphics, Point } from 'pixi.js'; +import { + calculateMirrorPoint, + GraphicAnimation, + JlGraphic, +} from 'src/jl-graphic'; +import { Lamp } from './Lamp'; +import { ISignalState } from './Signal'; + +export enum LampEnum { + lampPostColor = '0x3149c3', + redLamp = '0XFF0000', + greenLamp = '0X00FF00', + yellowLamp = '0XFFFF00', + whiteLamp = '0XFFFFFF', + blueLamp = '0X0033FF', +} + +const lampConsts = { + verticalLampPostLength: 16, + levelLampPostLength: 4, + postLineWidth: 3, + lampRadius: 8, +}; + +const anmiationNameConst = { + signaRedFlash: 'signal_red_flash', + signalGreenFlash: 'signal_green_flash', + signalYellowFlash: 'signal_yellow_flash', + signalWhiteFlash: 'signal_white_flash', + signalBlueFlash: 'signal_blue_flash', +}; + +export class LampMainBody extends JlGraphic { + static Type = 'LampMainBody'; + lampNum = 1; + lampPost: Graphics = new Graphics(); + lamps: Lamp[] = []; + redFlashAnimation: GraphicAnimation | null = null; + mirror = false; + deltaTime = 0; + states: ISignalState | null = null; + + constructor() { + super(LampMainBody.Type); + } + paint(lampNum: number, mirror: boolean, states: ISignalState) { + this.mirror = mirror; + this.states = states; + if (lampNum < 1) { + throw new Error('信号机灯数量异常'); + } + this.lampNum = lampNum; + this.removeChildren(0); + this.lampPost = new Graphics(); + let lpp = new Point(lampConsts.levelLampPostLength, 0); + if (mirror) { + lpp = calculateMirrorPoint(new Point(0, 0), lpp); + } + this.lampPost + .lineStyle(lampConsts.postLineWidth, LampEnum.lampPostColor) + .moveTo(0, -lampConsts.verticalLampPostLength / 2) + .lineTo(0, lampConsts.verticalLampPostLength / 2) + .moveTo(0, 0) + .lineTo(lpp.x, lpp.y); + this.addChild(this.lampPost); + + this.lamps = []; + for (let i = 0; i < this.lampNum; i++) { + const lamp = new Lamp(); + this.addChild(lamp); + const radiusX = + (1 + i * 2) * lampConsts.lampRadius + lampConsts.levelLampPostLength; + let lrp = new Point(radiusX, 0); + if (mirror) { + lrp = calculateMirrorPoint(new Point(0, 0), lrp); + } + lamp.paint(lrp.x, lrp.y); + this.lamps.push(lamp); + } + this.chagneState(this.states); + } + doRepaint() { + // this.paint(this.lampNum, this.mirror, this.states); + } + stopAnmiation() { + const redFlashA = this.animation(anmiationNameConst.signaRedFlash); + const greenFlashA = this.animation(anmiationNameConst.signalGreenFlash); + const blueFlashA = this.animation(anmiationNameConst.signalBlueFlash); + const yellowFlashA = this.animation(anmiationNameConst.signalYellowFlash); + const whiteFlashA = this.animation(anmiationNameConst.signalWhiteFlash); + if (redFlashA) { + redFlashA.pause(); + } + if (greenFlashA) { + greenFlashA.pause(); + } + if (blueFlashA) { + blueFlashA.pause(); + } + if (yellowFlashA) { + yellowFlashA.pause(); + } + if (whiteFlashA) { + whiteFlashA.pause(); + } + } + chagneState(states: ISignalState) { + this.stopAnmiation(); + if (states.extinguish) { + this.lamps.forEach((lamp) => lamp.createLogicMode()); + } else { + this.lamps.forEach((lamp) => lamp.logicModeClear()); + } + if (states.redOpen) { + this.lamps[0].createLamp(LampEnum.redLamp); + } else if (states.redFlash) { + let redFlashA = this.animation(anmiationNameConst.signaRedFlash); + if (!redFlashA) { + redFlashA = this.createFlashAnmiation( + anmiationNameConst.signaRedFlash, + LampEnum.redLamp, + 0 + ); + } + this.addAnimation(redFlashA); + redFlashA.resume(); + } else if (states.greenOpen) { + this.lamps.forEach((lamp) => lamp.createLamp(LampEnum.greenLamp)); + } else if (states.greenFlash) { + let greenFlashA = this.animation(anmiationNameConst.signalGreenFlash); + if (!greenFlashA) { + greenFlashA = this.createFlashAnmiation( + anmiationNameConst.signalGreenFlash, + LampEnum.greenLamp, + 1 + ); + } + this.addAnimation(greenFlashA); + greenFlashA.resume(); + } else if (states.yellowOpen) { + this.lamps.forEach((lamp) => lamp.createLamp(LampEnum.yellowLamp)); + } else if (states.yellowFlash) { + let yellowFlashA = this.animation(anmiationNameConst.signalYellowFlash); + if (!yellowFlashA) { + yellowFlashA = this.createFlashAnmiation( + anmiationNameConst.signalYellowFlash, + LampEnum.yellowLamp, + 1 + ); + } + this.addAnimation(yellowFlashA); + yellowFlashA.resume(); + } else if (states.blueOpen) { + this.lamps.forEach((lamp) => lamp.createLamp(LampEnum.blueLamp)); + } else if (states.blueFlash) { + let blueFlashA = this.animation(anmiationNameConst.signalBlueFlash); + if (!blueFlashA) { + blueFlashA = this.createFlashAnmiation( + anmiationNameConst.signalBlueFlash, + LampEnum.blueLamp, + 1 + ); + } + this.addAnimation(blueFlashA); + blueFlashA.resume(); + } else if (states.whiteOpen) { + this.lamps.forEach((lamp) => lamp.createLamp(LampEnum.whiteLamp)); + } else if (states.whiteFlash) { + let whiteFlashA = this.animation(anmiationNameConst.signalWhiteFlash); + if (!whiteFlashA) { + whiteFlashA = this.createFlashAnmiation( + anmiationNameConst.signalWhiteFlash, + LampEnum.whiteLamp, + 1 + ); + } + this.addAnimation(whiteFlashA); + whiteFlashA.resume(); + } + } + createFlashAnmiation( + name: string, + color: string, + lampIndex: number + ): GraphicAnimation { + const bgColor = '0X' + this.getCanvas().backgroundColor.substring(1); + const flashAnmiation = GraphicAnimation.init({ + name: name, + run: (dt: number) => { + this.deltaTime += dt; + if (this.deltaTime > 60) { + this.deltaTime = 0; + this.lamps[lampIndex].createLamp(color); + } else if (this.deltaTime > 30) { + this.lamps.forEach((lamp) => { + lamp.createLamp(bgColor); + }); + } + }, + }); + return flashAnmiation; + } +} diff --git a/src/graphics/signal/Signal.ts b/src/graphics/signal/Signal.ts new file mode 100644 index 0000000..4728e80 --- /dev/null +++ b/src/graphics/signal/Signal.ts @@ -0,0 +1,206 @@ +import { Graphics, Point } from 'pixi.js'; +import { + GraphicData, + GraphicState, + JlGraphic, + JlGraphicTemplate, +} from 'src/jl-graphic'; +import { calculateMirrorPoint } from 'src/jl-graphic'; +import { LampMainBody } from './LampMainBody'; +import { drawArrow } from '../CommonGraphics'; +import { SignalCode } from './SignalCode'; + +export interface KilometerSystem { + get coordinateSystem(): string; + set coordinateSystem(v: string); + get kilometer(): number; + set kilometer(v: number); +} + +export interface ISignalData extends GraphicData { + get code(): string; // 编号 + set code(v: string); + get mirror(): boolean; + set mirror(v: boolean); + get kilometerSystem(): KilometerSystem; + set kilometerSystem(v: KilometerSystem); + clone(): ISignalData; + copyFrom(data: ISignalData): void; + eq(other: ISignalData): boolean; +} + +export interface ISignalState extends GraphicState { + get redOpen(): boolean; + set redOpen(v: boolean); + get redFlash(): boolean; + set redFlash(v: boolean); + get greenOpen(): boolean; + set greenOpen(v: boolean); + get greenFlash(): boolean; + set greenFlash(v: boolean); + get yellowOpen(): boolean; + set yellowOpen(v: boolean); + get yellowFlash(): boolean; + set yellowFlash(v: boolean); + get whiteOpen(): boolean; + set whiteOpen(v: boolean); + get whiteFlash(): boolean; + set whiteFlash(v: boolean); + get blueOpen(): boolean; + set blueOpen(v: boolean); + get blueFlash(): boolean; + set blueFlash(v: boolean); + get fleetMode(): boolean; + set fleetMode(v: boolean); + get ctrlFleetMode(): boolean; + set ctrlFleetMode(v: boolean); + get autoMode(): boolean; + set autoMode(v: boolean); + get ctrlAutoMode(): boolean; + set ctrlAutoMode(v: boolean); + get extinguish(): boolean; + set extinguish(v: boolean); + get approachLock(): boolean; + set approachLock(v: boolean); + get protectRoute(): boolean; + set protectRoute(v: boolean); + get autoRouteDisable(): boolean; + set autoRouteDisable(v: boolean); + get callon(): boolean; + set callon(v: boolean); + get yellowYellow(): boolean; + set yellowYellow(v: boolean); + get yellowGreen(): boolean; + set yellowGreen(v: boolean); + get blocked(): boolean; + set blocked(v: boolean); + get lampFailure(): boolean; + set lampFailure(v: boolean); +} + +export enum SignalColorEnum { + humanControlColor = '0xffff00', + fleetModeColor = '0x00ff00', +} + +const signalConsts = { + lampNum: 2, + fleetModeLength: 24, + fleetModeRadius: 8, + fleetModeLineWidth: 6, + humanControlRadius: 8, + codeOffset: 20, +}; +export class Signal extends JlGraphic { + static Type = 'signal'; + signalCode: SignalCode = new SignalCode(); + humanControl: Graphics = new Graphics(); + fleetMode: Graphics = new Graphics(); + lampMainBody: LampMainBody = new LampMainBody(); + blockedMode: Graphics = new Graphics(); + + constructor() { + super(Signal.Type); + this.addChild(this.humanControl); + this.addChild(this.fleetMode); + this.addChild(this.lampMainBody); + this.addChild(this.signalCode); + } + + get datas(): ISignalData { + return this.getDatas(); + } + + get states(): ISignalState { + return this.getStates(); + } + + get mirror(): boolean { + return this.datas.mirror; + } + set mirror(v: boolean) { + const old = this.datas.clone(); + old.mirror = v; + this.updateData(old); + } + + paint(): void { + const mirror = this.datas.mirror; + this.lampMainBody.paint(signalConsts.lampNum, mirror, this.states); + this.signalCode.paint(this.datas, this.states); + const codeTransform = this.datas?.childTransforms?.find( + (item) => item.name === 'signalCode' + ); + if (codeTransform) { + const position = codeTransform?.transform.position; + const rotation = codeTransform?.transform?.rotation; + this.signalCode.position.set(position?.x, position?.y); + this.signalCode.rotation = rotation || 0; + } else { + this.signalCode.position.set(0, signalConsts.codeOffset); + } + } + + doRepaint(): void { + this.paint(); + this.fleetMode.clear(); + if (this.states.fleetMode) { + this.createFleetMode(); + } + this.humanControl.clear(); + if (this.states.autoRouteDisable) { + this.createHumanControl(); + } + } + createFleetMode(): void { + const mirror = this.datas.mirror; + this.fleetMode.beginFill(SignalColorEnum.fleetModeColor, 1); + let lmp = new Point( + this.lampMainBody.width + signalConsts.fleetModeLength, + 0 + ); + if (mirror) { + lmp = calculateMirrorPoint(new Point(0, 0), lmp); + } + drawArrow( + this.fleetMode, + lmp.x, + 0, + signalConsts.fleetModeLength, + signalConsts.fleetModeRadius, + signalConsts.fleetModeLineWidth, + mirror + ); + this.fleetMode.endFill(); + } + createHumanControl(): void { + const mirror = this.datas.mirror; + this.humanControl.beginFill(SignalColorEnum.humanControlColor, 1); + if (this.humanControl.drawRegularPolygon) { + let hmp = new Point(-signalConsts.humanControlRadius, 0); + if (mirror) { + hmp = calculateMirrorPoint(new Point(0, 0), hmp); + } + this.humanControl.drawRegularPolygon( + hmp.x, + hmp.y, + signalConsts.humanControlRadius, + 3, + (Math.PI / 2) * (mirror ? -1 : 1) + ); + } + this.humanControl.endFill(); + } +} + +export class SignalTemplate extends JlGraphicTemplate { + constructor(dataTemplate: ISignalData, stateTemplate: ISignalState) { + super(Signal.Type, { dataTemplate, stateTemplate }); + } + new(): Signal { + const g = new Signal(); + g.loadData(this.datas); + g.loadState(this.states); + return g; + } +} diff --git a/src/graphics/signal/SignalCode.ts b/src/graphics/signal/SignalCode.ts new file mode 100644 index 0000000..0b43a4d --- /dev/null +++ b/src/graphics/signal/SignalCode.ts @@ -0,0 +1,50 @@ +import { Container, Graphics, Point } from 'pixi.js'; +import { VectorText } from 'src/jl-graphic'; +import { ISignalData, ISignalState } from './Signal'; + +export enum CodeColorEnum { + defaultCodeColor = '0XFFFFFF', +} + +const signalCodeConsts = { + codeFontSize: 11, + blockedLineWidth: 1, + blockedColor: '0XFF0000', +}; + +export class SignalCode extends Container { + blockedMode: Graphics = new Graphics(); + codeGraph: VectorText = new VectorText(''); + name = 'signalCode'; + constructor() { + super(); + this.addChild(this.blockedMode); + this.addChild(this.codeGraph); + } + paint(datas: ISignalData, states: ISignalState) { + this.codeGraph.text = datas?.code || '信号机编号'; + this.codeGraph.style.fill = CodeColorEnum.defaultCodeColor; + this.codeGraph.setVectorFontSize(signalCodeConsts.codeFontSize); + this.codeGraph.anchor.set(0.5); + this.codeGraph.position.set(0, 0); + this.blockedMode.clear(); + if (states.blocked) { + this.createBlockedMode(); + } + } + createBlockedMode() { + const codeRect = this.codeGraph.getBounds(); + const rectP = this.screenToLocalPoint(new Point(codeRect.x, codeRect.y)); + this.blockedMode.clear(); + this.blockedMode.lineStyle( + signalCodeConsts.blockedLineWidth, + signalCodeConsts.blockedColor + ); + this.blockedMode.drawRect( + rectP.x, + rectP.y, + codeRect.width, + codeRect.height + ); + } +} diff --git a/src/graphics/signal/SignalDrawAssistant.ts b/src/graphics/signal/SignalDrawAssistant.ts new file mode 100644 index 0000000..2ca66e0 --- /dev/null +++ b/src/graphics/signal/SignalDrawAssistant.ts @@ -0,0 +1,167 @@ +import { DisplayObject, FederatedPointerEvent, Point } from 'pixi.js'; +import { + AbsorbableLine, + AbsorbablePosition, + GraphicDrawAssistant, + GraphicInteractionPlugin, + GraphicTransformEvent, + JlDrawApp, + JlGraphic, +} from 'src/jl-graphic'; + +import { ISignalData, Signal, SignalTemplate } from './Signal'; + +export interface ISignalDrawOptions { + newData: () => ISignalData; +} + +export class SignalDraw extends GraphicDrawAssistant< + SignalTemplate, + ISignalData +> { + _signal: Signal | null = null; + + constructor(app: JlDrawApp, template: SignalTemplate) { + super( + app, + template, + 'svguse: ../../drawIcon.svg#icon-signal', + '信号机Signal' + ); + + signalInteraction.init(app); + } + + public get signal(): Signal { + if (!this._signal) { + this._signal = this.graphicTemplate.new(); + this.signal.loadData(this.graphicTemplate.datas); + this.container.addChild(this.signal); + } + return this._signal; + } + + onRightClick(): void { + this.createAndStore(true); + } + onLeftUp(e: FederatedPointerEvent): void { + this.container.position.copyFrom(this.toCanvasCoordinates(e.global)); + this.createAndStore(true); + } + + redraw(p: Point): void { + this.signal.paint(); + this.container.position.set(p.x, p.y); + } + prepareData(data: ISignalData): boolean { + data.transform = this.container.saveTransform(); + return true; + } +} +/** + * 构建吸附线 + * @param signal + */ +function buildAbsorbablePositions(signal: Signal): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + const signals = signal.queryStore.queryByType(Signal.Type); + const canvas = signal.getCanvas(); + signals.forEach((item) => { + if (item.id === signal.id) { + return; + } + const ala = new AbsorbableLine( + new Point(item.x, 0), + new Point(item.x, canvas.height) + ); + const alb = new AbsorbableLine( + new Point(0, item.y), + new Point(canvas.width, item.y) + ); + aps.push(ala); + aps.push(alb); + }); + + return aps; +} +/** + * 信号机名称构建吸附线 + * @param signal + */ +function buildCodeAbsorbablePositions(signal: Signal): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + const signals = signal.queryStore.queryByType(Signal.Type); + const canvas = signal.getCanvas(); + signals.forEach((item) => { + if (item.id === signal.id) { + return; + } + const codePoint = item.signalCode.getPositionOnCanvas(); + const ala = new AbsorbableLine( + new Point(codePoint.x, 0), + new Point(codePoint.x, canvas.height) + ); + const alb = new AbsorbableLine( + new Point(0, codePoint.y), + new Point(canvas.width, codePoint.y) + ); + aps.push(ala); + aps.push(alb); + }); + return aps; +} + +export class signalInteraction extends GraphicInteractionPlugin { + static Name = 'signal_transform'; + constructor(app: JlDrawApp) { + super(signalInteraction.Name, app); + } + static init(app: JlDrawApp) { + return new signalInteraction(app); + } + filter(...grahpics: JlGraphic[]): Signal[] | undefined { + return grahpics + .filter((g) => g.type === Signal.Type) + .map((g) => g as Signal); + } + bind(g: Signal): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.scalable = true; + g.rotatable = true; + g.on('transformstart', this.transformstart, this); + g.signalCode.on('transformstart', this.codetransformstart, this); + g.signalCode.draggable = true; + g.signalCode.selectable = true; + g.signalCode.rotatable = true; + g.signalCode.transformSave = true; + g.signalCode.eventMode = 'static'; + } + + unbind(g: Signal): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + g.off('transformstart', this.transformstart, this); + g.signalCode.off('transformstart', this.codetransformstart, this); + g.signalCode.draggable = false; + g.signalCode.selectable = false; + g.signalCode.rotatable = false; + g.signalCode.transformSave = false; + g.signalCode.eventMode = 'none'; + } + transformstart(e: GraphicTransformEvent) { + const target = e.target as DisplayObject; + const signal = target.getGraphic() as Signal; + signal.getGraphicApp().setOptions({ + absorbablePositions: buildAbsorbablePositions(signal), + }); + } + codetransformstart(e: GraphicTransformEvent) { + const target = e.target as DisplayObject; + const signal = target.getGraphic() as Signal; + signal.getGraphicApp().setOptions({ + absorbablePositions: buildCodeAbsorbablePositions(signal), + }); + } +} diff --git a/src/graphics/station/Station.ts b/src/graphics/station/Station.ts new file mode 100644 index 0000000..1956a58 --- /dev/null +++ b/src/graphics/station/Station.ts @@ -0,0 +1,224 @@ +import { Color, Container, Graphics } from 'pixi.js'; +import { + GraphicData, + GraphicState, + JlGraphic, + JlGraphicTemplate, + VectorText, +} from 'src/jl-graphic'; +import { KilometerSystem } from '../signal/Signal'; + +export interface IStationData extends GraphicData { + get code(): string; // 编号 + set code(v: string); + get kilometerSystem(): KilometerSystem; + set kilometerSystem(v: KilometerSystem); + get hasControl(): boolean; /// 是否有控制 + set hasControl(v: boolean); + get concentrationStations(): boolean; ////是否集中站 + set concentrationStations(v: boolean); + clone(): IStationData; + copyFrom(data: IStationData): void; + eq(other: IStationData): boolean; +} + +export interface IStationState extends GraphicState { + get ipRtuStusDown(): boolean; + set ipRtuStusDown(v: boolean); + get ipRtuStusInLocalCtrl(): boolean; + set ipRtuStusInLocalCtrl(v: boolean); + get ipRtuStusInCentralCtrl(): boolean; + set ipRtuStusInCentralCtrl(v: boolean); + get ipRtuStusInEmergencyCtrl(): boolean; + set ipRtuStusInEmergencyCtrl(v: boolean); +} + +const stationConsts = { + radius: 3, + borderWidth: 1, + circleColorGrey: '0x808080', + circleColorBlue: '0x08F80D', + circleColorYellow: '0xFFFA0C', + codeColor: '0xF48815', + codeFontSize: 22, + codeControlFontSize: 12, + codeOffsetY: 30, + circleOffsetY: 20, + circleBetweenOffset: 40, + kilometerCodeColor: '0xFFFFFF', + kilometerCodeFontSize: 8, + kilometerCodeOffsetY: -25, +}; +class constrolGraphic extends Container { + circleA: Graphics = new Graphics(); + codeGraphA: VectorText = new VectorText(''); //控制名--站控 + circleB: Graphics = new Graphics(); + codeGraphB: VectorText = new VectorText(''); //控制名--中控 + arrow: Graphics = new Graphics(); + inArrow: Graphics = new Graphics(); + constructor() { + super(); + this.addChild(this.circleA); + this.addChild(this.codeGraphA); + this.addChild(this.circleB); + this.addChild(this.codeGraphB); + this.addChild(this.arrow); + this.addChild(this.inArrow); + this.codeGraphA.setVectorFontSize(stationConsts.codeFontSize); + this.codeGraphB.setVectorFontSize(stationConsts.codeFontSize); + } + draw(states: IStationState): void { + let StationControlFillColor = stationConsts.circleColorGrey; + let centralControlFillColor = stationConsts.circleColorBlue; + let inArrowFillColor = stationConsts.circleColorGrey; + if (states.ipRtuStusInLocalCtrl) { + StationControlFillColor = stationConsts.circleColorYellow; + centralControlFillColor = stationConsts.circleColorGrey; + if (!states.ipRtuStusDown) { + inArrowFillColor = stationConsts.circleColorBlue; + } + } + this.drawCircleCode( + this.circleA, + this.codeGraphA, + '站控', + StationControlFillColor + ); + this.circleA.position.set( + stationConsts.circleBetweenOffset / 2, + stationConsts.circleOffsetY + ); + this.codeGraphA.position.set( + stationConsts.circleBetweenOffset / 2, + stationConsts.codeOffsetY + ); + this.drawCircleCode( + this.circleB, + this.codeGraphB, + '中控', + centralControlFillColor + ); + this.circleB.position.set( + -stationConsts.circleBetweenOffset / 2, + stationConsts.circleOffsetY + ); + this.codeGraphB.position.set( + -stationConsts.circleBetweenOffset / 2, + stationConsts.codeOffsetY + ); + const arrow = this.arrow; + arrow.clear(); + arrow.lineStyle(stationConsts.borderWidth, new Color('0xFFFFFF')); + const points = [0, 0, 2, 2, 2, 1, 14, 1, 14, -1, 2, -1, 2, -2]; + arrow.beginFill('0xFFFFFF'); + arrow.drawPolygon(points); + arrow.endFill(); + arrow.scale.set(1.1, 1.1); + arrow.position.set(-7, stationConsts.circleOffsetY); + const inArrow = this.inArrow; + inArrow.beginFill(inArrowFillColor); + inArrow.drawPolygon(points); + inArrow.endFill(); + inArrow.position.set(-6.5, stationConsts.circleOffsetY); + } + drawCircleCode( + circle: Graphics, + codeGraph: VectorText, + code: string, + fillcolor: string + ): void { + circle.clear(); + circle.lineStyle(stationConsts.borderWidth, new Color(fillcolor)); + circle.beginFill(fillcolor, 1); + circle.drawCircle(0, 0, stationConsts.radius); + circle.endFill; + codeGraph.text = code; + codeGraph.style.fill = fillcolor; + codeGraph.setVectorFontSize(stationConsts.codeControlFontSize); + codeGraph.anchor.set(0.5); + } + clear(): void { + this.circleA.clear(); + this.circleB.clear(); + this.codeGraphA.text = ''; + this.codeGraphB.text = ''; + this.arrow.clear(); + this.inArrow.clear(); + } +} +export class Station extends JlGraphic { + static Type = 'station'; + codeGraph: VectorText = new VectorText(''); //车站名 + kilometerGraph: VectorText = new VectorText(''); //公里标 + controlGraphic: constrolGraphic = new constrolGraphic(); + constructor() { + super(Station.Type); + this.addChild(this.codeGraph); + this.addChild(this.kilometerGraph); + this.addChild(this.controlGraphic); + this.kilometerGraph.name = 'kilometer'; + this.controlGraphic.name = 'trainControl'; + } + + get datas(): IStationData { + return this.getDatas(); + } + get states(): IStationState { + return this.getStates(); + } + doRepaint(): void { + const codeGraph = this.codeGraph; + const kilometerGraph = this.kilometerGraph; + const controlGraphic = this.controlGraphic; + controlGraphic.clear(); + codeGraph.text = this.datas?.code || '车站Station'; + codeGraph.style.fill = stationConsts.codeColor; + codeGraph.setVectorFontSize(stationConsts.codeFontSize); + codeGraph.anchor.set(0.5); + const kilometerCode = this.datas.kilometerSystem?.kilometer || 12345678; + if (Math.floor(kilometerCode * 1000).toString().length > 3) { + const kiloBit = Math.floor(Number(kilometerCode) / 1000000).toString(); + kilometerGraph.text = + 'K' + + kiloBit + + '+' + + ( + Number(kilometerCode.toString().substring(kiloBit.length)) / 1000 + ).toFixed(3); + } else { + kilometerGraph.text = (kilometerCode * 1000).toFixed(3); + } + kilometerGraph.style.fill = stationConsts.kilometerCodeColor; + kilometerGraph.setVectorFontSize(stationConsts.kilometerCodeFontSize); + kilometerGraph.anchor.set(0.5); + kilometerGraph.position.set(0, stationConsts.kilometerCodeOffsetY); + if (this.datas.childTransforms?.length) { + this.datas.childTransforms.forEach((child) => { + if (child.name == 'kilometer') { + const pos = child.transform.position; + kilometerGraph.position.set(pos.x, pos.y); + } + }); + } + if (this.datas.hasControl) { + controlGraphic.draw(this.states); + } + } +} + +export class StationTemplate extends JlGraphicTemplate { + hasControl: boolean; + constructor(dataTemplate: IStationData, stateTemplate: IStationState) { + super(Station.Type, { + dataTemplate, + stateTemplate, + }); + this.hasControl = true; + } + new(): Station { + const station = new Station(); + station.loadData(this.datas); + station.loadState(this.states); + return station; + } +} diff --git a/src/graphics/station/StationDrawAssistant.ts b/src/graphics/station/StationDrawAssistant.ts new file mode 100644 index 0000000..15266cf --- /dev/null +++ b/src/graphics/station/StationDrawAssistant.ts @@ -0,0 +1,123 @@ +import { FederatedPointerEvent, Point } from 'pixi.js'; +import { + AbsorbableLine, + AbsorbablePosition, + GraphicDrawAssistant, + GraphicInteractionPlugin, + JlDrawApp, + JlGraphic, +} from 'src/jl-graphic'; + +import { IStationData, Station, StationTemplate } from './Station'; + +export interface IStationDrawOptions { + newData: () => IStationData; +} + +export class StationDraw extends GraphicDrawAssistant< + StationTemplate, + IStationData +> { + codeGraph: Station; + constructor(app: JlDrawApp, template: StationTemplate) { + super( + app, + template, + 'svguse:../../drawIcon.svg#icon-station', + '车站Station' + ); + this.codeGraph = this.graphicTemplate.new(); + this.container.addChild(this.codeGraph); + stationInteraction.init(app); + } + + bind(): void { + super.bind(); + this.codeGraph.loadData(this.graphicTemplate.datas); + this.codeGraph.doRepaint(); + } + + clearCache(): void { + //this.codeGraph.destroy(); + } + onLeftDown(e: FederatedPointerEvent): void { + this.container.position.copyFrom(this.toCanvasCoordinates(e.global)); + this.createAndStore(true); + } + + redraw(p: Point): void { + this.container.position.copyFrom(p); + } + prepareData(data: IStationData): boolean { + data.transform = this.container.saveTransform(); + data.hasControl = this.graphicTemplate.hasControl; + return true; + } +} + +function buildAbsorbablePositions(station: Station): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + const stations = station.queryStore.queryByType(Station.Type); + const { width } = station.getGraphicApp().canvas; + stations.forEach((other) => { + if (other.id == station.id) { + return; + } + const ps = other.datas.transform.position; + const xs = new AbsorbableLine({ x: 0, y: ps.y }, { x: width, y: ps.y }); + aps.push(xs); + }); + return aps; +} + +export class stationInteraction extends GraphicInteractionPlugin { + static Name = 'station_transform'; + constructor(app: JlDrawApp) { + super(stationInteraction.Name, app); + } + static init(app: JlDrawApp) { + return new stationInteraction(app); + } + filter(...grahpics: JlGraphic[]): Station[] | undefined { + return grahpics + .filter((g) => g.type === Station.Type) + .map((g) => g as Station); + } + bind(g: Station): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.scalable = true; + g.rotatable = true; + g.controlGraphic.eventMode = 'static'; + g.controlGraphic.cursor = 'pointer'; + g.controlGraphic.draggable = true; + g.controlGraphic.selectable = true; + g.controlGraphic.transformSave = true; + g.kilometerGraph.eventMode = 'static'; + g.kilometerGraph.cursor = 'pointer'; + g.kilometerGraph.draggable = true; + g.kilometerGraph.selectable = true; + g.kilometerGraph.transformSave = true; + g.on('selected', this.onSelected, this); + } + unbind(g: Station): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + g.controlGraphic.eventMode = 'none'; + g.controlGraphic.draggable = false; + g.controlGraphic.selectable = false; + g.controlGraphic.transformSave = false; + g.kilometerGraph.eventMode = 'none'; + g.kilometerGraph.draggable = false; + g.kilometerGraph.selectable = false; + g.kilometerGraph.transformSave = false; + g.off('selected', this.onSelected, this); + } + onSelected(): void { + const station = this.app.selectedGraphics[0] as Station; + this.app.setOptions({ + absorbablePositions: buildAbsorbablePositions(station), + }); + } +} diff --git a/src/graphics/stationLine/StationLine.ts b/src/graphics/stationLine/StationLine.ts new file mode 100644 index 0000000..3cf0fbc --- /dev/null +++ b/src/graphics/stationLine/StationLine.ts @@ -0,0 +1,144 @@ +import { Color, Container, Graphics, Point } from 'pixi.js'; +import { + GraphicData, + JlGraphic, + JlGraphicTemplate, + VectorText, +} from 'src/jl-graphic'; + +export interface IStationLineData extends GraphicData { + get code(): string; // 编号 + set code(v: string); + get hasTransfer(): boolean; + set hasTransfer(v: boolean); + get hideName(): boolean; + set hideName(v: boolean); + + clone(): IStationLineData; + copyFrom(data: IStationLineData): void; + eq(other: IStationLineData): boolean; +} + +const stationConsts = { + radius: 5, + borderWidth: 1, + borderColor: '0xffffff', + fillColor: '0xffffff', + transferRadius: 3.5, + transferWidth: 0.4, + transferColor: '0xff0000', + codeColor: '0xF48815', + codeFontSize: 8, + codeOffsetY: 20, +}; +//子元素--圆点 +class circleGraphic extends Container { + circle: Graphics = new Graphics(); + arcUp: Graphics = new Graphics(); + arcDown: Graphics = new Graphics(); + arrowUp: Graphics = new Graphics(); + arrowDown: Graphics = new Graphics(); + constructor() { + super(); + this.addChild(this.circle); + this.addChild(this.arcUp); + this.addChild(this.arcDown); + this.addChild(this.arrowUp); + this.addChild(this.arrowDown); + } + draw(datas: IStationLineData): void { + const circle = this.circle; + circle.clear(); + circle.lineStyle( + stationConsts.borderWidth, + new Color(stationConsts.borderColor) + ); + circle.beginFill(stationConsts.fillColor, 1); + circle.drawCircle(0, 0, stationConsts.radius); + circle.endFill; + const arcGraphicUp = this.arcUp; + const arcGraphicDown = this.arcDown; + const arrowUpGraphic = this.arrowUp; + const arrowDownGraphic = this.arrowDown; + arcGraphicUp.clear(); + arcGraphicDown.clear(); + arrowUpGraphic.clear(); + arrowDownGraphic.clear(); + if (datas.hasTransfer) { + this.drawTransfer(arcGraphicUp, arrowUpGraphic); + this.drawTransfer(arcGraphicDown, arrowDownGraphic); + arcGraphicDown.rotation = Math.PI; + arrowDownGraphic.rotation = (Math.PI * 24) / 25; + arrowDownGraphic.position.set(stationConsts.transferRadius, 0); + } + } + drawTransfer(transferGraphic: Graphics, arrowGraphic: Graphics): void { + transferGraphic.lineStyle( + stationConsts.transferWidth, + new Color(stationConsts.transferColor) + ); + transferGraphic.arc( + 0, + 0, + stationConsts.transferRadius, + Math.PI / 10, + Math.PI, + false + ); + arrowGraphic.lineStyle( + stationConsts.transferWidth, + new Color(stationConsts.transferColor) + ); + arrowGraphic.moveTo(0, 0); + arrowGraphic.lineTo(1, 1); + arrowGraphic.moveTo(0, 0); + arrowGraphic.lineTo(-1, 1); + arrowGraphic.position.set(-stationConsts.transferRadius, 0); + arrowGraphic.pivot = new Point(0, 0); + arrowGraphic.rotation = -(Math.PI * 1) / 25; + } +} +export class StationLine extends JlGraphic { + static Type = 'stationLine'; + circleGraphic: circleGraphic = new circleGraphic(); + codeGraph: VectorText = new VectorText(''); //车站名 + + constructor() { + super(StationLine.Type); + this.addChild(this.codeGraph); + this.addChild(this.circleGraphic); + this.codeGraph.name = 'trainLineCode'; + } + + get datas(): IStationLineData { + return this.getDatas(); + } + doRepaint(): void { + this.circleGraphic.draw(this.datas); + const codeGraph = this.codeGraph; + codeGraph.text = this.datas?.code || '车站StationLine'; + codeGraph.style.fill = stationConsts.codeColor; + codeGraph.setVectorFontSize(stationConsts.codeFontSize); + codeGraph.anchor.set(0.5); + codeGraph.visible = !this.datas.hideName; + if (this.datas.childTransforms?.length) { + const pos = this.datas.childTransforms[0].transform.position; + codeGraph.position.set(pos.x, pos.y); + } else { + codeGraph.position.set(0, stationConsts.codeOffsetY); + } + } +} + +export class StationLineTemplate extends JlGraphicTemplate { + hasTransfer: boolean; + constructor(dataTemplate: IStationLineData) { + super(StationLine.Type, { + dataTemplate, + }); + this.hasTransfer = true; + } + new(): StationLine { + return new StationLine(); + } +} diff --git a/src/graphics/stationLine/StationLineDrawAssistant.ts b/src/graphics/stationLine/StationLineDrawAssistant.ts new file mode 100644 index 0000000..3866272 --- /dev/null +++ b/src/graphics/stationLine/StationLineDrawAssistant.ts @@ -0,0 +1,124 @@ +import { FederatedPointerEvent, Point } from 'pixi.js'; +import { + AbsorbableLine, + AbsorbablePosition, + GraphicDrawAssistant, + GraphicInteractionPlugin, + JlDrawApp, + JlGraphic, +} from 'src/jl-graphic'; + +import { + IStationLineData, + StationLine, + StationLineTemplate, +} from './StationLine'; +import { RunLine } from '../runLine/RunLine'; + +export interface IStationLineDrawOptions { + newData: () => IStationLineData; +} + +export class StationLineDraw extends GraphicDrawAssistant< + StationLineTemplate, + IStationLineData +> { + codeGraph: StationLine; + constructor(app: JlDrawApp, template: StationLineTemplate) { + super( + app, + template, + 'svguse:../../drawIcon.svg#icon-station', + '车站StationLine' + ); + this.codeGraph = this.graphicTemplate.new(); + this.container.addChild(this.codeGraph); + stationLineInteraction.init(app); + } + + bind(): void { + super.bind(); + this.codeGraph.loadData(this.graphicTemplate.datas); + this.codeGraph.doRepaint(); + } + + clearCache(): void { + //this.codeGraph.destroy(); + } + onLeftDown(e: FederatedPointerEvent): void { + this.container.position.copyFrom(this.toCanvasCoordinates(e.global)); + this.createAndStore(true); + } + + redraw(p: Point): void { + this.container.position.copyFrom(p); + } + prepareData(data: IStationLineData): boolean { + const template = this.graphicTemplate; + data.transform = this.container.saveTransform(); + data.hasTransfer = template.hasTransfer; + return true; + } +} + +/** + * 构建吸附位置 + * @param polygon + * @returns + */ +function buildAbsorbablePositions(Station: StationLine): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + const runLines = Station.queryStore.queryByType(RunLine.Type); + runLines.forEach((runLine) => { + const points = runLine.datas.points; + for (let i = 0; i < points.length - 1; i++) { + aps.push(new AbsorbableLine(points[i], points[i + 1])); + } + }); + return aps; +} + +export class stationLineInteraction extends GraphicInteractionPlugin { + static Name = 'stationLine_transform'; + static stationLine: StationLine; + constructor(app: JlDrawApp) { + super(stationLineInteraction.Name, app); + } + static init(app: JlDrawApp) { + return new stationLineInteraction(app); + } + filter(...grahpics: JlGraphic[]): StationLine[] | undefined { + return grahpics + .filter((g) => g.type === StationLine.Type) + .map((g) => g as StationLine); + } + bind(g: StationLine): void { + stationLineInteraction.stationLine = g; + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.scalable = true; + g.rotatable = true; + g.codeGraph.eventMode = 'static'; + g.codeGraph.cursor = 'pointer'; + g.codeGraph.draggable = true; + g.codeGraph.selectable = true; + g.codeGraph.transformSave = true; + g.on('selected', this.onSelected, this); + } + unbind(g: StationLine): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + g.codeGraph.eventMode = 'none'; + g.codeGraph.draggable = false; + g.codeGraph.selectable = false; + g.codeGraph.transformSave = false; + } + onSelected(): void { + this.app.setOptions({ + absorbablePositions: buildAbsorbablePositions( + stationLineInteraction.stationLine + ), + }); + } +} diff --git a/src/graphics/train/Train.ts b/src/graphics/train/Train.ts new file mode 100644 index 0000000..7e20031 --- /dev/null +++ b/src/graphics/train/Train.ts @@ -0,0 +1,401 @@ +import { Color, Graphics, Container, Point } from 'pixi.js'; +import { + GraphicData, + GraphicState, + JlGraphic, + JlGraphicTemplate, + VectorText, + calculateMirrorPoint, +} from 'src/jl-graphic'; +import { train } from 'src/protos/train'; +import { state } from 'src/protos/device_status'; + +export interface ITrainData extends GraphicData { + get code(): string; // 车号 + set code(v: string); + clone(): ITrainData; + copyFrom(data: ITrainData): void; + eq(other: ITrainData): boolean; +} + +export interface ITrainState extends GraphicState { + get lineId(): number; // 线路id + set lineId(v: number); + get rtuId(): number; // 集中站站号 + set rtuId(v: number); + get window(): train.NccWindow; // NccWindow + set window(v: train.NccWindow); + get devType(): state.DeviceType; // 所在设备类型 + set devType(v: state.DeviceType); + get devName(): string; // 所在设备名称 + set devName(v: string); + get id(): string; // 设备唯一 + set id(v: string); + get groupId(): string; // 列车车组号 + set groupId(v: string); + get trainId(): string; // 列车表号 + set trainId(v: string); + get globalId(): string; // 列车车次号 + set globalId(v: string); + get destinationId(): number; // 目的地ID + set destinationId(v: number); + get rollingStock(): number; // 编组数量 + set rollingStock(v: number); + get driverId(): string; // 司机号 + set driverId(v: string); + get otpTime(): number; // 计划偏离时间 + set otpTime(v: number); + get mode(): state.TrainMode; // 列车状态 + set mode(v: state.TrainMode); + get arriveTime(): number; // 到点 + set arriveTime(v: number); + get departTime(): number; // 发点 + set departTime(v: number); + get speed(): number; // 速度 + set speed(v: number); + get show(): boolean; // 是否显示 + set show(v: boolean); + get type(): boolean; // 车次号变化状态 + set type(v: boolean); + get routeId(): number; // 运行路径号 + set routeId(v: number); + get rate(): number; // 满载率 + set rate(v: number); +} + +interface bodyWH { + width: number; // 宽 + height: number; // 高 +} + +// 列车颜色 +export enum TrainColorEnum { + headColor = '0xFFCE4D', // 箭头颜色 + bodyColor = '0xA388B1', // 背景色 + codeColor = '0xffffff', // 车号颜色 + borderColor = '0xA3E198', // 边框的颜色 + directionColor = '0x00FF00', // 方向箭头颜色 +} + +enum diriveModelColorEnum { // 驾驶模式对应颜色 + AM = '0x00FF00', // ATO自动驾驶 + SM = '0xFFFF00', // ATP 监控下的人工驾驶模式 + RM = '0xFFC837', // 限制人工驾驶模式 + NRM = '0xA0522D', // 非限制人工驾驶模式 + red = '0xF80103', // 红色表示通信中断 +} +enum AAColorEnum { // 识别号AA颜色 + accuracy = '0xffffff', // 准点 + early = '0x00FF00', // 早点 + late = '0xA0522D', // 晚点 +} +enum typeColorEnum { // 识别号BBB颜色 + schedule = '0xffffff', // 计划车 + head = '0xE9FC01', // 头码车 + manual = '0xE9FC01', // 人工车 + special = '0xE9FC01', // 特殊车 +} + +enum statusTextColor { + H = '0xFFFF00', // H扣车 + S = '0x6260F3', // S跳停 + D = '0x00FF00', // D开门 + A = '0xFF0000', // A报警 +} + +export const trainConsts = { + codeWidth: 120, + codeHeight: 40, + codePadding: 5, + borderWidth: 1, + codeFontSize: 22, + textFontSize: 16, // 状态字母大小 + textMarginY: 10, // 状态字母与列车距离 + statusTextList: ['H', 'S', 'D', 'A'], + marginX: 2, // 图形x轴边距 + pauseW: 2, // 停止框宽度 +}; + +export class TrainHead extends Container { + arrow: Graphics; // 箭头 + pause: Graphics; // 停止 + constructor() { + super(); + this.arrow = new Graphics(); + this.pause = new Graphics(); + this.addChild(this.arrow); + this.addChild(this.pause); + } + clear() { + this.arrow.clear(); + this.pause.clear(); + } + doRepaint(states: ITrainState, bodyWH?: bodyWH) { + let direction = ''; + if (states.mode?.ipModeTrainDirUp) { + direction = 'left'; + } + if (states.mode?.ipModeTrainDirDown) { + direction = 'right'; + } + this.clear(); + if (!direction) { + return; + } + const marginX = trainConsts.marginX; + const pauseW = trainConsts.pauseW; + const codeWidth = bodyWH ? bodyWH.width : trainConsts.codeWidth; + const codeHeight = bodyWH ? bodyWH.height : trainConsts.codeHeight; + let arrowPoint = [ + -codeHeight * 0.4 - marginX - pauseW - marginX - codeWidth / 2, + 0, + -marginX - pauseW - marginX - codeWidth / 2, + codeHeight / 2, + -marginX - pauseW - marginX - codeWidth / 2, + -codeHeight / 2, + ]; + let pausePoint = [ + -marginX - pauseW / 2 - codeWidth / 2, + -codeHeight / 2, + -marginX - pauseW / 2 - codeWidth / 2, + codeHeight / 2, + ]; + if (direction != 'left') { + const aP: Array = []; + arrowPoint.forEach((item, index) => { + if (index % 2 == 1) { + const p = new Point(arrowPoint[index - 1], item); + const newP = calculateMirrorPoint(new Point(0, 0), p); + aP.push(newP.x, newP.y); + } + }); + arrowPoint = aP; + const pP: Array = []; + pausePoint.forEach((item, index) => { + if (index % 2 == 1) { + const p = new Point(pausePoint[index - 1], item); + const newP = calculateMirrorPoint(new Point(0, 0), p); + pP.push(newP.x, newP.y); + } + }); + pausePoint = pP; + } + const arrow = this.arrow; + arrow.beginFill(TrainColorEnum.headColor, 1); + arrow.drawPolygon(arrowPoint); + arrow.endFill(); + this.pause.lineStyle(pauseW, TrainColorEnum.headColor, 1); + this.pause.moveTo(pausePoint[0], pausePoint[1]); + this.pause.lineTo(pausePoint[2], pausePoint[3]); + } + stop() { + this.pause.visible = true; + this.arrow.visible = false; + } + run() { + this.pause.visible = false; + this.arrow.visible = true; + } +} + +export class TrainBody extends Container { + codeRact: Graphics; + codeAGraph: VectorText = new VectorText(''); //识别号AA + codeBGraph: VectorText = new VectorText(''); //识别号BBB + constructor() { + super(); + this.codeRact = new Graphics(); + this.addChild(this.codeRact); + this.addChild(this.codeAGraph); + this.addChild(this.codeBGraph); + this.codeAGraph.setVectorFontSize(trainConsts.codeFontSize); + this.codeBGraph.setVectorFontSize(trainConsts.codeFontSize); + } + clear() { + this.codeRact.clear(); + } + getBodyWH(): bodyWH { + const bodyAWH = this.codeAGraph.getLocalBounds(); + const bodyBWH = this.codeBGraph.getLocalBounds(); + return { + width: bodyAWH.width + bodyBWH.width + trainConsts.codePadding * 2, + height: bodyAWH.height + trainConsts.codePadding * 2, + }; + } + + doRepaint(states: ITrainState): void { + this.clear(); + const codeAGraph = this.codeAGraph; + const codeBGraph = this.codeBGraph; + const codeRact = this.codeRact; + let codeA = states?.trainId; + let fillAColor = AAColorEnum.accuracy; + if (states.mode?.ipModeTrainTypeSchedule) { + if (states?.otpTime > 0) { + fillAColor = AAColorEnum.late; + } else if (states?.otpTime < 0) { + fillAColor = AAColorEnum.early; + } + } + let fillBColor = typeColorEnum.schedule; + if (states.mode?.ipModeTrainTypeHead) { + codeA = states?.destinationId + ''; + fillBColor = typeColorEnum.head; + } else if (states.mode?.ipModeTrainTypeManual) { + codeA = 'MM'; + fillBColor = typeColorEnum.manual; + } else if (states.mode?.ipModeTrainTypeSpecial) { + codeA = ''; + } + const codeB = states?.globalId; + codeAGraph.text = codeA || '01'; + codeBGraph.text = codeB || '2222'; + codeAGraph.anchor.set(0.5); + codeBGraph.anchor.set(0.5); + const styleA = { + fill: fillAColor, + fontSize: trainConsts.codeFontSize, + }; + const styleB = { + fill: fillBColor, + fontSize: trainConsts.codeFontSize, + }; + codeAGraph.style = styleA; + codeBGraph.style = styleB; + const bodyAWH = codeAGraph.getLocalBounds(); + const bodyBWH = codeBGraph.getLocalBounds(); + codeAGraph.position.set(-bodyBWH.width / 2, 0); + codeBGraph.position.set(bodyAWH.width / 2, 0); + codeAGraph.updateOnScaled(); + codeBGraph.updateOnScaled(); + const { width: codeWidth, height: codeHeight } = this.getBodyWH(); + codeRact.lineStyle( + trainConsts.borderWidth, + new Color(TrainColorEnum.borderColor) + ); + codeRact.beginFill(new Color(TrainColorEnum.bodyColor)); + codeRact.drawRect(-codeWidth / 2, -codeHeight / 2, codeWidth, codeHeight); + codeRact.endFill(); + } +} + +class StatusText extends Container { + sText: VectorText = new VectorText(''); + constructor() { + super(); + this.addChild(this.sText); + } + doRepaint(text: string, bodyWH: bodyWH): void { + this.sText.text = text; + this.sText.anchor.set(0.5); + const c = (statusTextColor as never)[text] || statusTextColor.D; + const style = { + fill: c, + fontSize: trainConsts.textFontSize, + }; + this.sText.style = style; + const { width: codeWidth, height: codeHeight } = bodyWH; + const { width: textHWidth, height: textHeight } = + this.sText.getLocalBounds(); + const num = trainConsts.statusTextList.length; + let index = trainConsts.statusTextList.findIndex((item) => { + return item == text; + }); + if (index < 0) { + index = 1.5; // 中间 + } + const textMargin = (codeWidth - textHWidth * num) / (num - 1); + this.sText.position.set( + -codeWidth / 2 + (textHWidth * (index * 2 + 1)) / 2 + textMargin * index, + -codeHeight / 2 - textHeight / 2 - trainConsts.textMarginY + ); + } + clear(): void { + this.sText.text = ''; + } +} + +export class Train extends JlGraphic { + static Type = 'Train'; + + trainHead: TrainHead; + trainbody: TrainBody; + statusTextMap: Map = new Map(); + constructor() { + super(Train.Type); + this.trainbody = new TrainBody(); + this.trainHead = new TrainHead(); + this.addChild(this.trainHead); + this.addChild(this.trainbody); + } + + get datas(): ITrainData { + return this.getDatas(); + } + + get states(): ITrainState { + return this.getStates(); + } + + doRepaint(): void { + this.trainbody.doRepaint(this.states); + const bodyWH = this.trainbody.getBodyWH(); + this.trainHead.doRepaint(this.states, bodyWH); + } + + stop() { + this.trainHead.stop(); + } + run() { + this.trainHead.run(); + } + + showStatus(s: string) { + if (this.statusTextMap.has(s)) { + return; + } + const bodyWH = this.trainbody.getBodyWH(); + const textD = new StatusText(); + textD.doRepaint(s, bodyWH); + this.addChild(textD); + this.statusTextMap.set(s, textD); + } + hideStatus(s: string) { + if (!this.statusTextMap.has(s)) { + return; + } + const textD = this.statusTextMap.get(s); + if (textD) { + textD.clear(); + this.statusTextMap.delete(s); + } + } + chagneDirection(): void { + const bodyWH = this.trainbody.getBodyWH(); + this.trainHead.doRepaint(this.states, bodyWH); + } + chagneState(): void { + if (this.states.mode?.ipModeTrainHolded) { + this.showStatus('H'); + } else { + this.hideStatus('H'); + } + if (this.states.mode?.ipModeTrainDoorOpen) { + this.showStatus('D'); + } else { + this.hideStatus('D'); + } + } +} + +export class TrainTemplate extends JlGraphicTemplate { + constructor(dataTemplate: ITrainData, stateTemplate: ITrainState) { + super(Train.Type, { dataTemplate, stateTemplate }); + } + new(): Train { + const train = new Train(); + train.loadData(this.datas); + train.loadState(this.states); + return train; + } +} diff --git a/src/graphics/train/TrainDrawAssistant.ts b/src/graphics/train/TrainDrawAssistant.ts new file mode 100644 index 0000000..65577e0 --- /dev/null +++ b/src/graphics/train/TrainDrawAssistant.ts @@ -0,0 +1,71 @@ +import { Point, FederatedPointerEvent } from 'pixi.js'; +import { + GraphicDrawAssistant, + GraphicInteractionPlugin, + JlDrawApp, + JlGraphic, +} from 'src/jl-graphic'; + +import { ITrainData, Train, TrainTemplate } from './Train'; + +export interface ITrainDrawOptions { + newData: () => ITrainData; +} + +export class TrainDraw extends GraphicDrawAssistant { + _Train: Train | null = null; + + constructor(app: JlDrawApp, template: TrainTemplate) { + super(app, template, 'directions_bus_filled', '不展示'); + trainInteraction.init(app); + } + + public get Train(): Train { + if (!this._Train) { + this._Train = this.graphicTemplate.new(); + this.Train.loadData(this.graphicTemplate.datas); + this.container.addChild(this.Train); + } + return this._Train; + } + + redraw(p: Point): void { + this.Train.doRepaint(); + this.container.position.set(p.x, p.y); + } + onRightClick(): void { + this.createAndStore(true); + } + onLeftDown(e: FederatedPointerEvent): void { + this.container.position.copyFrom(this.toCanvasCoordinates(e.global)); + this.createAndStore(true); + } + prepareData(data: ITrainData): boolean { + data.transform = this.container.saveTransform(); + return true; + } +} + +export class trainInteraction extends GraphicInteractionPlugin { + static Name = 'train_transform'; + constructor(app: JlDrawApp) { + super(trainInteraction.Name, app); + } + static init(app: JlDrawApp) { + return new trainInteraction(app); + } + filter(...grahpics: JlGraphic[]): Train[] | undefined { + return grahpics.filter((g) => g.type === Train.Type).map((g) => g as Train); + } + bind(g: Train): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.scalable = true; + g.rotatable = true; + } + unbind(g: Train): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + } +} diff --git a/src/graphics/trainLine/TrainLine.ts b/src/graphics/trainLine/TrainLine.ts new file mode 100644 index 0000000..ea326d6 --- /dev/null +++ b/src/graphics/trainLine/TrainLine.ts @@ -0,0 +1,81 @@ +import { + GraphicData, + GraphicState, + GraphicIdGenerator, + JlGraphic, + JlGraphicTemplate, +} from 'src/jl-graphic'; +import trainLineSprites from './trainLineSprites.png'; + +import { Assets, Sprite, Texture } from 'pixi.js'; + +export interface ITrainLineData extends GraphicData { + get code(): string; + set code(v: string); +} + +export interface ITrainLineState extends GraphicState { + get lineId(): number; + set lineId(v: number); + get trainIndex(): string; + set trainIndex(v: string); + get groupId(): string; + set groupId(v: string); + get show(): boolean; + set show(v: boolean); + get kilometerCode(): number; + set kilometerCode(v: number); + get dir(): number; + set dir(v: number); +} + +export class TrainLine extends JlGraphic { + static Type = 'TrainLine'; + train: Sprite; + trainTextures: Texture; + + constructor(trainTextures: Texture) { + super(TrainLine.Type); + this.trainTextures = trainTextures; + this.train = new Sprite(); + this.train.texture = this.trainTextures; + this.train.anchor.set(0.5); + this.train.scale.set(0.02, 0.02); + this.addChild(this.train); + } + get states(): ITrainLineState { + return this.getStates(); + } + doRepaint(): void { + this.train.texture = this.trainTextures; + // console.log(this.states, '****'); + // this.train.position.set(100, 100); + // const runLine = this.queryStore.queryById(this.states.lineId + ''); + } +} + +export class ItrainLineTemplate extends JlGraphicTemplate { + trainTextures?: Texture; + constructor(dataTemplate: ITrainLineData, stateTemplate: ITrainLineState) { + super(TrainLine.Type, { + dataTemplate, + stateTemplate, + }); + } + new(): TrainLine { + if (this.trainTextures) { + const data = this.datas as GraphicData; + data.id = GraphicIdGenerator.next(); + data.graphicType = this.type; + const g = new TrainLine(this.trainTextures); + g.loadData(data); + g.loadState(this.states); + return g; + } + throw new Error('资源未加载/加载失败'); + } + async loadAssets(): Promise { + this.trainTextures = await Assets.load(trainLineSprites); + return this.trainTextures as Texture; + } +} diff --git a/src/graphics/trainLine/TrainLineAssistant.ts b/src/graphics/trainLine/TrainLineAssistant.ts new file mode 100644 index 0000000..ce26b49 --- /dev/null +++ b/src/graphics/trainLine/TrainLineAssistant.ts @@ -0,0 +1,76 @@ +import { FederatedMouseEvent, Point } from 'pixi.js'; +import { + GraphicDrawAssistant, + GraphicInteractionPlugin, + JlDrawApp, + JlGraphic, +} from 'src/jl-graphic'; +import { ITrainLineData, TrainLine, ItrainLineTemplate } from './TrainLine'; + +export class TrainLineDraw extends GraphicDrawAssistant< + ItrainLineTemplate, + ITrainLineData +> { + train: TrainLine | null = null; + + constructor(app: JlDrawApp, template: ItrainLineTemplate) { + super(app, template, 'directions_bus_filled', '列车线网'); + ItrainLineInteraction.init(app); + } + + bind(): void { + super.bind(); + if (!this.train) { + this.train = this.graphicTemplate.new(); + this.container.addChild(this.train); + } + } + + public get trainLine(): TrainLine { + if (!this.train) { + throw new Error('列车绘制逻辑异常'); + } + return this.train; + } + + redraw(cp: Point): void { + this.trainLine.position.copyFrom(cp); + } + onLeftUp(e: FederatedMouseEvent): void { + this.trainLine.position.copyFrom(this.toCanvasCoordinates(e.global)); + this.createAndStore(false); + } + prepareData(data: ITrainLineData): boolean { + data.transform = this.trainLine.saveTransform(); + return true; + } + onEsc(): void { + this.finish(); + } +} + +export class ItrainLineInteraction extends GraphicInteractionPlugin { + static Name = 'trainLine_transform'; + constructor(app: JlDrawApp) { + super(ItrainLineInteraction.Name, app); + } + static init(app: JlDrawApp) { + return new ItrainLineInteraction(app); + } + filter(...grahpics: JlGraphic[]): TrainLine[] | undefined { + return grahpics + .filter((g) => g.type === TrainLine.Type) + .map((g) => g as TrainLine); + } + bind(g: TrainLine): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.scalable = true; + g.rotatable = true; + } + unbind(g: TrainLine): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + } +} diff --git a/src/graphics/trainLine/trainLineSprites.png b/src/graphics/trainLine/trainLineSprites.png new file mode 100644 index 0000000..75e8a93 Binary files /dev/null and b/src/graphics/trainLine/trainLineSprites.png differ diff --git a/src/graphics/trainWindow/TrainWindow.ts b/src/graphics/trainWindow/TrainWindow.ts new file mode 100644 index 0000000..bfcd1c2 --- /dev/null +++ b/src/graphics/trainWindow/TrainWindow.ts @@ -0,0 +1,86 @@ +import { Color, Graphics, Rectangle } from 'pixi.js'; +import { + GraphicData, + GraphicRelationParam, + JlGraphic, + JlGraphicTemplate, + distance2, + getRectangleCenter, +} from 'src/jl-graphic'; +import { Section, SectionType } from '../section/Section'; + +export interface ITrainWindowData extends GraphicData { + get code(): string; // 编号 + set code(v: string); + get sectionId(): string; // 编号 + set sectionId(v: string); + clone(): ITrainWindowData; + copyFrom(data: ITrainWindowData): void; + eq(other: ITrainWindowData): boolean; +} + +export const TrainWindowConsts = { + width: 40, + height: 15, + lineWidth: 2, + lineColor: '0x0fe81f', + offsetSection: 120, +}; + +export class TrainWindow extends JlGraphic { + static Type = 'TrainWindow'; + rectGraphic: Graphics = new Graphics(); + constructor() { + super(TrainWindow.Type); + this.addChild(this.rectGraphic); + } + get datas(): ITrainWindowData { + return this.getDatas(); + } + doRepaint(): void { + const section = this.queryStore.queryById
(this.datas.sectionId); + let width = TrainWindowConsts.width; + if (section.datas.sectionType == SectionType.Logic) { + const ps = section.getStartPoint(); + const pe = section.getEndPoint(); + width = distance2(ps, pe); + } + const rectGraphic = this.rectGraphic; + rectGraphic.clear(); + rectGraphic.lineStyle( + TrainWindowConsts.lineWidth, + new Color(TrainWindowConsts.lineColor) + ); + rectGraphic.drawRect(0, 0, width, TrainWindowConsts.height); + const rectP = new Rectangle(0, 0, width, TrainWindowConsts.height); + rectGraphic.pivot = getRectangleCenter(rectP); + } + loadRelations(): void { + const sectionId = this.datas.sectionId; + if (sectionId) { + const section = this.queryStore.queryById
(sectionId); + if (section) { + this.relationManage.addRelation( + this, + new GraphicRelationParam(section, section.datas.id) + ); + } + } + } + getRelatedSections(): Section[] { + return this.queryRelationByType('Section').map((rl) => + rl.getOtherGraphic
(this) + ); + } +} + +export class TrainWindowTemplate extends JlGraphicTemplate { + constructor(dataTemplate: ITrainWindowData) { + super(TrainWindow.Type, { + dataTemplate, + }); + } + new(): TrainWindow { + return new TrainWindow(); + } +} diff --git a/src/graphics/trainWindow/TrainWindowDrawAssistant.ts b/src/graphics/trainWindow/TrainWindowDrawAssistant.ts new file mode 100644 index 0000000..f0e117e --- /dev/null +++ b/src/graphics/trainWindow/TrainWindowDrawAssistant.ts @@ -0,0 +1,227 @@ +import { FederatedPointerEvent, IHitArea, Point } from 'pixi.js'; +import { + AbsorbableLine, + AbsorbablePosition, + GraphicDrawAssistant, + GraphicIdGenerator, + GraphicInteractionPlugin, + JlDrawApp, + JlGraphic, + distance2, + linePoint, +} from 'src/jl-graphic'; + +import { + ITrainWindowData, + TrainWindow, + TrainWindowTemplate, + TrainWindowConsts, +} from './TrainWindow'; +import { Section, SectionType } from '../section/Section'; + +export interface ITrainWindowDrawOptions { + newData: () => ITrainWindowData; +} + +export class GenerateParams { + count: number; + interval: number; + pd: boolean; // 是否在右侧开始添加 + constructor(count: number, interval: number, pd: boolean) { + this.count = count; + this.interval = interval; + this.pd = pd; + } +} + +export class TrainWindowDraw extends GraphicDrawAssistant< + TrainWindowTemplate, + ITrainWindowData +> { + trainWindowGraph: TrainWindow; + constructor(app: JlDrawApp, template: TrainWindowTemplate) { + super(app, template, 'sym_o_square', '不展示'); + this.trainWindowGraph = this.graphicTemplate.new(); + this.container.addChild(this.trainWindowGraph); + TrainWindowInteraction.init(app); + } + + bind(): void { + super.bind(); + this.trainWindowGraph.loadData(this.graphicTemplate.datas); + this.trainWindowGraph.doRepaint(); + } + + onLeftDown(e: FederatedPointerEvent): void { + this.container.position.copyFrom(this.toCanvasCoordinates(e.global)); + this.createAndStore(true); + } + + redraw(p: Point): void { + this.container.position.copyFrom(p); + } + + prepareData(data: ITrainWindowData): boolean { + data.transform = this.container.saveTransform(); + return true; + } + generates(trainWindow: TrainWindow, params: GenerateParams): void { + const { count, pd } = params; + let { interval } = params; + const ps = trainWindow.datas.transform.position; + let direction; + if (pd) { + direction = 1; + interval = direction * interval; + } else { + direction = -1; + interval = direction * interval; + } + const p = new Point( + ps.x + direction * TrainWindowConsts.width + interval, + ps.y + ); + const trainWindows: TrainWindow[] = []; + + for (let i = 0; i < count; i++) { + const point = p.clone(); + const offsetX = (direction * TrainWindowConsts.width + interval) * i; + point.x += offsetX; + const trainWindow = new TrainWindow(); + trainWindow.loadData(this.graphicTemplate.datas); + trainWindow.position.copyFrom(point); + trainWindow.id = GraphicIdGenerator.next(); + trainWindows.push(trainWindow); + } + this.storeGraphic(...trainWindows); + } + draw(x: number, ps: Point, direction: number, section: Section) { + const trainWindow = new TrainWindow(); + trainWindow.loadData(this.graphicTemplate.datas); + trainWindow.position.set( + x, + ps.y - direction * TrainWindowConsts.offsetSection + ); + trainWindow.id = GraphicIdGenerator.next(); + trainWindow.datas.sectionId = section.id; + this.storeGraphic(trainWindow); + trainWindow.loadRelations(); + } + oneGenerates(height: Point) { + const sections = this.app.queryStore.queryByType
(Section.Type); + const trainWindowAll = this.app.queryStore.queryByType( + TrainWindow.Type + ); + this.app.deleteGraphics(...trainWindowAll); + sections.forEach((section) => { + const ps = section.localToCanvasPoint(section.getStartPoint()); + const pe = section.localToCanvasPoint(section.getEndPoint()); + let direction = 1; + if (ps.y > height.y) { + direction = -1; + } + const x = (ps.x + pe.x) / 2; + if (section.datas.children.length) { + section.childSections.forEach((childSection) => { + const psChild = childSection.localToCanvasPoint( + childSection.getStartPoint() + ); + this.draw(psChild.x, psChild, direction, childSection); + }); + } else { + this.draw(x, ps, direction, section); + } + }); + } +} + +//碰撞检测 +export class RectGraphicHitArea implements IHitArea { + rect: TrainWindow; + constructor(rect: TrainWindow) { + this.rect = rect; + } + contains(x: number, y: number): boolean { + const section = this.rect.queryStore.queryById
( + this.rect.datas.sectionId + ); + let width = TrainWindowConsts.width; + if (section.datas.sectionType == SectionType.Logic) { + const ps = section.getStartPoint(); + const pe = section.getEndPoint(); + width = distance2(ps, pe); + } + let contains = false; + const tolerance = TrainWindowConsts.lineWidth; + const p1 = new Point(0, 0); + const p2 = new Point(width, 0); + const p3 = new Point(width, TrainWindowConsts.height); + const p4 = new Point(0, TrainWindowConsts.height); + const p = new Point(x, y); + + contains = contains || linePoint(p1, p2, p, tolerance); + contains = contains || linePoint(p2, p3, p, tolerance); + contains = contains || linePoint(p3, p4, p, tolerance); + contains = contains || linePoint(p4, p1, p, tolerance); + return contains; + } +} + +/** + * 构建吸附位置 + * @param polygon + * @returns + */ +function buildAbsorbablePositions( + trainWindow: TrainWindow +): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + const trainWindows = trainWindow.queryStore.queryByType( + TrainWindow.Type + ); + const { width } = trainWindow.getGraphicApp().canvas; + trainWindows.forEach((other) => { + if (other.id == trainWindow.id) { + return; + } + const ps = other.datas.transform.position; + const xs = new AbsorbableLine({ x: 0, y: ps.y }, { x: width, y: ps.y }); + aps.push(xs); + }); + return aps; +} + +export class TrainWindowInteraction extends GraphicInteractionPlugin { + static Name = 'TrainWindow_transform'; + constructor(app: JlDrawApp) { + super(TrainWindowInteraction.Name, app); + } + static init(app: JlDrawApp) { + return new TrainWindowInteraction(app); + } + filter(...grahpics: JlGraphic[]): TrainWindow[] | undefined { + return grahpics + .filter((g) => g.type === TrainWindow.Type) + .map((g) => g as TrainWindow); + } + bind(g: TrainWindow): void { + g.eventMode = 'static'; + g.cursor = 'pointer'; + g.scalable = true; + g.rotatable = true; + g.rectGraphic.hitArea = new RectGraphicHitArea(g); + g.on('transformstart', this.move, this); + } + unbind(g: TrainWindow): void { + g.eventMode = 'none'; + g.scalable = false; + g.rotatable = false; + g.off('selected', this.move, this); + } + move(): void { + const trainWindow = this.app.selectedGraphics[0] as TrainWindow; + this.app.setOptions({ + absorbablePositions: buildAbsorbablePositions(trainWindow), + }); + } +} diff --git a/src/graphics/trainWindow/oneClickDrawAssistant.ts b/src/graphics/trainWindow/oneClickDrawAssistant.ts new file mode 100644 index 0000000..c0c52b9 --- /dev/null +++ b/src/graphics/trainWindow/oneClickDrawAssistant.ts @@ -0,0 +1,81 @@ +import { Color, FederatedPointerEvent, Graphics, Point } from 'pixi.js'; +import { + GraphicData, + GraphicDrawAssistant, + JlDrawApp, + JlGraphic, + JlGraphicTemplate, +} from 'src/jl-graphic'; +import { TrainWindow } from './TrainWindow'; +import { TrainWindowDraw } from './TrainWindowDrawAssistant'; +import { AxleCounting } from '../axleCounting/AxleCounting'; +import { AxleCountingDraw } from '../axleCounting/AxleCountingDrawAssistant'; +import { useDrawStore } from 'src/stores/draw-store'; + +interface IOneClickData extends GraphicData { + get code(): string; // 编号 +} + +export class OneClickGenerate extends JlGraphic { + static Type = 'OneClickGenerate'; + lineGraphic: Graphics = new Graphics(); + constructor() { + super(OneClickGenerate.Type); + this.addChild(this.lineGraphic); + } + + doRepaint(): void { + this.lineGraphic.clear(); + this.lineGraphic.lineStyle(1, new Color('0xff0000')); + this.lineGraphic.moveTo(-1920, 0); + this.lineGraphic.lineTo(1920, 0); + } +} + +export class OneClickGenerateTemplate extends JlGraphicTemplate { + constructor() { + super(OneClickGenerate.Type, {}); + } + new(): OneClickGenerate { + return new OneClickGenerate(); + } +} + +export class OneClickGenerateDraw extends GraphicDrawAssistant< + OneClickGenerateTemplate, + IOneClickData +> { + lineGraph: OneClickGenerate; + constructor(app: JlDrawApp, template: OneClickGenerateTemplate) { + super(app, template, 'sym_o_square', '不展示'); + this.lineGraph = this.graphicTemplate.new(); + this.container.addChild(this.lineGraph); + } + + bind(): void { + super.bind(); + this.lineGraph.doRepaint(); + } + onLeftDown(e: FederatedPointerEvent): void { + const type = useDrawStore().$state.oneClickType; + if (type == 'TrainWindow') { + const trainWindowDraw = this.app.getDrawAssistant( + TrainWindow.Type + ) as TrainWindowDraw; + trainWindowDraw.oneGenerates(this.toCanvasCoordinates(e.global)); + } else { + const axleCountingDraw = this.app.getDrawAssistant( + AxleCounting.Type + ) as AxleCountingDraw; + axleCountingDraw.oneGenerates(this.toCanvasCoordinates(e.global)); + } + this.finish(); + } + + redraw(p: Point): void { + this.container.position.copyFrom(p); + } + prepareData(): boolean { + return true; + } +} diff --git a/src/graphics/turnout/Turnout.ts b/src/graphics/turnout/Turnout.ts new file mode 100644 index 0000000..9d83f43 --- /dev/null +++ b/src/graphics/turnout/Turnout.ts @@ -0,0 +1,351 @@ +import { Graphics, IPointData } from 'pixi.js'; +import { + GraphicData, + GraphicRelationParam, + GraphicState, + JlGraphic, + JlGraphicTemplate, + VectorText, + angleOfIncludedAngle, + distance2, +} from 'src/jl-graphic'; +import { Section, SectionPort } from '../section/Section'; +import { epsilon } from 'src/jl-graphic/math'; +import { + IRelatedRefData, + createRelatedRefProto, + protoPort2Data, +} from '../CommonGraphics'; +import { KilometerSystem } from '../signal/Signal'; + +export interface ITurnoutData extends GraphicData { + get code(): string; + set code(code: string); + get pointA(): IPointData[]; //A端点列表(从岔心向外) + set pointA(point: IPointData[]); + get pointB(): IPointData[]; + set pointB(point: IPointData[]); + get pointC(): IPointData[]; + set pointC(point: IPointData[]); + get paRef(): IRelatedRefData | undefined; + set paRef(ref: IRelatedRefData | undefined); + get pbRef(): IRelatedRefData | undefined; + set pbRef(ref: IRelatedRefData | undefined); + get pcRef(): IRelatedRefData | undefined; + set pcRef(ref: IRelatedRefData | undefined); + get kilometerSystem(): KilometerSystem[]; + set kilometerSystem(v: KilometerSystem[]); + clone(): ITurnoutData; + copyFrom(data: ITurnoutData): void; + eq(other: ITurnoutData): boolean; +} + +export const TurnoutConsts = { + lineColor: '#5578b6', + lineWidth: 5, + forkLenth: 20, + labelFontSize: 12, +}; + +export enum TurnoutPosition { + NORMAL = 0, + REVERSE = 1, +} + +export enum TurnoutPort { + A = 'A', + B = 'B', + C = 'C', +} + +export interface ITurnoutState extends GraphicState { + position: TurnoutPosition; +} + +export function getForkPoint(r: number, p: IPointData): IPointData { + if (r === 0) return { x: 0, y: 0 }; + const len = Math.sqrt((-p.x) ** 2 + (-p.y) ** 2); + const scale = r / len; + return { x: scale * p.x, y: scale * p.y }; +} + +export class TurnoutSection extends Graphics { + turnout: Turnout; + port: TurnoutPort; + constructor(turnout: Turnout, port: TurnoutPort) { + super(); + this.turnout = turnout; + this.port = port; + } + + paint() { + let pList: IPointData[] = []; + switch (this.port) { + case TurnoutPort.A: + pList = this.turnout.datas.pointA; + break; + case TurnoutPort.B: + pList = this.turnout.datas.pointB; + break; + case TurnoutPort.C: + pList = this.turnout.datas.pointC; + break; + } + const gap = this.port === TurnoutPort.A ? 0 : TurnoutConsts.forkLenth; + const start = getForkPoint(gap, pList[0]); + this.clear() + .lineStyle(TurnoutConsts.lineWidth, TurnoutConsts.lineColor) + .moveTo(start.x, start.y); + pList.forEach((p) => { + const { x, y } = p; + this.lineTo(x, y); + }); + } +} + +class ForkGraphic extends Graphics { + turnout: Turnout; + constructor(turnout: Turnout) { + super(); + this.turnout = turnout; + } + + paint(p: IPointData) { + const target = getForkPoint(TurnoutConsts.forkLenth, p); + this.clear() + .lineStyle(TurnoutConsts.lineWidth, TurnoutConsts.lineColor) + .moveTo(0, 0) + .lineTo(target.x, target.y); + } +} + +export class Turnout extends JlGraphic { + static Type = 'Turnout'; + graphics: { + fork: ForkGraphic; + sections: [TurnoutSection, TurnoutSection, TurnoutSection]; + label: VectorText; + }; + + constructor() { + super(Turnout.Type); + this.name = 'turnout'; + this.graphics = { + fork: new ForkGraphic(this), + sections: [ + new TurnoutSection(this, TurnoutPort.A), + new TurnoutSection(this, TurnoutPort.B), + new TurnoutSection(this, TurnoutPort.C), + ], + label: new VectorText(), + }; + this.addChild(this.graphics.fork); + // this.addChild(...this.graphics.sections); + this.addChild(this.graphics.sections[0]); + this.addChild(this.graphics.sections[1]); + this.addChild(this.graphics.sections[2]); + this.graphics.label.anchor.set(0.5); + this.graphics.label.style.fill = '#0f0'; + this.graphics.label.setVectorFontSize(TurnoutConsts.labelFontSize); + this.graphics.label.position.set(20, 20); + this.graphics.label.transformSave = true; + this.graphics.label.name = 'label'; + this.addChild(this.graphics.label); + } + + get datas(): ITurnoutData { + return this.getDatas(); + } + + get states(): ITurnoutState { + return this.getStates(); + } + + getPortPoints() { + return [this.datas.pointA, this.datas.pointB, this.datas.pointC]; + } + + doRepaint(): void { + const { pointB } = this.datas; + this.graphics.fork.paint(pointB[0]); + + this.graphics.sections.forEach((sectionGraphic) => sectionGraphic.paint()); + + this.graphics.label.text = this.datas.code; + } + + buildRelation(): void { + this.relationManage.deleteRelationOfGraphic(this); + + /** 道岔和区段 */ + this.queryStore.queryByType
(Section.Type).forEach((section) => { + this.getPortPoints().forEach((port, i) => { + if ( + distance2( + section.localToCanvasPoint(section.getStartPoint()), + this.localToCanvasPoint(port[port.length - 1]) + ) <= epsilon + ) { + this.relationManage.addRelation( + new GraphicRelationParam( + this, + [TurnoutPort.A, TurnoutPort.B, TurnoutPort.C][i] + ), + new GraphicRelationParam(section, SectionPort.A) + ); + } + if ( + distance2( + section.localToCanvasPoint(section.getEndPoint()), + this.localToCanvasPoint(port[port.length - 1]) + ) <= epsilon + ) { + this.relationManage.addRelation( + new GraphicRelationParam( + this, + [TurnoutPort.A, TurnoutPort.B, TurnoutPort.C][i] + ), + new GraphicRelationParam(section, SectionPort.B) + ); + } + }); + }); + + /** 道岔和道岔 */ + this.getPortPoints().forEach((thisPort, i) => { + let params: GraphicRelationParam[] = [], + deflection = 180; + this.queryStore.queryByType(Turnout.Type).forEach((turnout) => { + if (turnout.id === this.id) return; + turnout.getPortPoints().forEach((otherPort, j) => { + if ( + distance2( + this.localToCanvasPoint(thisPort[thisPort.length - 1]), + turnout.localToCanvasPoint(otherPort[otherPort.length - 1]) + ) <= epsilon + ) { + const angle = angleOfIncludedAngle( + this.localToCanvasPoint(thisPort[thisPort.length - 1]) /* 交点 */, + thisPort[thisPort.length - 2] + ? this.localToCanvasPoint(thisPort[thisPort.length - 2]) + : this.position, + otherPort[otherPort.length - 2] + ? turnout.localToCanvasPoint(otherPort[otherPort.length - 2]) + : turnout.position + ); + if (180 - Math.abs(angle) <= deflection) { + deflection = 180 - Math.abs(angle); + params = [ + new GraphicRelationParam( + this, + [TurnoutPort.A, TurnoutPort.B, TurnoutPort.C][i] + ), + new GraphicRelationParam( + turnout, + [TurnoutPort.A, TurnoutPort.B, TurnoutPort.C][j] + ), + ]; + } + } + }); + }); + if (params.length === 2) { + this.relationManage.addRelation(params[0], params[1]); + } + }); + } + + saveRelations() { + const paRelation = this.relationManage + .getRelationsOfGraphic(this) + .find( + (relation) => relation.getRelationParam(this).param === TurnoutPort.A + ); + const paDevice = paRelation?.getOtherGraphic
(this); + if (paDevice) { + this.datas.paRef = createRelatedRefProto( + paDevice.type, + paDevice.id, + paRelation?.getOtherRelationParam(this).param + ); + } else { + this.datas.paRef = undefined; + } + const pbRelation = this.relationManage + .getRelationsOfGraphic(this) + .find( + (relation) => relation.getRelationParam(this).param === TurnoutPort.B + ); + const pbDevice = pbRelation?.getOtherGraphic
(this); + if (pbDevice) { + this.datas.pbRef = createRelatedRefProto( + pbDevice.type, + pbDevice.id, + pbRelation?.getOtherRelationParam(this).param + ); + } else { + this.datas.pbRef = undefined; + } + const pcRelation = this.relationManage + .getRelationsOfGraphic(this) + .find( + (relation) => relation.getRelationParam(this).param === TurnoutPort.C + ); + const pcDevice = pcRelation?.getOtherGraphic
(this); + if (pcDevice) { + this.datas.pcRef = createRelatedRefProto( + pcDevice.type, + pcDevice.id, + pcRelation?.getOtherRelationParam(this).param + ); + } else { + this.datas.pcRef = undefined; + } + } + + loadRelations() { + if (this.datas.paRef?.id) { + this.relationManage.addRelation( + new GraphicRelationParam(this, TurnoutPort.A), + new GraphicRelationParam( + this.queryStore.queryById(this.datas.paRef.id), + protoPort2Data(this.datas.paRef.devicePort) + ) + ); + } + if (this.datas.pbRef?.id) { + this.relationManage.addRelation( + new GraphicRelationParam(this, TurnoutPort.B), + new GraphicRelationParam( + this.queryStore.queryById(this.datas.pbRef.id), + protoPort2Data(this.datas.pbRef.devicePort) + ) + ); + } + if (this.datas.pcRef?.id) { + this.relationManage.addRelation( + new GraphicRelationParam(this, TurnoutPort.C), + new GraphicRelationParam( + this.queryStore.queryById(this.datas.pcRef.id), + protoPort2Data(this.datas.pcRef.devicePort) + ) + ); + } + } +} + +export class TurnoutTemplate extends JlGraphicTemplate { + constructor(dataTemplate: ITurnoutData, stateTemplate?: ITurnoutState) { + super(Turnout.Type, { + dataTemplate, + stateTemplate, + }); + } + + new() { + const g = new Turnout(); + g.loadData(this.datas); + // g.loadState(this.states); + return g; + } +} diff --git a/src/graphics/turnout/TurnoutDrawAssistant.ts b/src/graphics/turnout/TurnoutDrawAssistant.ts new file mode 100644 index 0000000..9c22ebb --- /dev/null +++ b/src/graphics/turnout/TurnoutDrawAssistant.ts @@ -0,0 +1,445 @@ +import { + AbsorbablePosition, + DraggablePoint, + GraphicApp, + GraphicDrawAssistant, + GraphicInteractionPlugin, + GraphicTransformEvent, + JlDrawApp, + JlGraphic, + VectorText, + linePoint, + polylinePoint, +} from 'src/jl-graphic'; +import { + ITurnoutData, + Turnout, + TurnoutConsts, + TurnoutPort, + TurnoutSection, + TurnoutTemplate, + getForkPoint, +} from './Turnout'; +import { + DisplayObject, + FederatedMouseEvent, + IHitArea, + IPointData, + Point, +} from 'pixi.js'; +import { + GraphicEditPlugin, + getWaypointRangeIndex, +} from 'src/jl-graphic/plugins/GraphicEditPlugin'; +import { Section } from '../section/Section'; +import AbsorbablePoint, { + AbsorbableLine, +} from 'src/jl-graphic/graphic/AbsorbablePosition'; +import { ContextMenu } from 'src/jl-graphic/ui/ContextMenu'; +import { MenuItemOptions } from 'src/jl-graphic/ui/Menu'; + +export class TurnoutDraw extends GraphicDrawAssistant< + TurnoutTemplate, + ITurnoutData +> { + turnout: Turnout; + constructor(app: JlDrawApp, template: TurnoutTemplate) { + super(app, template, 'sym_o_ramp_left', '道岔Turnout'); + + this.turnout = this.graphicTemplate.new(); + this.container.addChild(this.turnout); + + TurnoutPointsInteractionPlugin.init(app); + } + + onLeftUp(e: FederatedMouseEvent): void { + this.turnout.position.copyFrom(this.toCanvasCoordinates(e.global)); + this.createAndStore(true); + } + + prepareData(data: ITurnoutData): boolean { + data.transform = this.turnout.saveTransform(); + data.code = 'A000000'; + return true; + } + + redraw(cp: Point): void { + this.turnout.position.copyFrom(cp); + } +} + +export class TurnoutHitArea implements IHitArea { + turnout: Turnout; + constructor(turnout: Turnout) { + this.turnout = turnout; + } + contains(x: number, y: number): boolean { + const { pointA, pointB, pointC } = this.turnout.datas; + return ( + polylinePoint( + [...pointA, { x: 0, y: 0 }], + { x, y }, + TurnoutConsts.lineWidth + ) || + polylinePoint( + [...pointB, { x: 0, y: 0 }], + { x, y }, + TurnoutConsts.lineWidth + ) || + polylinePoint( + [...pointC, { x: 0, y: 0 }], + { x, y }, + TurnoutConsts.lineWidth + ) + ); + } +} + +class ForkHitArea implements IHitArea { + turnout: Turnout; + constructor(turnout: Turnout) { + this.turnout = turnout; + } + contains(x: number, y: number): boolean { + const intersectPointB = getForkPoint( + TurnoutConsts.forkLenth, + this.turnout.datas.pointB[0] + ); + const intersectPointC = getForkPoint( + TurnoutConsts.forkLenth, + this.turnout.datas.pointC[0] + ); + + return ( + linePoint( + intersectPointB, + { x: 0, y: 0 }, + { x, y }, + TurnoutConsts.lineWidth + ) || + linePoint( + intersectPointC, + { x: 0, y: 0 }, + { x, y }, + TurnoutConsts.lineWidth + ) + ); + } +} + +class TurnoutSectionHitArea implements IHitArea { + section: TurnoutSection; + constructor(section: TurnoutSection) { + this.section = section; + } + contains(x: number, y: number): boolean { + let points: IPointData[]; + let start: IPointData; + switch (this.section.port) { + case TurnoutPort.A: + points = this.section.turnout.datas.pointA; + start = { x: 0, y: 0 }; + break; + case TurnoutPort.B: + points = this.section.turnout.datas.pointB; + start = getForkPoint(TurnoutConsts.forkLenth, points[0]); + break; + case TurnoutPort.C: + points = this.section.turnout.datas.pointC; + start = getForkPoint(TurnoutConsts.forkLenth, points[0]); + break; + } + return polylinePoint([start, ...points], { x, y }, TurnoutConsts.lineWidth); + } +} + +function buildAbsorbablePositions(turnout: Turnout): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + + const sections = turnout.queryStore.queryByType
(Section.Type); + sections.forEach((section) => { + const ps = new AbsorbablePoint( + section.localToCanvasPoint(section.getStartPoint()) + ); + const pe = new AbsorbablePoint( + section.localToCanvasPoint(section.getEndPoint()) + ); + aps.push(ps, pe); //区段端点 + }); + + const turnouts = turnout.queryStore.queryByType(Turnout.Type); + turnouts.forEach((otherTurnout) => { + const { + pointA: [A], + pointB: [B], + pointC: [C], + } = otherTurnout.datas; + + [A, B, C].forEach((p) => { + aps.push( + new AbsorbablePoint(otherTurnout.localToCanvasPoint(p)), //道岔端点 + new AbsorbableLine( + otherTurnout.localToCanvasPoint({ x: -5 * p.x, y: -5 * p.y }), + otherTurnout.localToCanvasPoint({ x: 5 * p.x, y: 5 * p.y }) + ) //道岔延长线 + ); + }); + aps.push( + new AbsorbableLine( + otherTurnout.localToCanvasPoint({ x: 0, y: -500 }), + otherTurnout.localToCanvasPoint({ x: 0, y: 500 }) + ), //岔心垂直线 + new AbsorbableLine( + otherTurnout.localToCanvasPoint({ x: -500, y: 0 }), + otherTurnout.localToCanvasPoint({ x: 500, y: 0 }) + ), //岔心水平线 + new AbsorbableLine( + otherTurnout.localToCanvasPoint({ x: -500, y: 500 }), + otherTurnout.localToCanvasPoint({ x: 500, y: -500 }) + ), //岔心/ + new AbsorbableLine( + otherTurnout.localToCanvasPoint({ x: -500, y: -500 }), + otherTurnout.localToCanvasPoint({ x: 500, y: 500 }) + ) //岔心\ + ); + }); + + return aps; +} + +function onEditPointCreate(turnout: Turnout, dp: DraggablePoint) { + dp.on('transformstart', (e: GraphicTransformEvent) => { + if (e.isShift()) { + turnout.getGraphicApp().setOptions({ + absorbablePositions: buildAbsorbablePositions(turnout), + }); + } + }); +} + +const addPointConfig: MenuItemOptions = { name: '添加路径点' }; +const clearPointConfig: MenuItemOptions = { name: '清除路径点' }; + +const turnoutSectionEditMenu: ContextMenu = ContextMenu.init({ + name: '道岔区段路径编辑', + groups: [ + { + items: [addPointConfig, clearPointConfig], + }, + ], +}); + +export class TurnoutPointsInteractionPlugin extends GraphicInteractionPlugin { + static Name = 'TurnoutPointsDrag'; + static init(app: JlDrawApp) { + return new TurnoutPointsInteractionPlugin(app); + } + + constructor(app: GraphicApp) { + super(TurnoutPointsInteractionPlugin.Name, app); + app.registerMenu(turnoutSectionEditMenu); + } + + onSectionContextMenu(e: FederatedMouseEvent, section: TurnoutSection) { + let points: IPointData[]; + if (section.port === TurnoutPort.A) points = section.turnout.datas.pointA; + if (section.port === TurnoutPort.B) points = section.turnout.datas.pointB; + if (section.port === TurnoutPort.C) points = section.turnout.datas.pointC; + const p = section.turnout.screenToLocalPoint(e.global); + addPointConfig.handler = () => { + if (section.port === TurnoutPort.A) { + const { start } = getWaypointRangeIndex( + [{ x: 0, y: 0 }, ...section.turnout.datas.pointA], + false, + p, + TurnoutConsts.lineWidth + ); + const points = section.turnout.datas.pointA; + const ps = points.slice(0, start); + ps.push(new Point(p.x, p.y)); + ps.push(...points.slice(start)); + section.turnout.datas.pointA = ps; + } + if (section.port === TurnoutPort.B) { + const { start } = getWaypointRangeIndex( + [{ x: 0, y: 0 }, ...section.turnout.datas.pointB], + false, + p, + TurnoutConsts.lineWidth + ); + const points = section.turnout.datas.pointB; + const ps = points.slice(0, start); + ps.push(new Point(p.x, p.y)); + ps.push(...points.slice(start)); + section.turnout.datas.pointB = ps; + } + if (section.port === TurnoutPort.C) { + const { start } = getWaypointRangeIndex( + [{ x: 0, y: 0 }, ...section.turnout.datas.pointC], + false, + p, + TurnoutConsts.lineWidth + ); + const points = section.turnout.datas.pointC; + const ps = points.slice(0, start); + ps.push(new Point(p.x, p.y)); + ps.push(...points.slice(start)); + section.turnout.datas.pointC = ps; + } + this.onSelected(section.turnout); + }; + clearPointConfig.handler = () => { + if (points.length <= 1) return; + points.splice(0, points.length - 1); + section.turnout.repaint(); + }; + turnoutSectionEditMenu.open(e.global); + } + + bind(g: Turnout): void { + g.graphics.fork.eventMode = 'static'; + g.graphics.fork.cursor = 'pointer'; + g.graphics.fork.hitArea = new ForkHitArea(g); + g.graphics.sections.forEach((sectionGraphic) => { + sectionGraphic.eventMode = 'static'; + sectionGraphic.cursor = 'pointer'; + sectionGraphic.hitArea = new TurnoutSectionHitArea(sectionGraphic); + sectionGraphic.on( + 'rightclick', + (e) => this.onSectionContextMenu(e, sectionGraphic), + sectionGraphic + ); + }); + g.graphics.label.eventMode = 'static'; + g.graphics.label.cursor = 'pointer'; + g.graphics.label.draggable = true; + g.graphics.label.selectable = true; + g.graphics.label.name = 'label'; + g.graphics.label.transformSave = true; + g.transformSave = true; + g.on('selected', this.onSelected, this); + g.on('unselected', this.onUnSelected, this); + } + + unbind(g: Turnout): void { + g.off('selected', this.onSelected, this); + g.off('unselected', this.onUnSelected, this); + g.graphics.sections.forEach((sectionGraphic) => { + sectionGraphic.off('rightclick'); + }); + } + + onSelected(g: DisplayObject) { + const turnout = g as Turnout; + let tep = turnout.getAssistantAppend( + TurnoutEditPlugin.Name + ); + if (!tep) { + tep = new TurnoutEditPlugin(turnout, { onEditPointCreate }); + turnout.addAssistantAppend(tep); + } + tep.reset(); + tep.showAll(); + } + + onUnSelected(g: DisplayObject) { + const turnout = g as Turnout; + const tep = turnout.getAssistantAppend( + TurnoutEditPlugin.Name + ); + if (tep) { + tep.hideAll(); + } + } + + filter(...grahpics: JlGraphic[]): Turnout[] | undefined { + return grahpics.filter((g) => g.type == Turnout.Type) as Turnout[]; + } +} + +type onTurnoutEditPointCreate = (turnout: Turnout, dp: DraggablePoint) => void; + +export interface ITurnoutEditOptions { + onEditPointCreate?: onTurnoutEditPointCreate; +} + +export class TurnoutEditPlugin extends GraphicEditPlugin { + static Name = 'TurnoutEdit'; + options: ITurnoutEditOptions; + editPoints: DraggablePoint[][] = [[], [], []]; + labels: VectorText[] = []; + + constructor(graphic: Turnout, options?: ITurnoutEditOptions) { + super(graphic); + this.name = TurnoutEditPlugin.Name; + this.options = Object.assign({}, options); + this.initEditPoints(); + } + reset(): void { + this.destoryEditPoints(); + this.removeChildren(); + this.initEditPoints(); + } + + initEditPoints() { + const cpA = this.graphic.localToCanvasPoints(...this.graphic.datas.pointA); + const cpB = this.graphic.localToCanvasPoints(...this.graphic.datas.pointB); + const cpC = this.graphic.localToCanvasPoints(...this.graphic.datas.pointC); + const cpMap: Map = new Map([ + [cpA, this.graphic.datas.pointA], + [cpB, this.graphic.datas.pointB], + [cpC, this.graphic.datas.pointC], + ]); + Array.from(cpMap.entries()).forEach(([cpDatas, dataPoints], i) => { + cpDatas.forEach((cpData, j) => { + const dp = new DraggablePoint(cpData); + dp.on('transforming', (e: GraphicTransformEvent) => { + const localPoint = this.graphic.canvasToLocalPoint(dp.position); + dataPoints[j].x = localPoint.x; + dataPoints[j].y = localPoint.y; + + this.graphic.repaint(); + }); + if (this.options.onEditPointCreate) { + this.options.onEditPointCreate(this.graphic, dp); + } + this.editPoints[i].push(dp); + }); + }); + this.editPoints.forEach((cps) => { + this.addChild(...cps); + }); + this.labels = ['A', 'B', 'C'].map((str) => { + const vc = new VectorText(str); + vc.setVectorFontSize(14); + vc.anchor.set(0.5); + return vc; + }); + this.addChild(...this.labels); + } + + destoryEditPoints() { + this.editPoints.forEach((dps) => { + dps.forEach((dp) => { + dp.off('transforming'); + dp.destroy(); + this.removeChild(dp); + }); + }); + this.editPoints = [[], [], []]; + } + + updateEditedPointsPosition() { + const cpA = this.graphic.localToCanvasPoints(...this.graphic.datas.pointA); + const cpB = this.graphic.localToCanvasPoints(...this.graphic.datas.pointB); + const cpC = this.graphic.localToCanvasPoints(...this.graphic.datas.pointC); + [cpA, cpB, cpC].forEach((cps, i) => { + cps.forEach((cp, j) => { + this.editPoints[i][j].position.copyFrom(cp); + if (j === cps.length - 1) { + this.labels[i].position.copyFrom({ x: cp.x, y: cp.y + 12 }); + } + }); + }); + } +} diff --git a/src/jl-graphic/app/JlDrawApp.ts b/src/jl-graphic/app/JlDrawApp.ts new file mode 100644 index 0000000..8a1bfa2 --- /dev/null +++ b/src/jl-graphic/app/JlDrawApp.ts @@ -0,0 +1,679 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-empty-function */ +import { + BitmapFont, + BitmapText, + Container, + DisplayObject, + FederatedMouseEvent, + IPointData, + Point, +} from 'pixi.js'; +import { GraphicIdGenerator } from '../core/IdGenerator'; +import { GraphicData, GraphicTemplate, JlGraphic } from '../core/JlGraphic'; +import { JlOperation } from '../operation/JlOperation'; +import { + AppDragEvent, + AppInteractionPlugin, + CombinationKey, + GraphicTransformEvent, + InteractionPlugin, + KeyListener, + ShiftData, +} from '../plugins'; +import { CommonMouseTool } from '../plugins/CommonMousePlugin'; +import { MenuItemOptions } from '../ui/Menu'; +import { DOWN, LEFT, RIGHT, UP, recursiveChildren } from '../utils'; +import { + GraphicApp, + GraphicAppOptions, + ICanvasProperties, + JlCanvas, +} from './JlGraphicApp'; + +/** + * 图形绘制助手 + */ +export abstract class GraphicDrawAssistant< + GT extends GraphicTemplate, + GD extends GraphicData +> extends AppInteractionPlugin { + readonly __GraphicDrawAssistant = true; + app: JlDrawApp; + type: string; // 图形对象类型 + description: string; // 描述 + icon: string; // 界面显示的图标 + container: Container = new Container(); + graphicTemplate: GT; + + escListener: KeyListener = new KeyListener({ + value: 'Escape', + onRelease: () => { + this.onEsc(); + }, + }); + + onEsc() { + this.createAndStore(true); + } + + constructor( + graphicApp: JlDrawApp, + graphicTemplate: GT, + icon: string, + description: string + ) { + super(graphicTemplate.type, graphicApp); + this.app = graphicApp; + this.type = graphicTemplate.type; + this.graphicTemplate = graphicTemplate; + this.icon = icon; + this.description = description; + this.app.registerGraphicTemplates(this.graphicTemplate); + } + + public get canvas(): JlCanvas { + return this.app.canvas; + } + + bind(): void { + this.app._drawing = true; + const canvas = this.canvas; + canvas.addChild(this.container); + canvas.on('mousedown', this.onLeftDown, this); + canvas.on('mousemove', this.onMouseMove, this); + canvas.on('mouseup', this.onLeftUp, this); + canvas.on('rightdown', this.onRightDown, this); + canvas.on('rightup', this.onRightUp, this); + canvas.on('_rightclick', this.onRightClick, this); + + this.app.viewport.wheel({ + percent: 0.01, + }); + this.app.addKeyboardListener(this.escListener); + + this.app.viewport.drag({ + mouseButtons: 'right', + }); + } + unbind(): void { + this.clearCache(); + const canvas = this.canvas; + if (this.container?.parent) { + canvas.removeChild(this.container); + } + canvas.off('mousedown', this.onLeftDown, this); + canvas.off('mousemove', this.onMouseMove, this); + canvas.off('mouseup', this.onLeftUp, this); + canvas.off('rightdown', this.onRightDown, this); + canvas.off('rightup', this.onRightUp, this); + + this.app.viewport.plugins.remove('wheel'); + + this.app.removeKeyboardListener(this.escListener); + + this.app.viewport.plugins.remove('drag'); + this.app._drawing = false; + } + + onLeftDown(e: FederatedMouseEvent) {} + + onMouseMove(e: FederatedMouseEvent) { + this.redraw(this.toCanvasCoordinates(e.global)); + } + + onLeftUp(e: FederatedMouseEvent) {} + onRightDown(e: FederatedMouseEvent) {} + onRightUp(e: FederatedMouseEvent) {} + onRightClick(e: FederatedMouseEvent) { + this.finish(); + } + /** + * 获取下一个id + */ + nextId(): string { + return GraphicIdGenerator.next(); + } + + clearCache(): void {} + + /** + * 重绘 + * @param cp 鼠标所在画布坐标 + */ + abstract redraw(cp: Point): void; + + abstract prepareData(data: GD): boolean; + + toCanvasCoordinates(p: Point): Point { + return this.app.toCanvasCoordinates(p); + } + /** + * 保存创建的图形对象 + */ + storeGraphic(...graphics: JlGraphic[]): void { + this.app.addGraphics(...graphics); + // 创建图形对象操作记录 + this.app.opRecord.record(new GraphicCreateOperation(this.app, graphics)); + } + /** + * 创建并添加到图形App + */ + createAndStore(finish: boolean): JlGraphic | null { + const data = this.graphicTemplate.datas as GD; + data.id = this.nextId(); + data.graphicType = this.graphicTemplate.type; + if (!this.prepareData(data)) { + if (finish) { + this.finish(); + } + return null; + } + const template = this.graphicTemplate; + const g = template.new(); + g.loadData(data); + this.storeGraphic(g); + if (finish) { + this.finish(g); + } + return g; + } + + /** + * 绘制完成 + */ + finish(...graphics: JlGraphic[]): void { + this.clearCache(); + this.app.interactionPlugin(CommonMouseTool.Name).resume(); + this.app.updateSelected(...graphics); + } +} + +export type DrawAssistant = GraphicDrawAssistant; + +export interface IDrawAppOptions { + /** + * 绘制辅助交互插件 + */ + drawAssistants: DrawAssistant[]; +} + +export type DrawAppOptions = GraphicAppOptions & IDrawAppOptions; + +/** + * 绘制应用 + */ +export class JlDrawApp extends GraphicApp { + font: BitmapFont = BitmapFont.from( + 'coordinates', + { + fontFamily: 'Roboto', + fontSize: 16, + fill: '#ff2700', + }, + { chars: ['画布坐标:() 屏幕坐标:() 缩放:.,', ['0', '9']] } + ); + coordinates: BitmapText = new BitmapText('画布坐标: (0, 0) 屏幕坐标:(0, 0)', { + fontName: 'coordinates', + }); + scaleText: BitmapText = new BitmapText('缩放: 1', { + fontName: 'coordinates', + }); + + drawAssistants: DrawAssistant[] = []; + _drawing = false; + + constructor(dom: HTMLElement) { + super(dom); + + this.appendDrawStatesDisplay(); + + // 拖拽操作记录 + this.appOperationRecord(); + // 绑定通用键盘操作 + this.bindKeyboardOperation(); + } + + setOptions(options: DrawAppOptions): void { + super.setOptions(options); + // this.registerInteractionPlugin(...options.drawAssistants); + } + + registerInteractionPlugin(...plugins: InteractionPlugin[]): void { + plugins.forEach((plugin) => { + if (plugin instanceof GraphicDrawAssistant) { + this.drawAssistants.push(plugin); + } + super.registerInteractionPlugin(plugin); + }); + } + + getDrawAssistant(graphicType: string): DA { + const sda = this.drawAssistants + .filter((da) => da.type === graphicType) + .pop(); + if (!sda) { + throw new Error(`未找到图形绘制助手: ${graphicType}`); + } + return sda as DA; + } + + private appOperationRecord() { + let dragStartDatas: GraphicData[] = []; + this.on('drag_op_start', (e: AppDragEvent) => { + // 图形拖拽,记录初始数据 + if (!e.target.isCanvas()) { + dragStartDatas = this.selectedGraphics.map((g) => g.saveData()); + } + }); + // 图形拖拽操作监听 + this.on('drag_op_end', () => { + // 图形拖拽,记录操作 + if (dragStartDatas.length > 0) { + const newData = this.selectedGraphics.map((g) => g.saveData()); + this.opRecord.record( + new GraphicDataUpdateOperation( + this, + this.selectedGraphics, + dragStartDatas, + newData + ) + ); + dragStartDatas = []; + } + }); + // 菜单操作 + let preMenuHandleDatas: GraphicData[] = []; + this.on('pre-menu-handle', (menu: MenuItemOptions) => { + if (menu.name === '撤销' || menu.name === '重做') { + return; + } + preMenuHandleDatas = this.selectedGraphics.map((g) => g.saveData()); + }); + this.on('post-menu-handle', () => { + if (preMenuHandleDatas.length > 0) { + const newData = this.selectedGraphics.map((g) => g.saveData()); + this.opRecord.record( + new GraphicDataUpdateOperation( + this, + this.selectedGraphics, + preMenuHandleDatas, + newData + ) + ); + preMenuHandleDatas = []; + } + }); + } + + /** + * 绘制状态信息显示 + */ + private appendDrawStatesDisplay(): void { + this.app.stage.addChild(this.coordinates); + this.app.stage.addChild(this.scaleText); + const bound = this.coordinates.getLocalBounds(); + this.scaleText.position.set(bound.width + 10, 0); + this.canvas.on('mousemove', (e) => { + if (e.target) { + const { x, y } = this.toCanvasCoordinates(e.global); + const cpTxt = `(${x}, ${y})`; + const tp = e.global; + const tpTxt = `(${tp.x}, ${tp.y})`; + this.coordinates.text = `画布坐标:${cpTxt} 屏幕坐标:${tpTxt}`; + const bound = this.coordinates.getLocalBounds(); + this.scaleText.position.set(bound.width + 10, 0); + } + }); + this.viewport.on('zoomed-end', () => { + this.scaleText.text = `缩放: ${this.viewport.scaled}`; + }); + } + + bindKeyboardOperation(): void { + this.addKeyboardListener( + // Ctrl + A + new KeyListener({ + value: 'KeyA', + combinations: [CombinationKey.Ctrl], + onPress: (e: KeyboardEvent, app: GraphicApp) => { + if (e.ctrlKey) { + (app as JlDrawApp).selectAllGraphics(); + } + }, + }) + ); + + // 复制功能 + this.addKeyboardListener( + new KeyListener({ + value: 'KeyD', + combinations: [CombinationKey.Shift], + onPress: (e: KeyboardEvent, app: GraphicApp) => { + app.graphicCopyPlugin.init(); + }, + }) + ); + this.addKeyboardListener( + new KeyListener({ + // Ctrl + Z + value: 'KeyZ', + global: true, + combinations: [CombinationKey.Ctrl], + onPress: (e: KeyboardEvent, app: GraphicApp) => { + app.opRecord.undo(); + }, + }) + ); + this.addKeyboardListener( + new KeyListener({ + // Ctrl + Shift + Z + value: 'KeyZ', + global: true, + combinations: [CombinationKey.Ctrl, CombinationKey.Shift], + onPress: (e: KeyboardEvent, app: GraphicApp) => { + app.opRecord.redo(); + }, + }) + ); + + this.addKeyboardListener( + new KeyListener({ + value: 'Delete', + onPress: (e: KeyboardEvent, app: GraphicApp) => { + (app as JlDrawApp).deleteSelectedGraphics(); + }, + }) + ); + this.addKeyboardListener( + new KeyListener({ + value: 'ArrowUp', + pressTriggerAsOriginalEvent: true, + onPress: (e: KeyboardEvent, app: GraphicApp) => { + updateGraphicPositionOnKeyboardEvent(app, UP); + }, + onRelease: (e: KeyboardEvent, app: GraphicApp) => { + recordGraphicMoveOperation(app); + }, + }) + ); + this.addKeyboardListener( + new KeyListener({ + value: 'ArrowDown', + pressTriggerAsOriginalEvent: true, + onPress: (e: KeyboardEvent, app: GraphicApp) => { + updateGraphicPositionOnKeyboardEvent(app, DOWN); + }, + onRelease: (e: KeyboardEvent, app: GraphicApp) => { + recordGraphicMoveOperation(app); + }, + }) + ); + this.addKeyboardListener( + new KeyListener({ + value: 'ArrowLeft', + pressTriggerAsOriginalEvent: true, + onPress: (e: KeyboardEvent, app: GraphicApp) => { + updateGraphicPositionOnKeyboardEvent(app, LEFT); + }, + onRelease: (e: KeyboardEvent, app: GraphicApp) => { + recordGraphicMoveOperation(app); + }, + }) + ); + this.addKeyboardListener( + new KeyListener({ + value: 'ArrowRight', + pressTriggerAsOriginalEvent: true, + onPress: (e: KeyboardEvent, app: GraphicApp) => { + updateGraphicPositionOnKeyboardEvent(app, RIGHT); + }, + onRelease: (e: KeyboardEvent, app: GraphicApp) => { + recordGraphicMoveOperation(app); + }, + }) + ); + } + + /** + * 全选 + */ + selectAllGraphics() { + this.updateSelected(...this.queryStore.getAllGraphics()); + } + + /** + * 图形对象存储处理,默认添加图形交互 + * @param graphic + */ + beforeGraphicStore(graphic: JlGraphic): void { + graphic.eventMode = 'static'; + graphic.selectable = true; + graphic.draggable = true; + } + + /** + * 删除选中图形对象 + */ + deleteSelectedGraphics() { + const deletes = this.selectedGraphics.slice( + 0, + this.selectedGraphics.length + ); + this.deleteGraphics(...this.selectedGraphics); + // 删除图形对象操作记录 + this.opRecord.record(new GraphicDeleteOperation(this, deletes)); + } + + updateCanvasAndRecord(data: ICanvasProperties) { + const old = this.canvas.properties.clone(); + this.canvas.update(data); + const newVal = this.canvas.properties.clone(); + this.opRecord.record( + new UpdateCanvasOperation(this, this.canvas, old, newVal) + ); + } + + updateGraphicAndRecord(g: JlGraphic, data: GraphicData) { + const old = g.saveData(); + g.updateData(data); + const newVal = g.saveData(); + this.opRecord.record( + new GraphicDataUpdateOperation(this, [g], [old], [newVal]) + ); + } +} + +let dragStartDatas: GraphicData[] = []; + +function handleArrowKeyMoveGraphics( + app: GraphicApp, + handler: (obj: DisplayObject) => void +) { + if ( + app.selectedGraphics.length === 1 && + app.selectedGraphics[0].hasSelectedChilds() + ) { + recursiveChildren(app.selectedGraphics[0], (child) => { + if (child.selected && child.draggable) { + handler(child); + } + }); + } else { + app.selectedGraphics.forEach((g) => { + handler(g); + }); + } +} + +function updateGraphicPositionOnKeyboardEvent(app: GraphicApp, dp: IPointData) { + let dragStart = false; + if (dragStartDatas.length === 0) { + dragStartDatas = app.selectedGraphics.map((g) => g.saveData()); + dragStart = true; + } + handleArrowKeyMoveGraphics(app, (g) => { + if (dragStart) { + g.shiftStartPoint = g.position.clone(); + g.emit( + 'transformstart', + GraphicTransformEvent.shift(g, ShiftData.new(g.shiftStartPoint)) + ); + } else { + g.shiftLastPoint = g.position.clone(); + } + g.position.x += dp.x; + g.position.y += dp.y; + if (!dragStart) { + if (g.shiftStartPoint && g.shiftLastPoint) { + g.emit( + 'transforming', + GraphicTransformEvent.shift( + g, + ShiftData.new( + g.shiftStartPoint, + g.position.clone(), + g.shiftLastPoint + ) + ) + ); + } + } + }); +} +function recordGraphicMoveOperation(app: GraphicApp) { + if ( + dragStartDatas.length > 0 && + dragStartDatas.length === app.selectedGraphics.length + ) { + const newData = app.selectedGraphics.map((g) => g.saveData()); + app.opRecord.record( + new GraphicDataUpdateOperation( + app, + app.selectedGraphics, + dragStartDatas, + newData + ) + ); + + handleArrowKeyMoveGraphics(app, (g) => { + if (g.shiftStartPoint) { + g.emit( + 'transformend', + GraphicTransformEvent.shift( + g, + ShiftData.new(g.shiftStartPoint, g.position.clone()) + ) + ); + } + }); + } + dragStartDatas = []; +} + +/** + * 更新画布操作 + */ +export class UpdateCanvasOperation extends JlOperation { + obj: JlCanvas; + old: ICanvasProperties; + data: ICanvasProperties; + description = ''; + + constructor( + app: GraphicApp, + obj: JlCanvas, + old: ICanvasProperties, + data: ICanvasProperties + ) { + super(app, 'update-canvas'); + this.app = app; + this.obj = obj; + this.old = old; + this.data = data; + } + + undo(): JlGraphic[] { + this.obj.update(this.old); + return []; + } + redo(): JlGraphic[] { + this.obj.update(this.data); + return []; + } +} +/** + * 创建图形操作 + */ +export class GraphicCreateOperation extends JlOperation { + obj: JlGraphic[]; + description = ''; + + constructor(app: GraphicApp, obj: JlGraphic[]) { + super(app, 'graphic-create'); + this.app = app; + this.obj = obj; + } + + undo(): JlGraphic[] | void { + this.app.deleteGraphics(...this.obj); + } + redo(): JlGraphic[] { + this.app.addGraphics(...this.obj); + return this.obj; + } +} +/** + * 删除图形操作 + */ +export class GraphicDeleteOperation extends JlOperation { + obj: JlGraphic[]; + + constructor(app: GraphicApp, obj: JlGraphic[]) { + super(app, 'graphic-delete'); + this.app = app; + this.obj = obj; + } + + undo(): JlGraphic[] { + this.app.addGraphics(...this.obj); + return this.obj; + } + redo(): void { + this.app.deleteGraphics(...this.obj); + } +} + +export class GraphicDataUpdateOperation extends JlOperation { + obj: JlGraphic[]; + oldData: GraphicData[]; + newData: GraphicData[]; + constructor( + app: GraphicApp, + obj: JlGraphic[], + oldData: GraphicData[], + newData: GraphicData[] + ) { + super(app, 'graphic-drag'); + this.obj = [...obj]; + this.oldData = oldData; + this.newData = newData; + } + + undo(): void | JlGraphic[] { + for (let i = 0; i < this.obj.length; i++) { + const g = this.obj[i]; + // g.exitChildEdit(); + g.updateData(this.oldData[i]); + } + return this.obj; + } + redo(): void | JlGraphic[] { + for (let i = 0; i < this.obj.length; i++) { + const g = this.obj[i]; + // g.exitChildEdit(); + g.updateData(this.newData[i]); + } + return this.obj; + } +} diff --git a/src/jl-graphic/app/JlGraphicApp.ts b/src/jl-graphic/app/JlGraphicApp.ts new file mode 100644 index 0000000..c2b0af8 --- /dev/null +++ b/src/jl-graphic/app/JlGraphicApp.ts @@ -0,0 +1,905 @@ +import EventEmitter from 'eventemitter3'; +import { Viewport } from 'pixi-viewport'; +import { + Application, + Color, + Container, + DisplayObject, + Graphics, + Point, + Rectangle, +} from 'pixi.js'; +import { GraphicQueryStore, GraphicStore } from '../core/GraphicStore'; +import { GraphicIdGenerator } from '../core/IdGenerator'; +import { + GraphicData, + GraphicState, + GraphicTemplate, + GraphicTransform, + JlGraphic, +} from '../core/JlGraphic'; +import { AbsorbablePosition } from '../graphic'; +import { + AppWsMsgBroker, + StompCli, + type AppStateSubscription, + type StompCliOption, +} from '../message/WsMsgBroker'; +import { OperationRecord } from '../operation/JlOperation'; +import { + AnimationManager, + CommonMouseTool, + GraphicTransformPlugin, + IMouseToolOptions, +} from '../plugins'; +import { GraphicCopyPlugin } from '../plugins/CopyPlugin'; +import { + AppDragEvent, + DragPlugin, + InteractionPlugin, + InteractionPluginType, + ViewportMovePlugin, +} from '../plugins/InteractionPlugin'; +import { + JlGraphicAppKeyboardPlugin, + KeyListener, +} from '../plugins/KeyboardPlugin'; +import { ContextMenu, ContextMenuPlugin } from '../ui/ContextMenu'; +import { MenuItemOptions } from '../ui/Menu'; +import { getRectangleCenter, recursiveChildren } from '../utils/GraphicUtils'; + +export const AppConsts = { + viewportname: '__viewport', + canvasname: '__jlcanvas', + AssistantAppendsName: '__assistantAppends', +}; + +/** + * 画布属性 + */ +export interface ICanvasProperties { + width: number; + height: number; + backgroundColor: string; + viewportTransform: GraphicTransform; +} + +export class CanvasData implements ICanvasProperties { + width: number; + height: number; + backgroundColor: string; + viewportTransform: GraphicTransform; + constructor( + properties: ICanvasProperties = { + width: 1920, + height: 1080, + backgroundColor: '#ffffff', + viewportTransform: GraphicTransform.default(), + } + ) { + this.width = properties.width; + this.height = properties.height; + this.backgroundColor = properties.backgroundColor; + this.viewportTransform = properties.viewportTransform; + } + + copyFrom(properties: ICanvasProperties): boolean { + let sizeChange = false; + if (properties.width <= 0 || properties.height <= 0) { + console.error('画布宽度/高度不能小于等于0'); + } else { + const width = Math.floor(properties.width); + const height = Math.floor(properties.height); + if (this.width != width) { + this.width = width; + sizeChange = true; + } + if (this.height != height) { + this.height = height; + sizeChange = true; + } + } + this.backgroundColor = properties.backgroundColor; + this.viewportTransform = properties.viewportTransform; + return sizeChange; + } + + clone(): CanvasData { + const cp = new CanvasData(this); + return cp; + } +} + +export class JlCanvas extends Container { + __JlCanvas = true; + type = 'Canvas'; + app: GraphicApp; + _properties: CanvasData; + bg: Graphics = new Graphics(); // 背景 + nonInteractiveContainer: Container; // 无交互对象容器 + assistantAppendContainer: Container; // 辅助附加容器 + + constructor(app: GraphicApp, properties: CanvasData = new CanvasData()) { + super(); + this.app = app; + this._properties = properties; + this.eventMode = 'static'; + this.nonInteractiveContainer = new Container(); + this.nonInteractiveContainer.name = 'non-interactives'; + this.nonInteractiveContainer.eventMode = 'none'; + this.addChild(this.bg); + this.addChild(this.nonInteractiveContainer); + + this.sortableChildren = true; + this.assistantAppendContainer = new Container(); + this.assistantAppendContainer.eventMode = 'static'; + this.assistantAppendContainer.name = AppConsts.AssistantAppendsName; + this.assistantAppendContainer.zIndex = 999; + this.assistantAppendContainer.sortableChildren = true; + this.addChild(this.assistantAppendContainer); + + this.repaint(); + } + + /** + * 图形重绘(数据/状态变化时触发) + */ + repaint(): void { + this.doRepaint(); + } + + public get width(): number { + return this._properties.width; + } + + public get height(): number { + return this._properties.height; + } + + public get backgroundColor(): string { + return this._properties.backgroundColor; + } + + doRepaint() { + this.bg.clear(); + this.bg + .beginFill(new Color(this.backgroundColor)) + .drawRect(0, 0, this._properties.width, this._properties.height) + .endFill(); + } + + public get properties(): CanvasData { + return this._properties; + } + + saveData(): CanvasData { + const vp = this.getViewport(); + this.properties.viewportTransform = vp.saveTransform(); + return this.properties.clone(); + } + + update(properties: ICanvasProperties) { + // 更新画布 + const old = this.properties.clone(); + const sizeChange = this._properties.copyFrom(properties); + this.repaint(); + if (sizeChange) { + this.app.updateViewport(); + } + const vp = this.getViewport(); + vp.loadTransform(properties.viewportTransform); + this.emit('dataupdate', this.properties, old); + } + + addChild(...children: U): U[0] { + const rt = super.addChild(...children); + children.forEach((g) => { + recursiveChildren(g as Container, (child) => child.onAddToCanvas()); + }); + return rt; + } + removeChild(...children: U): U[0] { + children.forEach((g) => { + recursiveChildren(g as Container, (child) => child.onRemoveFromCanvas()); + }); + return super.removeChild(...children); + } + /** + * 添加无交互Child + */ + addNonInteractiveChild(...obj: DisplayObject[]): void { + this.nonInteractiveContainer.addChild(...obj); + obj.forEach((g) => { + recursiveChildren(g as Container, (child) => child.onAddToCanvas()); + }); + } + + removeGraphic(...obj: DisplayObject[]): void { + obj.forEach((g) => { + recursiveChildren(g as Container, (child) => child.onRemoveFromCanvas()); + }); + this.removeChild(...obj); + this.nonInteractiveContainer.removeChild(...obj); + } + + /** + * 移除无交互Child + */ + removeNonInteractiveChild(...obj: DisplayObject[]): void { + obj.forEach((g) => { + recursiveChildren(g as Container, (child) => child.onRemoveFromCanvas()); + }); + this.nonInteractiveContainer.removeChild(...obj); + } + + addAssistantAppends(...appends: DisplayObject[]): void { + this.assistantAppendContainer.addChild(...appends); + appends.forEach((g) => { + recursiveChildren(g as Container, (child) => child.onAddToCanvas()); + }); + } + removeAssistantAppends(...appends: DisplayObject[]): void { + appends.forEach((g) => { + recursiveChildren(g as Container, (child) => child.onAddToCanvas()); + }); + this.assistantAppendContainer.removeChild(...appends); + } + + /** + * 暂停所有可交互对象 + */ + pauseInteractiveChildren() { + this.interactiveChildren = false; + } + + /** + * 恢复所有可交互对象 + */ + resumeInteractiveChildren() { + this.interactiveChildren = true; + } +} + +/** + * 选中改变事件 + */ +export class SelectedChangeEvent { + graphic: JlGraphic; + select: boolean; + + constructor(graphic: JlGraphic, select: boolean) { + this.graphic = graphic; + this.select = select; + } +} + +export interface GraphicAppEvents extends GlobalMixins.GraphicAppEvents { + graphicstored: [graphic: JlGraphic]; + graphicdeleted: [graphic: JlGraphic]; + loadfinish: []; + 'interaction-plugin-resume': [plugin: InteractionPlugin]; // 交互插件启用 + 'interaction-plugin-pause': [plugin: InteractionPlugin]; // 交互插件停止 + 'options-update': [options: GraphicAppOptions]; // 配置更新 + graphicselectedchange: [graphic: JlGraphic, selected: boolean]; + graphicchildselectedchange: [child: DisplayObject, selected: boolean]; + 'viewport-scaled': [vp: Viewport]; + drag_op_start: [event: AppDragEvent]; + drag_op_move: [event: AppDragEvent]; + drag_op_end: [event: AppDragEvent]; + 'pre-menu-handle': [menu: MenuItemOptions]; + 'post-menu-handle': [menu: MenuItemOptions]; + 'websocket-state-change': [app: GraphicApp, connected: boolean]; + destroy: [app: GraphicApp]; +} + +/** + * 图形App构造参数 + */ +export interface IGraphicAppConfig { + /** + * 交互类型配置 + */ + interactiveTypeOptions?: IInteractiveGraphicOptions; + /** + * 最大保存的操作记录数,默认100,越大越占用内存资源 + */ + maxOperationRecords?: number; + /** + * 拖拽触发移动门槛 + */ + threshold?: number; + /** + * 通用鼠标工具选项 + */ + mouseToolOptions?: IMouseToolOptions; + /** + * 可吸附位置列表 + */ + absorbablePositions?: AbsorbablePosition[]; + /** + * 超出屏幕显示范围是否剪裁,默认true + */ + cullable?: boolean; +} + +/** + * 图形添加到容器选项 + */ +export interface IInteractiveGraphicOptions { + /** + * 包含添加到可交互容器的图形类型,和Excludes同时只能存在一个 + */ + interactiveGraphicTypeIncludes?: string[]; + /** + * 不包含添加到可交互容器的图形类型,和Includes同时只能存在一个 + */ + interactiveGraphicTypeExcludes?: string[]; +} + +export type GraphicAppOptions = IGraphicAppConfig; + +/** + * 图形app基类 + */ +export class GraphicApp extends EventEmitter { + private graphicStore: GraphicStore; + _options?: GraphicAppOptions; + dom: HTMLElement; + app: Application; // Pixi 渲染器 + viewport: Viewport; // 视口 + canvas: JlCanvas; // 画布 + interactiveTypeOptions: IInteractiveGraphicOptions; // 图形交互配置 + + graphicTemplateMap: Map = new Map< + string, + GraphicTemplate + >(); // 图形对象模板 + + opRecord: OperationRecord; // 操作记录 + + keyboardPlugin: JlGraphicAppKeyboardPlugin; // 键盘操作处理插件 + graphicCopyPlugin: GraphicCopyPlugin; // 图形复制操作插件 + menuPlugin: ContextMenuPlugin; // 菜单插件 + animationManager: AnimationManager; // 动画管理组件 + + interactionPluginMap: Map = new Map< + string, + InteractionPlugin + >(); // 交互插件 + + wsMsgBroker?: AppWsMsgBroker; // websocket消息代理 + + constructor(dom: HTMLElement) { + super(); + document.body.style.overflow = 'hidden'; + // console.log('创建图形App') + this.dom = dom; + this.graphicStore = new GraphicStore(this); + /** + * 默认都添加为非交互 + */ + this.interactiveTypeOptions = { interactiveGraphicTypeIncludes: [] }; + // 创建pixi渲染app + this.app = new Application({ + width: dom.clientWidth, + height: dom.clientHeight, + antialias: true, + resizeTo: dom, + }); + dom.appendChild(this.app.view as unknown as Node); + + // 创建画布 + this.canvas = new JlCanvas(this); + this.canvas.name = AppConsts.canvasname; + // 创建相机 + this.viewport = new Viewport({ + screenWidth: window.innerWidth, + screenHeight: window.innerHeight, + worldWidth: this.canvas._properties.width, + worldHeight: this.canvas._properties.height, + // divWheel: dom, + passiveWheel: true, + events: this.app.renderer.events, + disableOnContextMenu: true, + }); + // 设置视口操作方式 + this.viewport + .wheel({ + percent: 1, + }) + .pinch() + .clampZoom({ + minScale: 0.1, + maxScale: 8, + }) + .clamp({ + direction: 'all', + }); + this.viewport.name = AppConsts.viewportname; + this.viewport.interactiveChildren = true; + // 添加视口到渲染器舞台 + this.app.stage.addChild(this.viewport); + // 将画布置于视口 + this.viewport.addChild(this.canvas); + + // 监听并通知缩放变化事件 + this.viewport.on('zoomed-end', () => { + this.emit('viewport-scaled', this.viewport); + }); + + this.opRecord = new OperationRecord(); + + // 绑定键盘监听 + this.keyboardPlugin = new JlGraphicAppKeyboardPlugin(this); + this.graphicCopyPlugin = new GraphicCopyPlugin(this); + this.menuPlugin = new ContextMenuPlugin(this); + + // 添加通用交互插件 + CommonMouseTool.new(this).resume(); + + // drag插件 + DragPlugin.new(this).resume(); + // 视口移动插件 + ViewportMovePlugin.new(this); + + // 图形变换插件 + GraphicTransformPlugin.new(this).resume(); + + // 动画管理 + this.animationManager = new AnimationManager(this); + } + + setOptions(options: GraphicAppOptions) { + // console.log('更新选项', options); + if (this._options) { + this._options = Object.assign(this._options, options); + } else { + this._options = options; + } + if (options.interactiveTypeOptions) { + // 更新交互类型配置 + this.interactiveTypeOptions = options.interactiveTypeOptions; + } + if (options.maxOperationRecords && options.maxOperationRecords > 0) { + this.opRecord.setMaxLen(options.maxOperationRecords); + } + this.emit('options-update', options); + } + + /** + * 注册图形对象模板 + * @param graphicTemplates + */ + registerGraphicTemplates(...graphicTemplates: GraphicTemplate[]) { + graphicTemplates.forEach((graphicTemplate) => { + this.graphicTemplateMap.set(graphicTemplate.type, graphicTemplate); + }); + } + + getGraphicTemplatesByType(type: string): GT { + const template = this.graphicTemplateMap.get(type); + if (!template) { + throw new Error(`不存在type=${type}的图形对象模板`); + } + return template as GT; + } + + /** + * 注册菜单 + * @param menu + */ + registerMenu(menu: ContextMenu) { + this.menuPlugin.registerMenu(menu); + } + + /** + * 使能websocket Stomp通信 + */ + enableWsStomp(options: StompCliOption) { + StompCli.new(options); + this.wsMsgBroker = new AppWsMsgBroker(this); + } + + /** + * 订阅websocket消息 + */ + subscribe(sub: AppStateSubscription) { + if (this.wsMsgBroker) { + // console.log('APP订阅', sub) + this.wsMsgBroker.subscribe(sub); + } else { + throw new Error('请先打开StompClient, 执行app.enableWebsocket()'); + } + } + /** + * 取消websocket订阅 + */ + unsubscribe(destination: string) { + if (this.wsMsgBroker) { + this.wsMsgBroker.unsbuscribe(destination); + } else { + throw new Error('请先执行enableWebsocket'); + } + } + + /** + * 处理websocket状态 + * @param graphicStates + */ + handleGraphicStates(graphicStates: GraphicState[]) { + graphicStates.forEach((state) => { + const list = this.queryStore.queryByIdOrCode(state.code); + if (list.length == 0) { + const template = this.getGraphicTemplatesByType(state.graphicType); + const g = template.new(); + g.loadState(state); + this.addGraphics(g); + } else { + list.forEach((g) => { + g.updateStates(state); + }); + } + }); + } + + /** + * 添加键盘监听器,如果是相同的按键,新注册的会覆盖旧的,当移除新的时,旧的自动生效 + * @param keyListeners + */ + addKeyboardListener(...keyListeners: KeyListener[]) { + keyListeners.forEach((keyListener) => + this.keyboardPlugin.addKeyListener(keyListener) + ); + } + + /** + * 移除键盘监听器 + * @param keyListeners + */ + removeKeyboardListener(...keyListeners: KeyListener[]) { + keyListeners.forEach((keyListener) => + this.keyboardPlugin.removeKeyListener(keyListener) + ); + } + + /** + * dom尺寸变更处理 + * @param domWidth canvas容器的宽 + * @param domHeight canvas容器的高 + */ + onDomResize(domWidth: number, domHeight: number) { + this.updateViewport(domWidth, domHeight); + } + + public get queryStore(): GraphicQueryStore { + return this.graphicStore; + } + + public get selectedGraphics(): JlGraphic[] { + return this.queryStore.getAllGraphics().filter((g) => g.selected); + } + + fireSelectedChange(graphic: JlGraphic) { + // console.log('通知选中变化', this.selecteds) + const select = graphic.selected; + this.emit('graphicselectedchange', graphic, select); + } + + /** + * 更新选中 + */ + updateSelected(...graphics: JlGraphic[]) { + this.selectedGraphics.forEach((graphic) => { + if (graphics.findIndex((g) => g.id === graphic.id) >= 0) { + return; + } + if (graphic.selected) { + graphic.updateSelected(false); + this.fireSelectedChange(graphic); + } + }); + graphics.forEach((graphic) => { + if (graphic.updateSelected(true)) { + this.fireSelectedChange(graphic); + } + }); + } + + /** + * 更新画布 + * @param param + */ + updateCanvas(param: ICanvasProperties) { + this.canvas.update(param); + } + + /** + * 加载图形,GraphicApp默认添加到无交互容器,DrawApp默认添加到交互容器,如需定制,提供选项配置 + * @param protos + * @param options 添加到可交互/不可交互容器选项配置 + */ + async loadGraphic(protos: GraphicData[]) { + for (const item of this.graphicTemplateMap) { + await item[1].loadAssets(); + } + // console.log('开始加载proto数据', protos); + // 加载数据到图形存储 + protos.forEach((proto) => { + const template = this.getGraphicTemplatesByType(proto.graphicType); + const g = template.new(); + g.loadData(proto); + this.addGraphics(g); + }); + // 加载数据关系 + this.graphicStore.getAllGraphics().forEach((g) => g.loadRelations()); + // 更新id生成器 + const max = + this.graphicStore + .getAllGraphics() + .filter((g) => !isNaN(parseInt(g.id))) + .map((g) => parseInt(g.id)) + .sort((a, b) => a - b) + .pop() ?? 0; + // console.log('最大值', max) + GraphicIdGenerator.initSerial(max); + // 加载完成通知 + this.emit('loadfinish'); + } + + /** + * 添加图形前处理 + * @param graphic + */ + beforeGraphicStore(graphic: JlGraphic): void { + const options = this.interactiveTypeOptions; + // 默认无交互 + graphic.eventMode = 'auto'; + if (options) { + if ( + options.interactiveGraphicTypeIncludes && + options.interactiveGraphicTypeIncludes.findIndex( + (type) => type === graphic.type + ) >= 0 + ) { + graphic.eventMode = 'static'; + } else if ( + options.interactiveGraphicTypeExcludes && + options.interactiveGraphicTypeExcludes.findIndex( + (type) => type === graphic.type + ) < 0 + ) { + graphic.eventMode = 'static'; + } + } + } + private doAddGraphics(graphic: JlGraphic): void { + this.beforeGraphicStore(graphic); + if (this.graphicStore.storeGraphics(graphic)) { + // cullable,默认设置剪裁,如果图形包围框不在屏幕内,则不渲染,增加效率用 + if (!this._options || this._options.cullable !== false) { + graphic.cullable = true; + } + if (graphic.eventMode == 'static' || graphic.eventMode == 'dynamic') { + // 添加为可交互 + // console.log(`type=${graphic.type}的图形添加到交互容器`); + this.canvas.addChild(graphic); + } else { + // 添加到不可交互容器 + // console.log(`type=${graphic.type}的图形添加到无交互容器`); + this.canvas.addNonInteractiveChild(graphic); + } + graphic.repaint(); + this.emit('graphicstored', graphic); + graphic.on('childselected', (child) => { + this.emit('graphicchildselectedchange', child, true); + }); + graphic.on('childunselected', (child) => { + this.emit('graphicchildselectedchange', child, false); + }); + } + } + + private doDeleteGraphics(graphic: JlGraphic): void { + // graphic可能是vue的Proxy对象,会导致canvas删除时因不是同一个对象而无法从画布移除 + const g = this.graphicStore.deleteGraphics(graphic); + if (g) { + // 从画布移除 + this.canvas.removeGraphic(g); + // 清除选中 + if (g.updateSelected(false)) { + this.fireSelectedChange(g); + } + // 对象删除处理 + g.onDelete(); + this.emit('graphicdeleted', g); + } + } + + /** + * 存储图形 + * @param graphics 图形对象 + */ + addGraphics(...graphics: JlGraphic[]) { + graphics.forEach((g) => this.doAddGraphics(g)); + } + /** + * 删除图形 + * @param graphics 图形对象 + */ + deleteGraphics(...graphics: JlGraphic[]) { + graphics.forEach((g) => this.doDeleteGraphics(g)); + } + + /** + * 检测并构建关系 + */ + detectRelations(): void { + this.graphicStore.getAllGraphics().forEach((g) => g.buildRelation()); + } + + /** + * 转换操作坐标点为画布坐标点 + * @param e 事件 + * @returns 画布坐标点 + */ + toCanvasCoordinates(p: Point): Point { + return this.viewport.toWorld(p); + } + + /** + * 获取当前缩放倍率 + */ + getViewportScaled(): number { + return this.viewport.scaled; + } + /** + * 视口中心坐标 + * @returns + */ + getViewportCenter(): Point { + return this.viewport.center; + } + /** + * 获取视口角落坐标 + * @returns + */ + getViewportCorner(): Point { + return this.viewport.corner; + } + + /** + * 注册交互插件,会替换旧的 + */ + registerInteractionPlugin(...plugins: InteractionPlugin[]): void { + plugins.forEach((plugin) => { + const old = this.interactionPluginMap.get(plugin.name); + if (old) { + console.warn(`已经存在name=${plugin.name}的交互插件,忽略此插件注册!`); + return; + } + this.interactionPluginMap.set(plugin.name, plugin); + }); + } + + /** + * 根据名称获取交互插件 + * @param name + * @returns + */ + interactionPlugin

(name: string): P { + const plugin = this.interactionPluginMap.get(name); + if (!plugin) { + throw new Error(`未找到name=${name}的交互插件`); + } + return plugin as P; + } + + /** + * 停止应用交互插件 + */ + pauseAppInteractionPlugins(): void { + this.interactionPluginMap.forEach((plugin) => { + if (plugin.isActive() && plugin._type === InteractionPluginType.App) { + this.doPauseInteractionPlugin(plugin); + } + }); + } + + private doPauseInteractionPlugin(plugin?: InteractionPlugin): void { + if (plugin && plugin.isActive()) { + plugin.pause(); + this.emit('interaction-plugin-pause', plugin); + } + } + + /** + * 移除交互插件 + */ + removeInteractionPlugin(plugin: InteractionPlugin) { + this.interactionPluginMap.delete(plugin.name); + } + + updateViewport(domWidth?: number, domHeight?: number): void { + let screenWidth = this.viewport.screenWidth; + let screenHeight = this.viewport.screenHeight; + if (domWidth) { + screenWidth = domWidth; + } + if (domHeight) { + screenHeight = domHeight; + } + const worldWidth = this.canvas._properties.width; + const worldHeight = this.canvas._properties.height; + this.app.resize(); + this.viewport.resize(screenWidth, screenHeight, worldWidth, worldHeight); + if (this.viewport.OOB().right) { + this.viewport.right = this.viewport.right + 1; + } else if (this.viewport.OOB().left) { + this.viewport.left = this.viewport.left - 1; + } else if (this.viewport.OOB().top) { + this.viewport.top = this.viewport.top - 1; + } else if (this.viewport.OOB().bottom) { + this.viewport.bottom = this.viewport.bottom + 1; + } + } + + /** + * 使图形居中显示(所有图形的外包围盒) + */ + makeGraphicCenterShow(...group: JlGraphic[]): void { + if (group.length > 0) { + const bounds0 = group[0].getBounds(); + let lx = bounds0.x; + let ly = bounds0.y; + let rx = bounds0.x + bounds0.width; + let ry = bounds0.y + bounds0.height; + if (group.length > 1) { + for (let i = 1; i < group.length; i++) { + const g = group[i]; + const bound = g.getBounds(); + if (bound.x < lx) { + lx = bound.x; + } + if (bound.y < ly) { + ly = bound.y; + } + const brx = bound.x + bound.width; + if (brx > rx) { + rx = brx; + } + const bry = bound.y + bound.height; + if (bry > ry) { + ry = bry; + } + } + } + const { x, y } = getRectangleCenter( + new Rectangle(lx, ly, rx - lx, ry - ly) + ); + const p = this.viewport.toWorld(x, y); + this.viewport.moveCenter(p.x, p.y); + } + } + + /** + * 销毁 + */ + destroy(): void { + console.log('销毁图形 APP'); + this.emit('destroy', this); + if (this.wsMsgBroker) { + this.wsMsgBroker.close(); + // if (!StompCli.hasAppMsgBroker()) { + // // 如果没有其他消息代理,关闭websocket Stomp客户端 + // StompCli.close(); + // } + } + this.interactionPluginMap.forEach((plugin) => { + plugin.pause(); + }); + this.canvas.destroy(true); + this.viewport.destroy(); + this.app.destroy(true, true); + document.body.style.overflow = 'auto'; + } +} diff --git a/src/jl-graphic/app/index.ts b/src/jl-graphic/app/index.ts new file mode 100644 index 0000000..9e8a44a --- /dev/null +++ b/src/jl-graphic/app/index.ts @@ -0,0 +1,2 @@ +export * from './JlGraphicApp'; +export * from './JlDrawApp'; diff --git a/src/jl-graphic/core/GraphicRelation.ts b/src/jl-graphic/core/GraphicRelation.ts new file mode 100644 index 0000000..88375d5 --- /dev/null +++ b/src/jl-graphic/core/GraphicRelation.ts @@ -0,0 +1,185 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { GraphicApp } from '../app/JlGraphicApp'; +import { JlGraphic } from './JlGraphic'; + +/** + * 图形关系数据 + */ +export class GraphicRelationParam { + g: JlGraphic; + param: any; + constructor(g: JlGraphic, param: any = null) { + this.g = g; + this.param = param; + } + isTheGraphic(g: JlGraphic): boolean { + return this.g.id === g.id; + } + getGraphic(): G { + return this.g as G; + } + getParam

(): P { + return this.param as P; + } + equals(other: GraphicRelationParam): boolean { + return this.isTheGraphic(other.g) && this.param === other.param; + } +} +/** + * 图形关系 + */ +export class GraphicRelation { + rp1: GraphicRelationParam; + rp2: GraphicRelationParam; + constructor(rp1: GraphicRelationParam, rp2: GraphicRelationParam) { + this.rp1 = rp1; + this.rp2 = rp2; + } + + contains(g: JlGraphic): boolean { + return this.rp1.isTheGraphic(g) || this.rp2.isTheGraphic(g); + } + + /** + * 获取给定图形的关系参数 + * @param g + * @returns + */ + getRelationParam(g: JlGraphic): GraphicRelationParam { + if (!this.contains(g)) { + throw new Error( + `图形关系${this.rp1.g.id}-${this.rp2.g.id}中不包含给定图形${g.id}` + ); + } + if (this.rp1.isTheGraphic(g)) { + return this.rp1; + } else { + return this.rp2; + } + } + /** + * 获取关联的另一个图形的关系参数 + * @param g + * @returns + */ + getOtherRelationParam(g: JlGraphic): GraphicRelationParam { + if (!this.contains(g)) { + throw new Error( + `图形关系${this.rp1.g.id}-${this.rp2.g.id}中不包含给定图形${g.id}` + ); + } + if (this.rp1.isTheGraphic(g)) { + return this.rp2; + } else { + return this.rp1; + } + } + /** + * 获取关联的另一个图形对象 + * @param g + * @returns graphic + */ + getOtherGraphic(g: JlGraphic): G { + return this.getOtherRelationParam(g).g as G; + } + + equals(orp1: GraphicRelationParam, orp2: GraphicRelationParam): boolean { + if (this.rp1.isTheGraphic(orp1.g)) { + return this.rp1.equals(orp1) && this.rp2.equals(orp2); + } else if (this.rp1.isTheGraphic(orp2.g)) { + return this.rp1.equals(orp2) && this.rp2.equals(orp1); + } + return false; + } + + isEqualOther(other: GraphicRelation): boolean { + return this.equals(other.rp1, other.rp2); + } +} + +/** + * 图形关系管理 + */ +export class RelationManage { + app: GraphicApp; + relations: GraphicRelation[] = []; + constructor(app: GraphicApp) { + this.app = app; + } + + isContainsRelation( + rp1: GraphicRelationParam, + rp2: GraphicRelationParam + ): boolean { + const relation = this.relations.find((relation) => + relation.equals(rp1, rp2) + ); + return !!relation; + } + addRelation( + rp1: GraphicRelationParam | JlGraphic, + rp2: GraphicRelationParam | JlGraphic + ): void { + if (!(rp1 instanceof GraphicRelationParam)) { + rp1 = new GraphicRelationParam(rp1); + } + if (!(rp2 instanceof GraphicRelationParam)) { + rp2 = new GraphicRelationParam(rp2); + } + if (!this.isContainsRelation(rp1, rp2)) { + const relation = new GraphicRelation(rp1, rp2); + this.relations.push(relation); + } + } + + /** + * 获取图形的所有关系 + * @param g + * @returns + */ + getRelationsOfGraphic(g: JlGraphic): GraphicRelation[] { + return this.relations.filter((rl) => rl.contains(g)); + } + + /** + * 获取指定图形的指定关系图形类型的所有关系 + * @param g 指定图形 + * @param type 关联图形的类型 + * @returns + */ + getRelationsOfGraphicAndOtherType( + g: JlGraphic, + type: string + ): GraphicRelation[] { + return this.relations.filter( + (rl) => rl.contains(g) && rl.getOtherGraphic(g).type === type + ); + } + + /** + * 删除关系 + * @param relation + */ + private deleteRelation(relation: GraphicRelation): void { + const index = this.relations.findIndex((rl) => rl.isEqualOther(relation)); + if (index >= 0) { + this.relations.splice(index, 1); + } + } + /** + * 删除指定图形的所有关系 + * @param g + */ + deleteRelationOfGraphic(g: JlGraphic): void { + const relations = this.getRelationsOfGraphic(g); + relations.forEach((rl) => this.deleteRelation(rl)); + } + /** + * 删除指定图形的所有关系 + * @param g + */ + deleteRelationOfGraphicAndOtherType(g: JlGraphic, type: string): void { + const relations = this.getRelationsOfGraphicAndOtherType(g, type); + relations.forEach((rl) => this.deleteRelation(rl)); + } +} diff --git a/src/jl-graphic/core/GraphicStore.ts b/src/jl-graphic/core/GraphicStore.ts new file mode 100644 index 0000000..979bd20 --- /dev/null +++ b/src/jl-graphic/core/GraphicStore.ts @@ -0,0 +1,185 @@ +import { GraphicApp } from '../app/JlGraphicApp'; +import { RelationManage } from './GraphicRelation'; +import { JlGraphic } from './JlGraphic'; + +export interface GraphicQueryStore { + /** + * 获取所有图形对象 + */ + getAllGraphics(): JlGraphic[]; + /** + * 根据id获取图形 + */ + queryById(id: string): T; + /** + * 根据id模糊查询图形 + * @param id + */ + queryByIdAmbiguous(id: string): JlGraphic[]; + + /** + * 根据类型获取图形列表 + */ + queryByType(type: string): T[]; + /** + * 根据code查询 + * @param code + */ + queryByCode(code: string): JlGraphic[] | undefined; + /** + * 根据code模糊查询图形 + * @param code + * @param type + */ + queryByCodeAmbiguous(code: string): JlGraphic[]; + /** + * 根据id或code查询图形 + * @param v + */ + queryByIdOrCode(v: string): JlGraphic[]; + /** + * 根据code和类型获取图形 + * @param code + * @param type + */ + queryByCodeAndType( + code: string, + type: string + ): T | undefined; + /** + * 根据code和类型模糊查询图形 + * @param code + * @param type + */ + queryByCodeAndTypeAmbiguous( + code: string, + type: string + ): T[]; +} + +/** + * 图形存储 + */ +export class GraphicStore implements GraphicQueryStore { + app: GraphicApp; + store: Map; + relationManage: RelationManage; + constructor(app: GraphicApp) { + this.app = app; + this.store = new Map(); + this.relationManage = new RelationManage(app); + } + /** + * 获取所有图形对象 + */ + getAllGraphics(): JlGraphic[] { + return [...this.store.values()]; + } + queryById(id: string): T { + const graphic = this.store.get(id) as T; + if (!graphic) throw Error(`未找到id为 [${id}] 的图形.`); + return this.store.get(id) as T; + } + queryByIdAmbiguous(id: string): JlGraphic[] { + const list: JlGraphic[] = []; + this.store.forEach((g) => { + if (g.id.search(id) >= 0) { + list.push(g); + } + }); + return list; + } + queryByType(type: string): T[] { + const list: T[] = []; + this.store.forEach((g) => { + if (g.type === type) { + list.push(g as T); + } + }); + return list; + } + queryByCode(code: string): JlGraphic[] | undefined { + const list: JlGraphic[] = []; + this.store.forEach((g) => { + if (g.code === code) { + list.push(g); + } + }); + return list; + } + queryByCodeAmbiguous(code: string): JlGraphic[] { + const list: JlGraphic[] = []; + this.store.forEach((g) => { + if (g.code.search(code) >= 0) { + list.push(g); + } + }); + return list; + } + queryByIdOrCode(s: string): JlGraphic[] { + const list: JlGraphic[] = []; + this.store.forEach((g) => { + if (g.isIdOrCode(s)) { + list.push(g); + } + }); + return list; + } + queryByCodeAndType( + code: string, + type: string + ): T | undefined { + for (const item of this.store.values()) { + if (item.code === code && item.type === type) { + return item as T; + } + } + } + queryByCodeAndTypeAmbiguous( + code: string, + type: string + ): T[] { + const list: T[] = []; + this.store.forEach((g) => { + if (g.type === type && g.code.search(code) >= 0) { + list.push(g as T); + } + }); + return list; + } + + /** + * 存储图形对象 + * @param graphics 要存储的图形 + */ + storeGraphics(graphic: JlGraphic): boolean { + if (!graphic.id || graphic.id.trim() === '') { + throw new Error(`存储图形对象异常: id为空, ${graphic}`); + } + if (this.store.has(graphic.id)) { + // 已经存在 + const exist = this.store.get(graphic.id); + console.error(`已经存在id=${graphic.id}的设备${exist}`); + return false; + } else { + this.store.set(graphic.id, graphic); + graphic.queryStore = this; + graphic.relationManage = this.relationManage; + return true; + } + } + /** + * 删除图形 + * @param graph 要删除的图形 + */ + deleteGraphics(graphic: JlGraphic): JlGraphic | undefined { + const id = graphic.id; + const remove = this.store.get(id); + if (remove) { + this.store.delete(id); + // 删除图形关系 + this.relationManage.deleteRelationOfGraphic(remove); + } + return remove; + } +} diff --git a/src/jl-graphic/core/IdGenerator.ts b/src/jl-graphic/core/IdGenerator.ts new file mode 100644 index 0000000..131f699 --- /dev/null +++ b/src/jl-graphic/core/IdGenerator.ts @@ -0,0 +1,28 @@ +/** + * ID生成器 + */ +export class IdGenerator { + serial = 0; + type: string; + + constructor(type: string) { + this.type = type; + } + + next(): string { + ++this.serial; + // console.log(this.getType() + this.serial) + return this.getType() + this.serial; + } + + getType(): string { + return this.type; + } + + initSerial(serial: number): void { + // console.log(serial) + this.serial = serial; + } +} + +export const GraphicIdGenerator: IdGenerator = new IdGenerator(''); diff --git a/src/jl-graphic/core/JlGraphic.ts b/src/jl-graphic/core/JlGraphic.ts new file mode 100644 index 0000000..7ed967a --- /dev/null +++ b/src/jl-graphic/core/JlGraphic.ts @@ -0,0 +1,1015 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/no-empty-function */ +import { Viewport } from 'pixi-viewport'; +import { + Container, + DisplayObject, + Graphics, + IPointData, + Point, + Rectangle, +} from 'pixi.js'; +import { AppConsts, JlCanvas } from '../app'; +import { + convertRectangleToPolygonPoints, + recursiveChildren, + recursiveFindChild, + recursiveFindParent, + recursiveParents, +} from '../utils'; +import { GraphicRelation, RelationManage } from './GraphicRelation'; +import { GraphicQueryStore } from './GraphicStore'; +import { GraphicIdGenerator } from './IdGenerator'; + +//基础图形对象扩展 +DisplayObject.prototype._selectable = false; //是否可选中 +DisplayObject.prototype._selected = false; +DisplayObject.prototype._childEdit = false; +DisplayObject.prototype._transformSave = false; +DisplayObject.prototype._assistantAppendMap = null; +DisplayObject.prototype._draggable = false; +DisplayObject.prototype._shiftStartPoint = null; +DisplayObject.prototype._shiftLastPoint = null; +DisplayObject.prototype._scalable = false; +DisplayObject.prototype._keepAspectRatio = true; +DisplayObject.prototype._rotatable = false; +Object.defineProperties(DisplayObject.prototype, { + assistantAppendMap: { + get() { + if (this._assistantAppendMap == null) { + this._assistantAppendMap = new Map(); + } + return this._assistantAppendMap; + }, + }, + selectable: { + get(): boolean { + return this._selectable; + }, + set(value: boolean): void { + this._selectable = value; + }, + }, + selected: { + get(): boolean { + return this._selected; + }, + set(v) { + this._selected = v; + }, + }, + childEdit: { + get() { + return this._childEdit; + }, + set(v) { + this._childEdit = v; + }, + }, + transformSave: { + get() { + return this._transformSave; + }, + set(v) { + this._transformSave = v; + }, + }, + draggable: { + get(): boolean { + return this._draggable; + }, + set(v) { + this._draggable = v; + }, + }, + shiftStartPoint: { + get() { + return this._shiftStartPoint; + }, + set(v) { + this._shiftStartPoint = v; + }, + }, + shiftLastPoint: { + get() { + return this._shiftLastPoint; + }, + set(v) { + this._shiftLastPoint = v; + }, + }, + scalable: { + get() { + return this._scalable; + }, + set(v) { + this._scalable = v; + }, + }, + keepAspectRatio: { + get(): boolean { + return this._keepAspectRatio; + }, + set(v) { + this._keepAspectRatio = v; + }, + }, + rotatable: { + get() { + return this._rotatable; + }, + set(v) { + this._rotatable = v; + }, + }, + worldAngle: { + get() { + let angle = this.angle; + let parent = this.parent; + while (parent != undefined && parent != null) { + angle += parent.angle; + parent = parent.parent; + } + angle = angle % 360; + if (angle > 180) { + angle = angle - 360; + } + return angle; + }, + }, +}); +DisplayObject.prototype.getAllParentScaled = + function getAllParentScaled(): Point { + const scaled = new Point(1, 1); + recursiveParents(this, (parent) => { + scaled.x *= parent.scale.x; + scaled.y *= parent.scale.y; + }); + return scaled; + }; +DisplayObject.prototype.getPositionOnCanvas = + function getPositionOnCanvas(): Point { + if (this.parent.isCanvas()) { + return this.position; + } else { + return this.parent.localToCanvasPoint(this.position); + } + }; +DisplayObject.prototype.updatePositionByCanvasPosition = + function updatePositionByCanvasPosition(p: IPointData): void { + if (this.parent.isCanvas()) { + this.position.copyFrom(p); + } else { + const localPosition = this.parent.canvasToLocalPoint(p); + this.position.copyFrom(localPosition); + } + }; +DisplayObject.prototype.saveTransform = function saveTransform() { + return GraphicTransform.fromObject(this); +}; +DisplayObject.prototype.loadTransform = function loadTransform( + transfrom: GraphicTransform +) { + this.position.copyFrom(transfrom.position); + this.scale.copyFrom(transfrom.scale); + this.rotation = transfrom.rotation; + this.skew.copyFrom(transfrom.skew); +}; +DisplayObject.prototype.isChild = function isChild( + obj: DisplayObject +): boolean { + return recursiveFindChild(this as Container, (child) => child == obj) != null; +}; +DisplayObject.prototype.isParent = function isParent( + obj: DisplayObject +): boolean { + return recursiveFindParent(this, (parent) => parent == obj) != null; +}; +DisplayObject.prototype.isAssistantAppend = + function isAssistantAppend(): boolean { + return ( + recursiveFindParent(this, (parent) => { + return parent.name === AppConsts.AssistantAppendsName; + }) != null + ); + }; +DisplayObject.prototype.addAssistantAppend = function addAssistantAppend< + D extends DisplayObject +>(...appends: D[]): void { + appends.forEach((append) => { + if (append.name == null || append.name.trim() == '') { + throw new Error('辅助附加name不能为空'); + } + this.assistantAppendMap.set(append.name, append); + this.getCanvas().addAssistantAppends(append); + }); +}; +DisplayObject.prototype.getAssistantAppend = function getAssistantAppend< + D extends DisplayObject +>(name: string): D | undefined { + return this.assistantAppendMap.get(name) as D; +}; +DisplayObject.prototype.removeAssistantAppend = function removeAssistantAppend( + ...appends: DisplayObject[] +): void { + appends.forEach((append) => { + if (append.name) { + this.removeAssistantAppendByName(append.name); + } + }); +}; +DisplayObject.prototype.removeAssistantAppendByName = + function removeAssistantAppendByName(...names: string[]): void { + names.forEach((name) => { + const append = this.getAssistantAppend(name); + if (append) { + this.getCanvas().removeAssistantAppends(append); + this.assistantAppendMap.delete(name); + append.destroy(); + } + }); + }; +DisplayObject.prototype.removeAllAssistantAppend = + function removeAllAssistantAppend(): void { + if (this._assistantAppendMap != null) { + this.assistantAppendMap.forEach((append) => { + append.getCanvas().removeAssistantAppends(append); + }); + this.assistantAppendMap.clear(); + } + }; + +DisplayObject.prototype.isGraphic = function isGraphic() { + return Object.hasOwn(this, '__JlGraphic'); +}; +DisplayObject.prototype.getGraphic = function getGraphic< + G extends JlGraphic +>(): G | null { + let graphic = this as DisplayObject; + while (graphic && !Object.hasOwn(graphic, '__JlGraphic')) { + graphic = graphic.parent; + } + if (graphic) { + return graphic as G; + } + return null; +}; +DisplayObject.prototype.isGraphicChild = function isGraphicChild() { + const g = this.getGraphic(); + return g != null && !this.isAssistantAppend() && g.isChild(this); +}; +DisplayObject.prototype.onAddToCanvas = function onAddToCanvas() {}; +DisplayObject.prototype.onRemoveFromCanvas = function onRemoveFromCanvas() {}; +DisplayObject.prototype.isInCanvas = function isInCanvas(): boolean { + let graphic = this as DisplayObject; + while (graphic && !Object.hasOwn(graphic, '__JlCanvas')) { + graphic = graphic.parent; + } + if (graphic) { + return true; + } + return false; +}; +DisplayObject.prototype.getCanvas = function getCanvas() { + let graphic = this as DisplayObject; + while (graphic && !Object.hasOwn(graphic, '__JlCanvas')) { + graphic = graphic.parent; + } + if (graphic) { + return graphic as JlCanvas; + } + throw new Error(`图形${this.name}不在画布中`); +}; +DisplayObject.prototype.isCanvas = function isCanvas(): boolean { + return Object.hasOwn(this, '__JlCanvas'); +}; +DisplayObject.prototype.getViewport = function getViewport() { + const canvas = this.getCanvas(); + return canvas.parent as Viewport; +}; +DisplayObject.prototype.getGraphicApp = function getGraphicApp() { + const canvas = this.getCanvas(); + return canvas.app; +}; +DisplayObject.prototype.localToCanvasPoint = function localToCanvasPoint( + p: IPointData +): Point { + return this.getViewport().toWorld(this.toGlobal(p)); +}; +DisplayObject.prototype.localToCanvasPoints = function localToCanvasPoints( + ...points: IPointData[] +): Point[] { + return points.map((p) => this.localToCanvasPoint(p)); +}; +DisplayObject.prototype.canvasToLocalPoint = function canvasToLocalPoint( + p: IPointData +): Point { + return this.toLocal(this.getViewport().toScreen(p)); +}; +DisplayObject.prototype.canvasToLocalPoints = function canvasToLocalPoints( + ...points: IPointData[] +): Point[] { + return points.map((p) => this.canvasToLocalPoint(p)); +}; +DisplayObject.prototype.localToScreenPoint = function localToScreenPoint( + p: IPointData +): Point { + return this.toGlobal(p); +}; +DisplayObject.prototype.localToScreenPoints = function localToScreenPoints( + ...points: IPointData[] +): Point[] { + return points.map((p) => this.toGlobal(p)); +}; +DisplayObject.prototype.screenToLocalPoint = function screenToLocalPoint( + p: IPointData +): Point { + return this.toLocal(p); +}; +DisplayObject.prototype.screenToLocalPoints = function screenToLocalPoints( + ...points: IPointData[] +): Point[] { + return points.map((p) => this.toLocal(p)); +}; + +DisplayObject.prototype.localBoundsToCanvasPoints = + function localBoundsToCanvasPoints() { + const rect = this.getLocalBounds(); + const pps = convertRectangleToPolygonPoints(rect); + return this.localToCanvasPoints(...pps); + }; + +// 扩展pixijs图形对象,添加自定义绘制贝塞尔曲线,可自定义分段数 +Graphics.prototype.drawBezierCurve = function drawBezierCurve( + p1: IPointData, + p2: IPointData, + cp1: IPointData, + cp2: IPointData, + segmentsCount: number +): Graphics { + const fromX = p1.x; + const fromY = p1.y; + const n = segmentsCount; + let dt = 0; + let dt2 = 0; + let dt3 = 0; + let t2 = 0; + let t3 = 0; + const cpX = cp1.x; + const cpY = cp1.y; + const cpX2 = cp2.x; + const cpY2 = cp2.y; + const toX = p2.x; + const toY = p2.y; + this.moveTo(p1.x, p1.y); + for (let i = 1, j = 0; i <= n; ++i) { + j = i / n; + dt = 1 - j; + dt2 = dt * dt; + dt3 = dt2 * dt; + t2 = j * j; + t3 = t2 * j; + const px = dt3 * fromX + 3 * dt2 * j * cpX + 3 * dt * t2 * cpX2 + t3 * toX; + const py = dt3 * fromY + 3 * dt2 * j * cpY + 3 * dt * t2 * cpY2 + t3 * toY; + this.lineTo(px, py); + } + return this; +}; + +export interface IGraphicTransform { + position: IPointData; + scale: IPointData; + rotation: number; + skew: IPointData; +} + +/** + * 图形变换数据 + */ +export class GraphicTransform { + position: IPointData; + scale: IPointData; + rotation: number; + skew: IPointData; + + constructor( + position: IPointData, + scale: IPointData, + rotation: number, + skew: IPointData + ) { + this.position = position; + this.scale = scale; + this.rotation = rotation; + this.skew = skew; + } + static default(): GraphicTransform { + return new GraphicTransform( + new Point(0, 0), + new Point(1, 1), + 0, + new Point(0, 0) + ); + } + static fromObject(obj: DisplayObject): GraphicTransform { + return new GraphicTransform( + obj.position.clone(), + obj.scale.clone(), + obj.rotation, + obj.skew.clone() + ); + } + static from(transform: IGraphicTransform | undefined): GraphicTransform { + if (transform) { + return new GraphicTransform( + new Point(transform.position.x, transform.position.y), + new Point(transform.scale.x, transform.scale.y), + transform.rotation, + new Point(transform.skew.x, transform.skew.y) + ); + } + return GraphicTransform.default(); + } +} + +export interface IChildTransform { + name: string; + transform: IGraphicTransform; +} + +/** + * 图形子元素变换 + */ +export class ChildTransform { + name: string; + transform: GraphicTransform; + constructor(name: string, transform: GraphicTransform) { + this.name = name; + this.transform = transform; + } + static fromChild(child: DisplayObject): ChildTransform { + if ( + child.name == null || + child.name == undefined || + child.name.trim() == '' + ) { + throw new Error( + `图形type=${ + child.getGraphic()?.type + }的子元素${child}name为空,但设置为需要保存变换数据` + ); + } + return new ChildTransform(child.name, GraphicTransform.fromObject(child)); + } + static from(ct: IChildTransform): ChildTransform { + return new ChildTransform(ct.name, GraphicTransform.from(ct.transform)); + } +} + +/** + * 图形数据 + */ +export interface GraphicData { + get id(): string; // 图形id + set id(v: string); + get graphicType(): string; // 图形类型 + set graphicType(v: string); + get transform(): GraphicTransform; // + set transform(v: GraphicTransform); + get childTransforms(): ChildTransform[] | undefined; // + set childTransforms(v: ChildTransform[] | undefined); + + /** + * 克隆消息 + */ + clone(): GraphicData; + /** + * 从给定数据拷贝 + * @param data + */ + copyFrom(data: GraphicData): void; + /** + * 是否相等 + * @param other + */ + eq(other: GraphicData): boolean; +} + +/** + * 图形状态 + */ +export interface GraphicState { + get code(): string; // 业务标识 + get graphicType(): string; // 图形类型 + /** + * 克隆消息 + */ + clone(): GraphicState; + /** + * 从给定数据拷贝 + * @param data + */ + copyFrom(data: GraphicState): void; + /** + * 是否相等 + * @param data + */ + eq(data: GraphicState): boolean; +} + +export interface GraphicAnimationOptions { + name: string; + + run?: (dt: number) => void; +} + +export class GraphicAnimation { + options: GraphicAnimationOptions; + _running: boolean; + /** + * 倍速 + */ + _xSpeed: number; + constructor(options: GraphicAnimationOptions) { + this.options = options; + this._running = false; + this._xSpeed = 1; + } + + static init(options: GraphicAnimationOptions) { + return new GraphicAnimation(options); + } + + pause(): GraphicAnimation { + this._running = false; + return this; + } + resume(): GraphicAnimation { + this._running = true; + return this; + } + + public get name(): string { + return this.options.name; + } + + public get running(): boolean { + return this._running; + } + + public get xSpeed(): number { + return this._xSpeed; + } + + public set xSpeed(v: number) { + this._xSpeed = v; + } + + run(dt: number): GraphicAnimation { + if (this.options.run) { + this.options.run(dt * this.xSpeed); + } + return this; + } +} + +/** + * 图形对象基类 + */ +export abstract class JlGraphic extends Container { + readonly __JlGraphic = true as const; + readonly type: string; // 图形类型 + private _id = ''; // 图形的唯一标识,不具有业务意义,唯一,不可重复,可用做图形数据关联。 + private _code = ''; // 业务编号/名称,用于标识图形对象,具有业务意义 + _datas?: GraphicData; // 图形数据 + _states?: GraphicState; // 图形状态数据 + private _relationManage?: RelationManage; // 图形关系管理 + private _queryStore?: GraphicQueryStore; // 图形对象查询仓库 + + constructor(type: string) { + super(); + this.type = type; + this.draggable = false; + this.filters; + } + + /** + * 添加图形动画,只有在画布上才能添加 + * @param animation + */ + addAnimation(animation: GraphicAnimation): void { + const app = this.getGraphicApp(); + app.animationManager.registerAnimation(this, animation); + } + removeAnimation(name: string): void { + const app = this.getGraphicApp(); + app.animationManager.unregisterAnimation(this, name); + } + animation(name: string): GraphicAnimation | undefined { + const app = this.getGraphicApp(); + return app.animationManager.animation(this, name); + } + removeAllAnimation(): void { + const app = this.getGraphicApp(); + app.animationManager.unregisterGraphicAnimations(this); + } + + /** + * 更新选中状态 + * @param selected + * @returns 是否更新 + */ + updateSelected(selected: boolean): boolean { + if (this.selected !== selected) { + this.selected = selected; + this.fireSelected(); + return true; + } + return false; + } + + invertSelected() { + this.selected = !this.selected; + this.fireSelected(); + } + + fireSelected() { + if (this.selected) { + this.emit('selected', this); + } else { + this.exitChildEdit(); + this.removeAllChildSelected(); + this.emit('unselected', this); + } + } + + hasSelectedChilds(): boolean { + return ( + recursiveFindChild(this, (child) => { + if (child.selected) { + return true; + } + return false; + }) != null + ); + } + setChildSelected(child: DisplayObject): boolean { + if (child.isGraphicChild() && child.selectable) { + this.removeAllChildSelected(); + child.selected = true; + this.fireChildSelected(child); + } + return false; + } + invertChildSelected(child: DisplayObject): boolean { + if (child.isGraphicChild() && child.selectable) { + child.selected = !child.selected; + this.fireChildSelected(child); + } + return false; + } + removeAllChildSelected() { + recursiveChildren(this, (child) => { + if (child.selected) { + child.selected = false; + this.fireChildSelected(child); + } + }); + } + fireChildSelected(child: DisplayObject) { + if (child.selected) { + this.emit('childselected', child); + } else { + this.emit('childunselected', child); + } + } + exitChildEdit() { + this.childEdit = false; + this.removeAllChildSelected(); + } + + /** + * 是否此对象id/code + */ + isIdOrCode(s: string): boolean { + return this.id === s || this.code === s; + } + + /** + * 获取图形id,如果图形数据对象存在,则返回图形数据对象id + */ + public get id(): string { + if (this._datas) { + return this._datas.id; + } + return this._id; + } + /** + * 设置图形id,如果图形数据存在,则同时设置图形数据id + */ + public set id(v: string) { + this._id = v; + if (this._datas) { + this._datas.id = v; + } + } + /** + * 获取图形业务code,如果业务code在图形数据或图形状态中,则需要重写此方法 + */ + public get code(): string { + return this._code; + } + /** + * 设置图形业务code,如果业务code在图形数据或图形状态中,则需要重写此方法 + */ + public set code(v: string) { + this._code = v; + } + + getDatas(): D { + if (this._datas) { + return this._datas as D; + } + throw new Error(`id=${this.id},type=${this.type}的图形没有数据`); + } + + getStates(): S { + if (this._states) { + return this._states as S; + } + throw new Error(`id=${this.id},type=${this.type}的的图形没有状态`); + } + + public get queryStore(): GraphicQueryStore { + if (this._queryStore) { + return this._queryStore; + } + throw new Error(`type=${this.type}的图形没有QueryStore`); + } + + public set queryStore(v: GraphicQueryStore) { + this._queryStore = v; + } + + public get relationManage(): RelationManage { + if (this._relationManage) { + return this._relationManage; + } + throw new Error(`type=${this.type}的图形没有关系管理`); + } + + public set relationManage(v: RelationManage) { + this._relationManage = v; + } + + /** + * 构建图形关系 + * @param g + */ + buildRelation() {} + + /** + * 从数据加载恢复图形关系 + */ + loadRelations() {} + + /** + * 获取当前图形的所有图形关系 + * @returns + */ + getAllRelations(): GraphicRelation[] { + return this.relationManage.getRelationsOfGraphic(this); + } + /** + * 获取当前图形的所有指定类型图形关系 + * @param type + * @returns + */ + queryRelationByType(type: string): GraphicRelation[] { + return this.relationManage.getRelationsOfGraphicAndOtherType(this, type); + } + /** + * 删除当前图形关联的指定类型的关系 + * @param type + */ + deleteRelationByType(type: string): void { + this.relationManage.deleteRelationOfGraphicAndOtherType(this, type); + } + + /** + * 构建并保存关系数据到datas中 + */ + saveRelations(): void {} + /** + * 保存数据,复制,非原始数据 + * @returns + */ + saveData(): D { + this.getDatas().graphicType = this.type; + this.getDatas().transform = GraphicTransform.fromObject(this); + this.getDatas().childTransforms = this.buildChildTransforms(); + this.saveRelations(); + return this.getDatas().clone() as D; + } + /** + * 构建子元素变换列表 + * @returns + */ + private buildChildTransforms(): ChildTransform[] { + const childTransforms: ChildTransform[] = []; + recursiveChildren(this, (child) => { + if (child.transformSave) { + childTransforms.push(ChildTransform.fromChild(child)); + } + }); + return childTransforms; + } + + /** + * 加载数据 + * @param data + */ + loadData(data: GraphicData) { + if (data.graphicType !== this.type) { + throw new Error( + `不同的图形类型,请检查数据是否正常: data.graphicType="${data.graphicType}, type="${this.type}` + ); + } + this._datas = data; + this.loadTransformFrom(data); + } + + private loadTransformFrom(data: GraphicData) { + if (data.transform) { + this.loadTransform(data.transform); + } + if (data.childTransforms) { + data.childTransforms.forEach((ct) => { + const child = this.getChildByName(ct.name, true); + if (child) { + child.loadTransform(ct.transform); + } + }); + } + } + /** + * 更新图形数据 + * @param data + * @returns + */ + updateData(data: GraphicData): boolean { + let update = false; + if (!this.getDatas().eq(data)) { + update = true; + const old = this.getDatas().clone(); + this.getDatas().copyFrom(data); + this.onDataChange(data, old); + this.loadTransformFrom(data); + this.emit('dataupdate', this.getDatas(), old); + this.repaint(); + } + return update; + } + /** + * 图形数据更新 + */ + onDataChange(newVal: GraphicData, old?: GraphicData): void {} + + /** + * 加载状态 + * @param state + */ + loadState(state: GraphicState) { + if (state.graphicType !== this.type) { + throw new Error( + `不同的图形类型,请检查数据是否正常: state.graphicType="${state.graphicType}, type="${this.type}` + ); + } + this._states = state; + } + /** + * 更新状态 + * @param state + * @returns + */ + updateStates(state: GraphicState): boolean { + let stateChange = false; + if (!this.getStates().eq(state)) { + // 判断并更新状态,默认状态 + const old = this.getStates().clone(); + this.getStates().copyFrom(state); + this.onStateChange(state, old); + stateChange = true; + this.emit('stateupdate', this.getStates(), old); + this.repaint(); + } + return stateChange; + } + /** + * 图形状态更新处理 + */ + onStateChange(newVal: GraphicState, old?: GraphicState): void {} + + repaint(): void { + this.doRepaint(); + this.emit('repaint', this); + } + + /** + * 处理重绘逻辑 + */ + abstract doRepaint(): void; + + /** + * 处理删除逻辑 + */ + onDelete(): void { + this.removeAllAssistantAppend(); + this.removeAllListeners(); + recursiveChildren(this, (child) => child.removeAllAssistantAppend()); + } + + /** + * 框选检测,默认取图形包围盒判定,若需要精细判定-子类重写此方法 + * @param box + * @returns + */ + boxIntersectCheck(box: Rectangle): boolean { + return box.intersects(this.getLocalBounds(), this.localTransform); + } +} + +export type CreateData = () => GraphicData; +export type CreateState = () => GraphicState; + +export interface IGraphicTemplateOptions { + dataTemplate?: GraphicData; + stateTemplate?: GraphicState; +} + +/** + * 图形对象模板 + */ +export abstract class JlGraphicTemplate { + readonly type: string; + options: IGraphicTemplateOptions; + + constructor(type: string, options: IGraphicTemplateOptions) { + this.type = type; + this.options = options; + } + + get datas(): GraphicData { + if (this.options.dataTemplate) { + return this.options.dataTemplate.clone(); + } + throw new Error(`type=${this.type}的图形模板没有数据模板`); + } + + get states(): GraphicState { + if (this.options.stateTemplate) { + return this.options.stateTemplate.clone(); + } + throw new Error(`type=${this.type}的图形模板没有状态模板`); + } + + // getDataCreator(): T { + // return this.options.dataCreator as T; + // } + // getStateCreator(): T { + // return this.options.stateCreator as T; + // } + + /** + * 初始化一个新的图形对象 + */ + abstract new(): G; + /** + * 加载图形对象需要用到的资源 + */ + async loadAssets(): Promise {} + + /** + * 克隆图形对象 + * @param graphic + * @returns + */ + clone(graphic: G): G { + const g = this.new(); + if (graphic._datas) { + // 数据克隆 + const datas = graphic.saveData(); + g.loadData(datas); + } + if (graphic._states) { + // 状态克隆 + const state = graphic.getStates().clone(); + g.loadState(state); + } + g.id = GraphicIdGenerator.next(); + return g; + } +} + +export type GraphicTemplate = JlGraphicTemplate; diff --git a/src/jl-graphic/core/index.ts b/src/jl-graphic/core/index.ts new file mode 100644 index 0000000..742c1e9 --- /dev/null +++ b/src/jl-graphic/core/index.ts @@ -0,0 +1,4 @@ +export * from './JlGraphic'; +export * from './IdGenerator'; +export * from './GraphicRelation'; +export * from './GraphicStore'; diff --git a/src/jl-graphic/global.d.ts b/src/jl-graphic/global.d.ts new file mode 100644 index 0000000..a70a5f9 --- /dev/null +++ b/src/jl-graphic/global.d.ts @@ -0,0 +1,158 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +declare namespace GlobalMixins { + type JlCanvasType = import('./app').JlCanvas; + type CanvasProperties = import('./app').ICanvasProperties; + type GraphicApp = import('./app').GraphicApp; + type JlGraphicType = import('./core').JlGraphic; + type GraphicData = import('./core').GraphicData; + type GraphicState = import('./core').GraphicState; + type GraphicTransform = import('./core').GraphicTransform; + type GraphicTransformEvent = import('./plugins').GraphicTransformEvent; + type BoundsGraphic = import('./plugins').BoundsGraphic; + type IPointDataType = import('pixi.js').IPointData; + type PointType = import('pixi.js').Point; + type FederatedMouseEvent = import('pixi.js').FederatedMouseEvent; + type DisplayObjectType = import('pixi.js').DisplayObject; + type ContainerType = import('pixi.js').Container; + interface DisplayObjectEvents { + 'enter-absorbable-area': [number | undefined, number | undefined]; + 'out-absorbable-area': [number | undefined, number | undefined]; + dataupdate: [newVal: any, oldVal: any]; + stateupdate: [newVal: any, oldVal: any]; + repaint: [DisplayObjectType]; + transformstart: [e: GraphicTransformEvent]; + transforming: [e: GraphicTransformEvent]; + transformend: [e: GraphicTransformEvent]; + _rightclick: [e: FederatedMouseEvent]; + _leftclick: [e: FederatedMouseEvent]; + selected: [DisplayObjectType]; + unselected: [DisplayObjectType]; + childselected: [DisplayObjectType]; + childunselected: [DisplayObjectType]; + } + + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface GraphicAppEvents { + // propertiesupdate: [selectedData: GraphicData | CanvasProperties | null]; + } + + interface DisplayObject { + _selectable: boolean; + _selected: boolean; + selectable: boolean; //是否可选中 + selected: boolean; // 是否选中 + _childEdit: boolean; // 子元素编辑模式 + childEdit: boolean; + _transformSave: boolean; // 变换是否保存 + transformSave: boolean; // + _assistantAppendMap: Map | null; // 辅助附加图形map + assistantAppendMap: Map; + _draggable: boolean; // 是否可拖拽 + draggable: boolean; + _shiftStartPoint: PointType | null; // 位移起始坐标 + shiftStartPoint: PointType | null; + _shiftLastPoint: PointType | null; // 位移上一个事件时坐标 + shiftLastPoint: PointType | null; + _scalable: boolean; // 是否可缩放 + scalable: boolean; + _keepAspectRatio: boolean; // 缩放是否保持纵横比,默认保持 + keepAspectRatio: boolean; + _rotatable: boolean; // 是否可旋转 + rotatable: boolean; + worldAngle: number; // 世界角度,(-180, 180] + /** + * 获取所有父级元素叠加缩放 + */ + getAllParentScaled(): PointType; + /** + * 获取位置在画布的坐标 + */ + getPositionOnCanvas(): PointType; + /** + * 通过画布坐标更新位置 + * @param p 画布坐标 + */ + updatePositionByCanvasPosition(p: IPointData): void; + /** + * 保存变换数据 + */ + saveTransform(): GraphicTransform; + /** + * 加载变换 + * @param transform 变换数据 + */ + loadTransform(transform: GraphicTransform): void; + isChild(obj: DisplayObject): boolean; // 是否子元素 + isParent(obj: DisplayObject): boolean; // 是否父元素 + isAssistantAppend(): boolean; // 是否辅助附加图形 + addAssistantAppend(...appends: D[]): void; + removeAssistantAppend(...appends: DisplayObjectType[]): void; + removeAssistantAppendByName(...names: string[]): void; + removeAllAssistantAppend(): void; + getAssistantAppend( + name: string + ): D | undefined; // 获取辅助附加图形对象 + isGraphic(): boolean; // 是否业务图形对象 + getGraphic(): G | null; // 获取所属的图形对象 + isGraphicChild(): boolean; // 是否图形子元素 + onAddToCanvas(): void; // 添加到画布处理 + onRemoveFromCanvas(): void; //从画布移除处理 + isInCanvas(): boolean; // 是否添加到画布中 + getCanvas(): JlCanvasType; // 获取所在画布 + isCanvas(): boolean; // 是否画布对象 + getViewport(): Viewport; // 获取视口 + getGraphicApp(): GraphicApp; // 获取图形app + /** + * 图形本地坐标转为画布坐标 + * @param p 图形本地坐标 + */ + localToCanvasPoint(p: IPointData): PointType; + /** + * 批量转换图形本地坐标为画布坐标 + * @param points 图形本地坐标 + */ + localToCanvasPoints(...points: IPointData[]): PointType[]; + /** + * 画布坐标转为图形本地坐标 + * @param p 画布坐标 + */ + canvasToLocalPoint(p: IPointData): PointType; + /** + * 批量转换画布坐标为图形本地坐标 + * @param points 画布坐标 + */ + canvasToLocalPoints(...points: IPointData[]): PointType[]; + /** + * 本地坐标转为屏幕坐标 + * @param p 本地坐标 + */ + localToScreenPoint(p: IPointData): PointType; + /** + * 批量转换本地坐标为屏幕坐标 + * @param points 本地坐标 + */ + localToScreenPoints(...points: IPointData[]): PointType[]; + /** + * 屏幕坐标转为本地坐标 + * @param p 屏幕坐标 + */ + screenToLocalPoint(p: IPointData): PointType; + /** + * 批量转换屏幕坐标为本地坐标 + * @param points 屏幕坐标 + */ + screenToLocalPoints(...points: IPointData[]): PointType[]; // 批量 + + localBoundsToCanvasPoints(): PointType[]; // 本地包围框转为多边形点坐标 + } + + interface Graphics { + drawBezierCurve( + p1: IPointData, + p2: IPointData, + cp1: IPointData, + cp2: IPointData, + segmentsCount: number + ): Graphics; + } +} diff --git a/src/jl-graphic/graphic/AbsorbablePosition.ts b/src/jl-graphic/graphic/AbsorbablePosition.ts new file mode 100644 index 0000000..b3a7acf --- /dev/null +++ b/src/jl-graphic/graphic/AbsorbablePosition.ts @@ -0,0 +1,252 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +import { + Color, + Container, + DisplayObject, + Graphics, + IPointData, + Point, +} from 'pixi.js'; +import { + calculateFootPointFromPointToLine, + calculateIntersectionPointOfCircleAndPoint, + distance, + distance2, + isLineContainOther, + linePoint, +} from '../utils'; +import { VectorGraphic, VectorGraphicUtil } from './VectorGraphic'; + +/** + * 抽象可吸附位置 + */ +export interface AbsorbablePosition extends Container { + /** + * 是否与另一个可吸附位置重叠(相似,但可能范围不同) + * @param other + */ + isOverlapping(other: AbsorbablePosition): boolean; + + /** + * 与另一个相似的吸附位置比较范围大小 + * @param other + * @returns >0此吸附范围大,<0另一个吸附范围大,=0两个吸附范围一样大 + */ + compareTo(other: AbsorbablePosition): number; + + /** + * 尝试吸附图形对象 + * @param objs 图形对象列表 + * @returns 如果吸附成功,返回true,否则false + */ + tryAbsorb(...objs: DisplayObject[]): void; +} + +/** + * 可吸附点图形参数 + */ +export const AbsorbablePointParam = { + lineWidth: 1, + lineColor: '#000000', + fillColor: '#E77E0E', + radius: 5, // 半径 +}; + +const AbsorbablePointGraphic = new Graphics(); +// AbsorbablePointGraphic.lineStyle( +// AbsorbablePointParam.lineWidth, +// AbsorbablePointParam.lineColor +// ); +AbsorbablePointGraphic.beginFill(AbsorbablePointParam.fillColor); +AbsorbablePointGraphic.drawCircle(0, 0, AbsorbablePointParam.radius); +AbsorbablePointGraphic.endFill(); + +/** + * 可吸附点 + */ +export default class AbsorbablePoint + extends Graphics + implements AbsorbablePosition, VectorGraphic +{ + _point: Point; + absorbRange: number; + scaledListenerOn = false; + + /** + * + * @param point 画布坐标 + * @param absorbRange + */ + constructor(point: IPointData, absorbRange = 10) { + super(AbsorbablePointGraphic.geometry); + this._point = new Point(point.x, point.y); + this.absorbRange = absorbRange; + this.position.copyFrom(this._point); + this.interactive; + VectorGraphicUtil.handle(this); + } + compareTo(other: AbsorbablePosition): number { + if (other instanceof AbsorbablePoint) { + return this.absorbRange - other.absorbRange; + } + throw new Error('非可吸附点'); + } + isOverlapping(other: AbsorbablePosition): boolean { + if (other instanceof AbsorbablePoint) { + return ( + this._point.equals(other._point) && + this.absorbRange === other.absorbRange + ); + } + return false; + } + tryAbsorb(...objs: DisplayObject[]): void { + for (let i = 0; i < objs.length; i++) { + const obj = objs[i]; + const canvasPosition = obj.getPositionOnCanvas(); + if ( + distance( + this._point.x, + this._point.y, + canvasPosition.x, + canvasPosition.y + ) < this.absorbRange + ) { + obj.updatePositionByCanvasPosition(this._point); + } + } + } + updateOnScaled() { + const scaled = this.getAllParentScaled(); + const scale = Math.max(scaled.x, scaled.y); + this.scale.set(1 / scale, 1 / scale); + } +} + +/** + * 可吸附线 + */ +export class AbsorbableLine extends Graphics implements AbsorbablePosition { + p1: Point; + p2: Point; + absorbRange: number; + _color = '#E77E0E'; + + /** + * + * @param p1 画布坐标 + * @param p2 画布坐标 + * @param absorbRange + */ + constructor(p1: IPointData, p2: IPointData, absorbRange = 20) { + super(); + this.p1 = new Point(p1.x, p1.y); + this.p2 = new Point(p2.x, p2.y); + this.absorbRange = absorbRange; + this.redraw(); + } + isOverlapping(other: AbsorbablePosition): boolean { + if (other instanceof AbsorbableLine) { + const contain = isLineContainOther( + { p1: this.p1, p2: this.p2 }, + { p1: other.p1, p2: other.p2 } + ); + return contain; + } + return false; + } + compareTo(other: AbsorbablePosition): number { + if (other instanceof AbsorbableLine) { + return distance2(this.p1, this.p2) - distance2(other.p1, other.p2); + } + throw new Error('非可吸附线'); + } + redraw() { + this.clear(); + this.lineStyle(1, new Color(this._color)); + this.moveTo(this.p1.x, this.p1.y); + this.lineTo(this.p2.x, this.p2.y); + } + + tryAbsorb(...objs: DisplayObject[]): void { + for (let i = 0; i < objs.length; i++) { + const obj = objs[i]; + const canvasPosition = obj.getPositionOnCanvas(); + if (linePoint(this.p1, this.p2, canvasPosition, this.absorbRange, true)) { + const fp = calculateFootPointFromPointToLine( + this.p1, + this.p2, + canvasPosition + ); + obj.updatePositionByCanvasPosition(fp); + } + } + } +} + +/** + * 可吸附圆 + */ +export class AbsorbableCircle extends Graphics implements AbsorbablePosition { + absorbRange: number; + p0: Point; + radius: number; + _color = '#E77E0E'; + + /** + * + * @param p 画布坐标 + * @param radius + * @param absorbRange + */ + constructor(p: IPointData, radius: number, absorbRange = 10) { + super(); + this.p0 = new Point(p.x, p.y); + this.radius = radius; + this.absorbRange = absorbRange; + this.redraw(); + } + isOverlapping(other: AbsorbablePosition): boolean { + if (other instanceof AbsorbableCircle) { + return this.p0.equals(other.p0) && this.radius === other.radius; + } + return false; + } + compareTo(other: AbsorbablePosition): number { + if (other instanceof AbsorbableCircle) { + return this.absorbRange - other.absorbRange; + } + throw new Error('非可吸附圆'); + } + + redraw() { + this.clear(); + this.lineStyle(1, new Color(this._color)); + this.drawCircle(this.p0.x, this.p0.y, this.radius); + } + + tryAbsorb(...objs: DisplayObject[]): void { + for (let i = 0; i < objs.length; i++) { + const obj = objs[i]; + const canvasPosition = obj.getPositionOnCanvas(); + const len = distance( + this.p0.x, + this.p0.y, + canvasPosition.x, + canvasPosition.y + ); + if ( + len > this.radius - this.absorbRange && + len < this.radius + this.absorbRange + ) { + // 吸附,计算直线与圆交点,更新对象坐标 + const p = calculateIntersectionPointOfCircleAndPoint( + this.p0, + this.radius, + canvasPosition + ); + obj.updatePositionByCanvasPosition(p); + } + } + } +} diff --git a/src/jl-graphic/graphic/DashedLine.ts b/src/jl-graphic/graphic/DashedLine.ts new file mode 100644 index 0000000..fbed07e --- /dev/null +++ b/src/jl-graphic/graphic/DashedLine.ts @@ -0,0 +1,102 @@ +import { Container, Graphics, IPointData, Point } from 'pixi.js'; +import { angleToAxisx } from '../utils'; + +export interface IDashedLineOptions { + /** + * 每小段长度,默认4 + */ + length?: number; + /** + * 起始间隔,默认0 + */ + startSpace?: number; + /** + * 间隔长度,默认4 + */ + space?: number; + /** + * 线宽,默认1 + */ + lineWidth?: number; + /** + * 线色,默认黑 + */ + color?: string; +} + +interface ICompleteDashedLineOptions extends IDashedLineOptions { + length: number; + startSpace: number; + space: number; + lineWidth: number; + color: string; +} + +const DefaultDashedLineOptions: ICompleteDashedLineOptions = { + length: 4, + startSpace: 0, + space: 4, + lineWidth: 1, + color: '#0000ff', +}; + +export class DashedLine extends Container { + p1: Point; + p2: Point; + _options: ICompleteDashedLineOptions; + constructor(p1: IPointData, p2: IPointData, options?: IDashedLineOptions) { + super(); + const config = Object.assign({}, DefaultDashedLineOptions, options); + this._options = config; + this.p1 = new Point(p1.x, p1.y); + this.p2 = new Point(p2.x, p2.y); + this.redraw(); + } + + setOptions(options: IDashedLineOptions) { + if (options.startSpace != undefined) { + this._options.startSpace = options.startSpace; + } + if (options.length != undefined) { + this._options.length = options.length; + } + if (options.space != undefined) { + this._options.space = options.space; + } + if (options.lineWidth != undefined) { + this._options.lineWidth = options.lineWidth; + } + if (options.color != undefined) { + this._options.color = options.color; + } + this.redraw(); + } + + redraw() { + this.removeChildren(); + const p1 = this.p1; + const p2 = this.p2; + const option = this._options; + const total = Math.pow( + Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2), + 0.5 + ); + let len = option.startSpace; + while (len < total) { + let dashedLen = option.length; + if (len + option.length > total) { + dashedLen = total - len; + } + const line = new Graphics(); + line.lineStyle(option.lineWidth, option.color); + line.moveTo(len, 0); + line.lineTo(len + dashedLen, 0); + this.addChild(line); + len = len + dashedLen + option.space; + } + + this.pivot.set(0, option.lineWidth / 2); + this.position.set(p1.x, p1.y); + this.angle = angleToAxisx(p1, p2); + } +} diff --git a/src/jl-graphic/graphic/DraggablePoint.ts b/src/jl-graphic/graphic/DraggablePoint.ts new file mode 100644 index 0000000..2fbcf8e --- /dev/null +++ b/src/jl-graphic/graphic/DraggablePoint.ts @@ -0,0 +1,45 @@ +import { Graphics, IPointData } from 'pixi.js'; +import { VectorGraphic, VectorGraphicUtil } from './VectorGraphic'; + +/** + * 拖拽点参数 + */ +export const DraggablePointParam = { + lineWidth: 1, + lineColor: 0x000000, + fillColor: 0xffffff, + radius: 5, // 半径 +}; + +const DraggablePointGraphic = new Graphics(); +DraggablePointGraphic.lineStyle( + DraggablePointParam.lineWidth, + DraggablePointParam.lineColor +); +DraggablePointGraphic.beginFill(DraggablePointParam.fillColor); +DraggablePointGraphic.drawCircle(0, 0, DraggablePointParam.radius); +DraggablePointGraphic.endFill(); + +/** + * 拖拽点,用于更新图形属性 + */ +export class DraggablePoint extends Graphics implements VectorGraphic { + scaledListenerOn = false; + /** + * + * @param point 画布坐标点 + */ + constructor(point: IPointData) { + super(DraggablePointGraphic.geometry); + this.position.copyFrom(point); + this.eventMode = 'static'; + this.draggable = true; + this.cursor = 'crosshair'; + VectorGraphicUtil.handle(this); + } + updateOnScaled() { + const scaled = this.getAllParentScaled(); + const scale = Math.max(scaled.x, scaled.y); + this.scale.set(1 / scale, 1 / scale); + } +} diff --git a/src/jl-graphic/graphic/VectorGraphic.ts b/src/jl-graphic/graphic/VectorGraphic.ts new file mode 100644 index 0000000..b00b385 --- /dev/null +++ b/src/jl-graphic/graphic/VectorGraphic.ts @@ -0,0 +1,44 @@ +import { DisplayObject } from 'pixi.js'; + +export interface VectorGraphic extends DisplayObject { + scaledListenerOn: boolean; + updateOnScaled(): void; +} + +export class VectorGraphicUtil { + static handle(obj: VectorGraphic): void { + const vg = obj; + const onScaleChange = function (obj: DisplayObject) { + if (vg.isParent(obj)) { + vg.updateOnScaled(); + } + }; + const registerScaleChange = function registerScaleChange( + obj: VectorGraphic + ): void { + if (!obj.scaledListenerOn) { + obj.scaledListenerOn = true; + obj.getGraphicApp().on('viewport-scaled', onScaleChange); + } + }; + const unregisterScaleChange = function unregisterScaleChange( + obj: VectorGraphic + ): void { + obj.scaledListenerOn = false; + obj.getGraphicApp().off('viewport-scaled', onScaleChange); + }; + obj.onAddToCanvas = function onAddToCanvas() { + obj.updateOnScaled(); + registerScaleChange(obj); + }; + obj.onRemoveFromCanvas = function onRemoveFromCanvas() { + unregisterScaleChange(obj); + }; + + obj.on('added', (container) => { + if (container.isInCanvas()) { + obj.onAddToCanvas(); + } + }); + } +} diff --git a/src/jl-graphic/graphic/VectorText.ts b/src/jl-graphic/graphic/VectorText.ts new file mode 100644 index 0000000..f28e031 --- /dev/null +++ b/src/jl-graphic/graphic/VectorText.ts @@ -0,0 +1,35 @@ +import { ICanvas, ITextStyle, Text, TextStyle } from 'pixi.js'; +import { VectorGraphic, VectorGraphicUtil } from '.'; + +/** + * 矢量文字.实现原理:在缩放发生变化时,更新fontSize + */ +export class VectorText extends Text implements VectorGraphic { + vectorFontSize = 8; + scaled = 1; + scaledListenerOn = false; + + constructor( + text?: string | number, + style?: Partial | TextStyle, + canvas?: ICanvas + ) { + super(text, style, canvas); + VectorGraphicUtil.handle(this); + } + + updateOnScaled() { + const scaled = this.getAllParentScaled(); + const scale = Math.max(scaled.x, scaled.y); + this.style.fontSize = this.vectorFontSize * scale; + this.scale.set(1 / scale, 1 / scale); + } + + /** + * 设置矢量文字的字体大小 + */ + setVectorFontSize(fontSize: number) { + this.vectorFontSize = fontSize; + this.style.fontSize = fontSize; + } +} diff --git a/src/jl-graphic/graphic/index.ts b/src/jl-graphic/graphic/index.ts new file mode 100644 index 0000000..726584a --- /dev/null +++ b/src/jl-graphic/graphic/index.ts @@ -0,0 +1,4 @@ +export * from './VectorGraphic'; +export * from './VectorText'; +export * from './DraggablePoint'; +export * from './AbsorbablePosition'; diff --git a/src/jl-graphic/index.ts b/src/jl-graphic/index.ts new file mode 100644 index 0000000..e64f743 --- /dev/null +++ b/src/jl-graphic/index.ts @@ -0,0 +1,7 @@ +export * from './core'; +export * from './graphic'; +export * from './app'; +export * from './operation'; +export * from './utils'; +export * from './plugins'; +export * from './message'; diff --git a/src/jl-graphic/math/Constants.ts b/src/jl-graphic/math/Constants.ts new file mode 100644 index 0000000..87393fb --- /dev/null +++ b/src/jl-graphic/math/Constants.ts @@ -0,0 +1,26 @@ +/** + * 浮点数相等判断误差值 + */ +export const epsilon = 0.00001; + +/** + * 判断浮点数是不是0 + * @param v + * @returns + */ +export function isZero(v: number) { + if (Math.abs(v) < epsilon) { + return true; + } + return false; +} + +/** + * 两浮点数是否相等 + * @param f1 + * @param f2 + * @returns + */ +export function floatEquals(f1: number, f2: number): boolean { + return isZero(f1 - f2); +} diff --git a/src/jl-graphic/math/Vector2.ts b/src/jl-graphic/math/Vector2.ts new file mode 100644 index 0000000..1894d6f --- /dev/null +++ b/src/jl-graphic/math/Vector2.ts @@ -0,0 +1,360 @@ +/* eslint-disable @typescript-eslint/no-this-alias */ + +import { epsilon } from './Constants'; + +export default class Vector2 { + constructor(values?: [number, number]) { + if (values !== undefined) { + this.xy = values; + } + } + + static from(p: { x: number; y: number }): Vector2 { + return new Vector2([p.x, p.y]); + } + + private values = new Float32Array(2); + + static readonly zero = new Vector2([0, 0]); + static readonly one = new Vector2([1, 1]); + + get x(): number { + return this.values[0]; + } + + set x(value: number) { + this.values[0] = value; + } + get y(): number { + return this.values[1]; + } + set y(value: number) { + this.values[1] = value; + } + + get xy(): [number, number] { + return [this.values[0], this.values[1]]; + } + + set xy(values: [number, number]) { + this.values[0] = values[0]; + this.values[1] = values[1]; + } + + at(index: number): number { + return this.values[index]; + } + + reset(): void { + this.x = 0; + this.y = 0; + } + + copy(dest?: Vector2): Vector2 { + if (!dest) { + dest = new Vector2(); + } + + dest.x = this.x; + dest.y = this.y; + + return dest; + } + + negate(dest?: Vector2): Vector2 { + if (!dest) { + dest = this; + } + + dest.x = -this.x; + dest.y = -this.y; + + return dest; + } + + equals(vector: Vector2, threshold = epsilon): boolean { + if (Math.abs(this.x - vector.x) > threshold) { + return false; + } + + if (Math.abs(this.y - vector.y) > threshold) { + return false; + } + + return true; + } + + length(): number { + return Math.sqrt(this.squaredLength()); + } + + squaredLength(): number { + const x = this.x; + const y = this.y; + + return x * x + y * y; + } + + add(vector: Vector2): Vector2 { + this.x += vector.x; + this.y += vector.y; + + return this; + } + + subtract(vector: Vector2): Vector2 { + this.x -= vector.x; + this.y -= vector.y; + + return this; + } + + multiply(vector: Vector2): Vector2 { + this.x *= vector.x; + this.y *= vector.y; + + return this; + } + + divide(vector: Vector2): Vector2 { + this.x /= vector.x; + this.y /= vector.y; + + return this; + } + + scale(value: number, dest?: Vector2): Vector2 { + if (!dest) { + dest = this; + } + + dest.x *= value; + dest.y *= value; + + return dest; + } + + normalize(dest?: Vector2): Vector2 { + if (!dest) { + dest = this; + } + + let length = this.length(); + + if (length === 1) { + return this; + } + + if (length === 0) { + dest.x = 0; + dest.y = 0; + + return dest; + } + + length = 1.0 / length; + + dest.x *= length; + dest.y *= length; + + return dest; + } + + // multiplyMat2(matrix: mat2, dest?: Vector2): Vector2 { + // if (!dest) { + // dest = this; + // } + + // return matrix.multiplyVec2(this, dest); + // } + + // multiplyMat3(matrix: mat3, dest?: Vector2): Vector2 { + // if (!dest) { + // dest = this; + // } + + // return matrix.multiplyVec2(this, dest); + // } + + // static cross(vector: Vector2, vector2: Vector2, dest?: vec3): vec3 { + // if (!dest) { + // dest = new vec3(); + // } + + // const x = vector.x; + // const y = vector.y; + + // const x2 = vector2.x; + // const y2 = vector2.y; + + // const z = x * y2 - y * x2; + + // dest.x = 0; + // dest.y = 0; + // dest.z = z; + + // return dest; + // } + + /** + * 向量点乘 + * @param vector + * @param vector2 + * @returns + */ + static dot(vector: Vector2, vector2: Vector2): number { + return vector.x * vector2.x + vector.y * vector2.y; + } + /** + * 向量长度 + * @param vector + * @param vector2 + * @returns + */ + static distance(vector: Vector2, vector2: Vector2): number { + return Math.sqrt(this.squaredDistance(vector, vector2)); + } + + /** + * 向量长度平方 + * @param vector + * @param vector2 + * @returns + */ + static squaredDistance(vector: Vector2, vector2: Vector2): number { + const x = vector2.x - vector.x; + const y = vector2.y - vector.y; + + return x * x + y * y; + } + + /** + * v2->v1的方向的单位向量 + * @param v1 + * @param v2 + * @param dest + * @returns + */ + static direction(v1: Vector2, v2: Vector2, dest?: Vector2): Vector2 { + if (!dest) { + dest = new Vector2(); + } + + const x = v1.x - v2.x; + const y = v1.y - v2.y; + + let length = Math.sqrt(x * x + y * y); + + if (length === 0) { + dest.x = 0; + dest.y = 0; + + return dest; + } + + length = 1 / length; + + dest.x = x * length; + dest.y = y * length; + + return dest; + } + + static mix( + vector: Vector2, + vector2: Vector2, + time: number, + dest?: Vector2 + ): Vector2 { + if (!dest) { + dest = new Vector2(); + } + + const x = vector.x; + const y = vector.y; + + const x2 = vector2.x; + const y2 = vector2.y; + + dest.x = x + time * (x2 - x); + dest.y = y + time * (y2 - y); + + return dest; + } + + /** + * 向量加法 + * @param vector + * @param vector2 + * @param dest + * @returns + */ + static sum(vector: Vector2, vector2: Vector2, dest?: Vector2): Vector2 { + if (!dest) { + dest = new Vector2(); + } + + dest.x = vector.x + vector2.x; + dest.y = vector.y + vector2.y; + + return dest; + } + + /** + * 向量减法 + * @param vector + * @param vector2 + * @param dest + * @returns + */ + static difference( + vector: Vector2, + vector2: Vector2, + dest?: Vector2 + ): Vector2 { + if (!dest) { + dest = new Vector2(); + } + + dest.x = vector.x - vector2.x; + dest.y = vector.y - vector2.y; + + return dest; + } + + /** + * 向量乘法 + * @param vector + * @param vector2 + * @param dest + * @returns + */ + static product(vector: Vector2, vector2: Vector2, dest?: Vector2): Vector2 { + if (!dest) { + dest = new Vector2(); + } + + dest.x = vector.x * vector2.x; + dest.y = vector.y * vector2.y; + + return dest; + } + + /** + * 向量除法 + * @param vector + * @param vector2 + * @param dest + * @returns + */ + static quotient(vector: Vector2, vector2: Vector2, dest?: Vector2): Vector2 { + if (!dest) { + dest = new Vector2(); + } + + dest.x = vector.x / vector2.x; + dest.y = vector.y / vector2.y; + + return dest; + } +} diff --git a/src/jl-graphic/math/index.ts b/src/jl-graphic/math/index.ts new file mode 100644 index 0000000..3935efe --- /dev/null +++ b/src/jl-graphic/math/index.ts @@ -0,0 +1,4 @@ +/// 向量和矩阵代码源自开源代码:https://github.com/matthiasferch/tsm + +export * from './Constants'; +export * from './Vector2'; diff --git a/src/jl-graphic/message/WsMsgBroker.ts b/src/jl-graphic/message/WsMsgBroker.ts new file mode 100644 index 0000000..52d561a --- /dev/null +++ b/src/jl-graphic/message/WsMsgBroker.ts @@ -0,0 +1,248 @@ +import { + Client as StompClient, + StompSubscription, + type Frame, + type Message, + type messageCallbackType, +} from '@stomp/stompjs'; +import type { GraphicApp } from '../app/JlGraphicApp'; +import { GraphicState } from '../core/JlGraphic'; + +export interface StompCliOption { + /** + * websocket url地址 + */ + wsUrl: string; + /** + * 认证token + */ + token?: string; + /** + * 认证失败处理 + * @returns + */ + onAuthenticationFailed?: () => void; + reconnectDelay?: number; // 重连延时,默认3秒,设置为0不重连. + heartbeatIncoming?: number; // 服务端过来的心跳间隔,默认30秒 + heartbeatOutgoing?: number; // 到服务端的心跳间隔,默认30秒 +} + +const DefaultStompOption: StompCliOption = { + wsUrl: '', + token: '', + reconnectDelay: 3000, + heartbeatIncoming: 30000, + heartbeatOutgoing: 30000, +}; + +export class StompCli { + private static client: StompClient; + private static options: StompCliOption; + private static appMsgBroker: AppWsMsgBroker[] = []; + /** + * key-订阅路径 + */ + subscriptions: Map = new Map< + string, + AppStateSubscription + >(); + private static connected = false; + static new(options: StompCliOption) { + if (StompCli.client) { + // 已经创建 + return; + } + StompCli.options = Object.assign({}, DefaultStompOption, options); + StompCli.client = new StompClient({ + brokerURL: StompCli.options.wsUrl, + connectHeaders: { + Authorization: StompCli.options.token ? StompCli.options.token : '', + }, + reconnectDelay: StompCli.options.reconnectDelay, + heartbeatIncoming: StompCli.options.heartbeatIncoming, + heartbeatOutgoing: StompCli.options.heartbeatOutgoing, + }); + + StompCli.client.onConnect = () => { + // console.log('websocket连接(重连),重新订阅', StompCli.appMsgBroker.length) + StompCli.connected = true; + StompCli.emitConnectStateChangeEvent(); + StompCli.appMsgBroker.forEach((broker) => { + broker.resubscribe(); + }); + }; + + StompCli.client.onStompError = (frame: Frame) => { + const errMsg = frame.headers['message']; + if (errMsg === '401') { + console.warn('认证失败,断开WebSocket连接'); + StompCli.close(); + if (StompCli.options.onAuthenticationFailed) { + StompCli.options.onAuthenticationFailed(); + } + } else { + console.error('收到Stomp错误消息', frame); + } + }; + + StompCli.client.onDisconnect = (frame: Frame) => { + console.log('Stomp 断开连接', frame); + StompCli.connected = false; + StompCli.emitConnectStateChangeEvent(); + }; + StompCli.client.onWebSocketClose = (evt: CloseEvent) => { + console.log('websocket 关闭', evt); + StompCli.connected = false; + StompCli.emitConnectStateChangeEvent(); + }; + // websocket错误处理 + StompCli.client.onWebSocketError = (err: Event) => { + console.log('websocket错误', err); + }; + + StompCli.client.activate(); + } + + static emitConnectStateChangeEvent() { + StompCli.appMsgBroker.forEach((broker) => { + broker.app.emit('websocket-state-change', broker.app, StompCli.connected); + }); + } + + static isConnected(): boolean { + return StompCli.client && StompCli.client.connected; + } + + static trySubscribe( + destination: string, + handler: messageCallbackType + ): StompSubscription | undefined { + if (StompCli.isConnected()) { + return StompCli.client.subscribe(destination, handler, { + id: destination, + }); + } + return undefined; + } + + static registerAppMsgBroker(broker: AppWsMsgBroker) { + StompCli.appMsgBroker.push(broker); + } + + static removeAppMsgBroker(broker: AppWsMsgBroker) { + const index = StompCli.appMsgBroker.findIndex((mb) => mb == broker); + if (index >= 0) { + StompCli.appMsgBroker.splice(index, 1); + } + } + + static hasAppMsgBroker(): boolean { + return StompCli.appMsgBroker.length > 0; + } + + /** + * 关闭websocket连接 + */ + static close() { + StompCli.connected = false; + if (StompCli.client) { + StompCli.client.deactivate(); + } + } +} + +// 状态订阅消息转换器 +export type GraphicStateMessageConvert = ( + message: Uint8Array +) => GraphicState[]; + +// 订阅消息处理器 +export type SubscriptionMessageHandle = (message: Uint8Array) => void; + +// 图形app状态订阅 +export interface AppStateSubscription { + /** + * 订阅路径 + */ + destination: string; + /** + * 图形状态消息转换 + */ + messageConverter?: GraphicStateMessageConvert; + /** + * 订阅消息处理 + */ + messageHandle?: SubscriptionMessageHandle; + /** + * 订阅成功对象,用于取消订阅 + * 非客户端使用 + */ + subscription?: StompSubscription; +} + +/** + * 图形APP的websocket消息代理 + */ +export class AppWsMsgBroker { + app: GraphicApp; + subscriptions: Map = new Map< + string, + AppStateSubscription + >(); + + constructor(app: GraphicApp) { + this.app = app; + StompCli.registerAppMsgBroker(this); + } + + subscribe(sub: AppStateSubscription) { + this.unsbuscribe(sub.destination); // 先尝试取消之前订阅 + sub.subscription = StompCli.trySubscribe( + sub.destination, + (message: Message) => { + if (sub.messageConverter) { + const graphicStates = sub.messageConverter(message.binaryBody); + this.app.handleGraphicStates(graphicStates); + } else if (sub.messageHandle) { + sub.messageHandle(message.binaryBody); + } else { + console.error( + `订阅destination:${sub.destination}没有消息处理器或图形状态消息转换器` + ); + } + } + ); + // console.log('代理订阅结果', sub.subscription) + this.subscriptions.set(sub.destination, sub); + } + + resubscribe() { + this.subscriptions.forEach((record) => { + this.subscribe(record); + }); + } + + unsbuscribe(destination: string) { + const oldSub = this.subscriptions.get(destination); + if (oldSub) { + if (oldSub.subscription && StompCli.isConnected()) { + oldSub.subscription.unsubscribe(); + } + oldSub.subscription = undefined; + } + } + + unsbuscribeAll() { + this.subscriptions.forEach((record) => { + this.unsbuscribe(record.destination); + }); + } + + /** + * 取消所有订阅,从通用Stomp客户端移除此消息代理 + */ + close() { + StompCli.removeAppMsgBroker(this); + this.unsbuscribeAll(); + } +} diff --git a/src/jl-graphic/message/index.ts b/src/jl-graphic/message/index.ts new file mode 100644 index 0000000..fddbf3f --- /dev/null +++ b/src/jl-graphic/message/index.ts @@ -0,0 +1 @@ +export * from './WsMsgBroker'; diff --git a/src/jl-graphic/operation/JlOperation.ts b/src/jl-graphic/operation/JlOperation.ts new file mode 100644 index 0000000..5673930 --- /dev/null +++ b/src/jl-graphic/operation/JlOperation.ts @@ -0,0 +1,99 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { GraphicApp } from '../app/JlGraphicApp'; +import { JlGraphic } from '../core/JlGraphic'; + +/** + * 操作 + */ +export abstract class JlOperation { + type: string; // 操作类型/名称 + app: GraphicApp; + obj?: any; // 操作对象 + data?: any; // 操作数据 + description?: string = ''; // 操作描述 + + constructor(app: GraphicApp, type: string) { + this.app = app; + this.type = type; + } + + undo1(): void { + const updates = this.undo(); + if (updates) { + this.app.updateSelected(...updates); + } + } + redo1(): void { + const updates = this.redo(); + if (updates) { + this.app.updateSelected(...updates); + } + } + + abstract undo(): JlGraphic[] | void; + abstract redo(): JlGraphic[] | void; +} + +/** + * 操作记录 + */ +export class OperationRecord { + undoStack: JlOperation[] = []; + redoStack: JlOperation[] = []; + private maxLen: number; + + constructor(maxLen = 100) { + this.maxLen = maxLen; + } + + public get hasUndo(): boolean { + return this.undoStack.length > 0; + } + + public get hasRedo(): boolean { + return this.redoStack.length > 0; + } + + setMaxLen(v: number) { + this.maxLen = v; + const len = this.undoStack.length; + if (len > v) { + const removeCount = len - v; + this.undoStack.splice(0, removeCount); + } + } + /** + * 记录 + * @param op + */ + record(op: JlOperation) { + if (this.undoStack.length >= this.maxLen) { + this.undoStack.shift(); + } + // console.log('operation record', op) + this.undoStack.push(op); + this.redoStack.splice(0, this.redoStack.length); + } + /** + * 撤销 + */ + undo() { + const op = this.undoStack.pop(); + // console.log('撤销', op); + if (op) { + op.undo1(); + this.redoStack.push(op); + } + } + /** + * 重做 + */ + redo() { + const op = this.redoStack.pop(); + // console.log('重做', op); + if (op) { + op.redo1(); + this.undoStack.push(op); + } + } +} diff --git a/src/jl-graphic/operation/index.ts b/src/jl-graphic/operation/index.ts new file mode 100644 index 0000000..0d6da94 --- /dev/null +++ b/src/jl-graphic/operation/index.ts @@ -0,0 +1 @@ +export * from './JlOperation'; diff --git a/src/jl-graphic/plugins/AnimationManager.ts b/src/jl-graphic/plugins/AnimationManager.ts new file mode 100644 index 0000000..492a7fd --- /dev/null +++ b/src/jl-graphic/plugins/AnimationManager.ts @@ -0,0 +1,75 @@ +import { GraphicApp } from '../app'; +import { GraphicAnimation, JlGraphic } from '../core'; + +/** + * 图形动画管理 + */ +export class AnimationManager { + app: GraphicApp; + graphicAnimationMap: Map>; + constructor(app: GraphicApp) { + this.app = app; + this.graphicAnimationMap = new Map>(); + // 动画控制 + app.app.ticker.add((dt: number) => { + this.graphicAnimationMap.forEach((map) => { + map.forEach((animation) => { + if (animation.running) { + animation.run(dt); + } + }); + }); + }); + } + + static new(app: GraphicApp): AnimationManager { + return new AnimationManager(app); + } + + /** + * 图形对象的所有动画map + * @param graphic + * @returns + */ + animationMap(graphic: JlGraphic): Map { + let map = this.graphicAnimationMap.get(graphic.id); + if (!map) { + map = new Map(); + this.graphicAnimationMap.set(graphic.id, map); + } + return map; + } + + /** + * 注册图形动画 + * @param graphic + * @param animation + */ + registerAnimation(graphic: JlGraphic, animation: GraphicAnimation) { + this.animationMap(graphic).set(animation.name, animation); + } + /** + * 删除图形动画 + * @param graphic + * @param name + */ + unregisterAnimation(graphic: JlGraphic, name: string) { + this.animationMap(graphic).delete(name); + } + /** + * 删除所有图形动画 + * @param graphic + */ + unregisterGraphicAnimations(graphic: JlGraphic) { + this.animationMap(graphic).clear(); + } + /** + * 获取图形指定名称动画 + * @param graphic + * @param name + * @returns + */ + animation(graphic: JlGraphic, name: string): GraphicAnimation | undefined { + return this.animationMap(graphic).get(name); + } +} diff --git a/src/jl-graphic/plugins/CommonMousePlugin.ts b/src/jl-graphic/plugins/CommonMousePlugin.ts new file mode 100644 index 0000000..b7a33f1 --- /dev/null +++ b/src/jl-graphic/plugins/CommonMousePlugin.ts @@ -0,0 +1,328 @@ +import { DisplayObject, FederatedMouseEvent, Graphics, Point } from 'pixi.js'; +import { GraphicApp, JlCanvas } from '../app'; +import { JlGraphic } from '../core'; +import { + AppDragEvent, + AppInteractionPlugin, + ViewportMovePlugin, +} from './InteractionPlugin'; + +type GraphicSelectFilter = (graphic: JlGraphic) => boolean; + +export interface IMouseToolOptions { + /** + * 是否启用框选,默认启用 + */ + boxSelect?: boolean; + /** + * 是否启用视口拖拽(默认右键),默认启用 + */ + viewportDrag?: boolean; + /** + * 是否启用鼠标滚轮缩放,默认启用 + */ + wheelZoom?: boolean; + /** + * 可选择图形过滤器 + */ + selectFilter?: GraphicSelectFilter; +} + +class CompleteMouseToolOptions implements IMouseToolOptions { + boxSelect: boolean; + viewportDrag: boolean; + wheelZoom: boolean; + selectFilter?: GraphicSelectFilter | undefined; + constructor() { + this.boxSelect = true; + this.viewportDrag = true; + this.wheelZoom = true; + } + update(options: IMouseToolOptions) { + if (options.boxSelect != undefined) { + this.boxSelect = options.boxSelect; + } + if (options.viewportDrag != undefined) { + this.viewportDrag = options.viewportDrag; + } + if (options.wheelZoom != undefined) { + this.wheelZoom = options.wheelZoom; + } + this.selectFilter = options.selectFilter; + } +} + +const DefaultSelectToolOptions: CompleteMouseToolOptions = + new CompleteMouseToolOptions(); + +/** + * 通用交互工具 + */ +export class CommonMouseTool extends AppInteractionPlugin { + static Name = 'mouse-tool'; + static SelectBox = '__select_box'; + options: CompleteMouseToolOptions; + box: Graphics; + leftDownTarget: DisplayObject | null = null; + + drag = false; + graphicSelect = false; + + rightTarget: DisplayObject | null = null; + + constructor(graphicApp: GraphicApp) { + super(CommonMouseTool.Name, graphicApp); + this.options = DefaultSelectToolOptions; + + this.box = new Graphics(); + this.box.name = CommonMouseTool.SelectBox; + this.box.visible = false; + this.app.canvas.addAssistantAppends(this.box); + + graphicApp.on('options-update', (options) => { + if (options.mouseToolOptions) { + this.options.update(options.mouseToolOptions); + if (this.isActive()) { + this.pause(); + this.resume(); + } + } + }); + } + + static new(app: GraphicApp) { + return new CommonMouseTool(app); + } + + bind(): void { + const canvas = this.app.canvas; + canvas.on('mousedown', this.onMouseDown, this); + canvas.on('mouseup', this.onMouseUp, this); + this.app.on('drag_op_start', this.onDragStart, this); + this.app.on('drag_op_move', this.onDragMove, this); + this.app.on('drag_op_end', this.onDragEnd, this); + if (this.options.viewportDrag) { + this.app.viewport.drag({ + mouseButtons: 'right', + }); + canvas.on('rightdown', this.setCursor, this); + canvas.on('rightup', this.resumeCursor, this); + canvas.on('rightupoutside', this.resumeCursor, this); + } + if (this.options.wheelZoom) { + this.app.viewport.wheel({ + percent: 0.01, + }); + } + } + unbind(): void { + const canvas = this.app.canvas; + // 确保所有事件取消监听 + canvas.off('mousedown', this.onMouseDown, this); + canvas.off('mouseup', this.onMouseUp, this); + + this.app.off('drag_op_start', this.onDragStart, this); + this.app.off('drag_op_move', this.onDragMove, this); + this.app.off('drag_op_end', this.onDragEnd, this); + + this.app.viewport.plugins.remove('drag'); + canvas.off('rightdown', this.setCursor, this); + canvas.off('rightup', this.resumeCursor, this); + canvas.off('rightupoutside', this.resumeCursor, this); + + this.app.viewport.plugins.remove('wheel'); + this.clearCache(); + } + + onDragStart(event: AppDragEvent) { + // console.log( + // 'start', + // `pointerType:${event.original.pointerType},pointerId:${event.original.pointerId},button: ${event.original.button},buttons:${event.original.buttons}` + // ); + if (this.boxSelect && event.target.isCanvas() && event.isLeftButton) { + this.box.visible = true; + this.app.interactionPlugin(ViewportMovePlugin.Name).resume(); + } + this.drag = true; + } + + onDragMove(event: AppDragEvent) { + // console.log( + // 'moving', + // `pointerType:${event.original.pointerType},pointerId:${event.original.pointerId},button: ${event.original.button},buttons:${event.original.buttons}` + // ); + if (this.boxSelect && event.target.isCanvas()) { + this.boxSelectDraw(event.start, event.end); + } + } + onDragEnd(event: AppDragEvent) { + // console.log( + // 'end', + // `pointerType:${event.original.pointerType},pointerId:${event.original.pointerId},button: ${event.original.button},buttons:${event.original.buttons}` + // ); + if (this.boxSelect && event.target.isCanvas() && event.isLeftButton) { + this.boxSelectDraw(event.start, event.end); + this.boxSelectGraphicCheck(); + this.app.interactionPlugin(ViewportMovePlugin.Name).pause(); + this.box.clear(); + this.box.visible = false; + } + } + + setCursor(e: FederatedMouseEvent) { + this.rightTarget = e.target as DisplayObject; + if (e.target instanceof JlCanvas && this.app.app.view.style) { + this.app.app.view.style.cursor = 'grab'; + } + } + + resumeCursor() { + if ( + this.rightTarget && + this.rightTarget instanceof JlCanvas && + this.app.app.view.style + ) { + this.app.app.view.style.cursor = 'inherit'; + } + this.rightTarget = null; + } + + onMouseDown(e: FederatedMouseEvent) { + this.leftDownTarget = e.target as DisplayObject; + this.graphicSelect = false; + // 图形 + const graphic = this.leftDownTarget.getGraphic(); + if (graphic) { + const app = this.app; + // console.log(this.leftDownTarget.isGraphic()); + // 图形选中 + if (!e.ctrlKey && !graphic.selected && graphic.selectable) { + app.updateSelected(graphic); + graphic.childEdit = false; + this.graphicSelect = true; + } else if (!e.ctrlKey && graphic.selected && graphic.childEdit) { + if ( + this.leftDownTarget.isGraphicChild() && + this.leftDownTarget.selectable + ) { + graphic.setChildSelected(this.leftDownTarget); + } else { + graphic.exitChildEdit(); + } + } + } + } + + /** + * 选中处理 + * @param e + */ + onMouseUp(e: FederatedMouseEvent) { + const app = this.app; + if (!this.drag) { + const target = e.target as DisplayObject; + const graphic = (e.target as DisplayObject).getGraphic(); + if ( + graphic && + graphic.selected && + !this.graphicSelect && + app.selectedGraphics.length == 1 && + target === this.leftDownTarget && + target.isGraphicChild() && + target.selectable + ) { + graphic.childEdit = true; + } + if (e.ctrlKey) { + // 多选 + if (graphic) { + if (graphic.childEdit && target === this.leftDownTarget) { + graphic.invertChildSelected(target); + } else { + graphic.invertSelected(); + app.fireSelectedChange(graphic); + } + } + } else { + // 非多选 + if (e.target instanceof JlCanvas) { + this.app.updateSelected(); + } else { + if ( + graphic && + graphic.childEdit && + app.selectedGraphics.length === 1 && + target === this.leftDownTarget + ) { + graphic.setChildSelected(target); + } + } + } + // 多个图形选中,退出子元素编辑模式 + const selecteds = this.app.selectedGraphics; + if (selecteds.length > 1) { + selecteds.forEach((g) => g.exitChildEdit()); + } + } + this.clearCache(); + } + + /** + * 清理缓存 + */ + clearCache() { + this.drag = false; + this.leftDownTarget = null; + } + + public get boxSelect(): boolean | undefined { + return this.options.boxSelect; + } + + public get selectFilter(): GraphicSelectFilter | undefined { + return this.options.selectFilter; + } + + /** + * 框选图形绘制并检查 + */ + boxSelectDraw(start: Point, end: Point): void { + if (!this.drag) return; + // 绘制框选矩形框 + this.box.clear(); + this.box.lineStyle({ width: 1, color: 0x000000 }); + const dsx = end.x - start.x; + const dsy = end.y - start.y; + let { x, y } = start; + if (dsx < 0) { + x += dsx; + } + if (dsy < 0) { + y += dsy; + } + const width = Math.abs(dsx); + const height = Math.abs(dsy); + this.box.drawRect(x, y, width, height); + } + + /** + * 框选图形判断 + * @returns + */ + boxSelectGraphicCheck(): void { + if (!this.drag) return; + // 遍历筛选 + const boxRect = this.box.getLocalBounds(); + const app = this.app; + const selects: JlGraphic[] = []; + app.queryStore.getAllGraphics().forEach((g) => { + if (!this.selectFilter || this.selectFilter(g)) { + // 选择过滤器 + if (g.boxIntersectCheck(boxRect)) { + selects.push(g); + } + } + }); + app.updateSelected(...selects); + } +} diff --git a/src/jl-graphic/plugins/CopyPlugin.ts b/src/jl-graphic/plugins/CopyPlugin.ts new file mode 100644 index 0000000..2cbc71f --- /dev/null +++ b/src/jl-graphic/plugins/CopyPlugin.ts @@ -0,0 +1,141 @@ +import { Container, FederatedPointerEvent, Point } from 'pixi.js'; +import { GraphicApp, GraphicCreateOperation } from '../app'; +import { JlGraphic } from '../core'; +import { KeyListener } from './KeyboardPlugin'; + +export class GraphicCopyPlugin { + container: Container; + app: GraphicApp; + keyListeners: KeyListener[]; + copys: JlGraphic[]; + start?: Point; + running = false; + moveLimit?: 'x' | 'y'; + constructor(app: GraphicApp) { + this.app = app; + this.container = new Container(); + this.copys = []; + this.keyListeners = []; + this.keyListeners.push( + new KeyListener({ + // ESC 用于取消复制操作 + value: 'Escape', + global: true, + // combinations: [CombinationKey.Ctrl], + onPress: () => { + this.cancle(); + }, + }), + new KeyListener({ + // X 限制只能在x轴移动 + value: 'KeyX', + global: true, + // combinations: [CombinationKey.Ctrl], + onPress: () => { + this.updateMoveLimit('x'); + }, + }), + new KeyListener({ + // Y 限制只能在y轴移动 + value: 'KeyY', + global: true, + // combinations: [CombinationKey.Ctrl], + onPress: () => { + this.updateMoveLimit('y'); + }, + }) + ); + } + + updateMoveLimit(limit?: 'x' | 'y'): void { + if (this.moveLimit === limit) { + this.moveLimit = undefined; + } else { + this.moveLimit = limit; + } + } + + init(): void { + if (this.running) return; + if (this.app.selectedGraphics.length === 0) { + throw new Error('没有选中图形,复制取消'); + } + this.running = true; + this.copys = []; + this.container.alpha = 0.5; + this.app.canvas.addChild(this.container); + const app = this.app; + this.app.selectedGraphics.forEach((g) => { + const template = app.getGraphicTemplatesByType(g.type); + const clone = template.clone(g); + this.copys.push(clone); + this.container.position.set(0, 0); + this.container.addChild(clone); + clone.repaint(); + }); + this.app.canvas.on('mousemove', this.onPointerMove, this); + this.app.canvas.on('mouseup', this.onFinish, this); + this.app.canvas.on('rightup', this.cancle, this); + this.keyListeners.forEach((kl) => { + this.app.addKeyboardListener(kl); + }); + } + + clear(): void { + this.running = false; + this.start = undefined; + this.moveLimit = undefined; + this.copys = []; + this.container.removeChildren(); + this.app.canvas.removeChild(this.container); + this.app.canvas.off('mousemove', this.onPointerMove, this); + this.app.canvas.off('mouseup', this.onFinish, this); + this.app.canvas.off('rightup', this.cancle, this); + this.keyListeners.forEach((kl) => { + this.app.removeKeyboardListener(kl); + }); + } + + onPointerMove(e: FederatedPointerEvent): void { + const cp = this.app.toCanvasCoordinates(e.global); + if (!this.start) { + this.start = cp; + } else { + if (this.moveLimit === 'x') { + const dx = cp.x - this.start.x; + this.container.position.x = dx; + this.container.position.y = 0; + } else if (this.moveLimit === 'y') { + const dy = cp.y - this.start.y; + this.container.position.x = 0; + this.container.position.y = dy; + } else { + const dx = cp.x - this.start.x; + const dy = cp.y - this.start.y; + this.container.position.x = dx; + this.container.position.y = dy; + } + } + } + + onFinish(): void { + console.log('复制确认'); + // 将图形添加到app + this.copys.forEach((g) => { + g.position.x += this.container.position.x; + g.position.y += this.container.position.y; + }); + this.app.addGraphics(...this.copys); + // 创建图形对象操作记录 + this.app.opRecord.record(new GraphicCreateOperation(this.app, this.copys)); + this.app.detectRelations(); + this.app.updateSelected(...this.copys); + this.clear(); + } + + cancle(): void { + console.log('复制操作取消'); + this.app.canvas.removeChild(this.container); + this.clear(); + } +} diff --git a/src/jl-graphic/plugins/GraphicEditPlugin.ts b/src/jl-graphic/plugins/GraphicEditPlugin.ts new file mode 100644 index 0000000..9b1cc5b --- /dev/null +++ b/src/jl-graphic/plugins/GraphicEditPlugin.ts @@ -0,0 +1,514 @@ +import { + Color, + Container, + DisplayObject, + Graphics, + IDestroyOptions, + IPointData, + Point, +} from 'pixi.js'; +import { JlGraphic } from '../core'; +import { DraggablePoint } from '../graphic'; +import { + calculateDistanceFromPointToLine, + calculateFootPointFromPointToLine, + calculateLineSegmentingPoint, + calculateMirrorPoint, + convertToBezierParams, + distance2, + linePoint, + pointPolygon, +} from '../utils'; +import { GraphicTransformEvent, ShiftData } from './GraphicTransformPlugin'; + +export abstract class GraphicEditPlugin< + DO extends DisplayObject = DisplayObject +> extends Container { + graphic: DO; + constructor(g: DO) { + super(); + this.graphic = g; + this.zIndex = 2; + this.sortableChildren = true; + this.graphic.on('transformstart', this.hideAll, this); + this.graphic.on('transformend', this.showAll, this); + this.graphic.on('repaint', this.showAll, this); + } + + destroy(options?: boolean | IDestroyOptions | undefined): void { + this.graphic.off('transformstart', this.hideAll, this); + this.graphic.off('transformend', this.showAll, this); + this.graphic.off('repaint', this.showAll, this); + super.destroy(options); + } + + abstract updateEditedPointsPosition(): void; + + hideAll() { + this.visible = false; + } + showAll() { + this.updateEditedPointsPosition(); + this.visible = true; + } +} + +export interface ILineGraphic extends JlGraphic { + get linePoints(): IPointData[]; + set linePoints(points: IPointData[]); +} + +export abstract class LineEditPlugin extends GraphicEditPlugin { + linePoints: IPointData[]; + editedPoints: DraggablePoint[] = []; + constructor(g: ILineGraphic) { + super(g); + this.linePoints = g.linePoints; + this.graphic.on('dataupdate', this.reset, this); + } + + destroy(options?: boolean | IDestroyOptions | undefined): void { + this.graphic.off('dataupdate', this.reset, this); + super.destroy(options); + } + + reset(): void { + this.linePoints = this.graphic.linePoints; + this.removeChildren(); + this.editedPoints.splice(0, this.editedPoints.length); + this.initEditPoints(); + } + + abstract initEditPoints(): void; +} + +export function getWayLineIndex( + points: IPointData[], + p: IPointData +): { start: number; end: number } { + let start = 0; + let end = 0; + let minDistance = 0; + for (let i = 1; i < points.length; i++) { + const sp = points[i - 1]; + const ep = points[i]; + let distance = calculateDistanceFromPointToLine(sp, ep, p); + distance = Math.round(distance * 100) / 100; + if (i == 1) { + minDistance = distance; + } + if (distance == minDistance) { + const minX = Math.min(sp.x, ep.x); + const maxX = Math.max(sp.x, ep.x); + const minY = Math.min(sp.y, ep.y); + const maxY = Math.max(sp.y, ep.y); + const point = calculateFootPointFromPointToLine(sp, ep, p); + if ( + point.x >= minX && + point.x <= maxX && + point.y >= minY && + point.y <= maxY + ) { + start = i - 1; + } + } + if (distance < minDistance) { + minDistance = distance; + start = i - 1; + } + } + end = start + 1; + return { start, end }; +} + +export function getWaypointRangeIndex( + points: IPointData[], + curve: boolean, + p: IPointData, + lineWidth: number +): { start: number; end: number } { + let start = 0; + let end = 0; + if (!curve) { + // 直线 + for (let i = 1; i < points.length; i++) { + const sp = points[i - 1]; + const ep = points[i]; + const fp = calculateFootPointFromPointToLine(sp, ep, p); + if (linePoint(sp, ep, fp, 1, true)) { + start = i - 1; + end = i; + break; + } + } + } else { + // 贝塞尔曲线 + const bps = convertToBezierParams(points); + for (let i = 0; i < bps.length; i++) { + const bp = bps[i]; + if (pointPolygon(p, [bp.p1, bp.cp1, bp.cp2, bp.p2], lineWidth)) { + start = i * 3; + end = start + 3; + } + } + // assertBezierPoints(points); + // for (let i = 0; i < points.length - 3; i += 3) { + // const p1 = points[i]; + // const cp1 = points[i + 1]; + // const cp2 = points[i + 2]; + // const p2 = points[i + 3]; + // if (pointPolygon(p, [p1, cp1, cp2, p2], lineWidth)) { + // start = i; + // end = i + 3; + // } + // } + } + return { start, end }; +} + +export type onEditPointCreate = ( + g: ILineGraphic, + dp: DraggablePoint, + index: number +) => void; + +export interface IEditPointOptions { + /** + * 编辑点创建处理 + */ + onEditPointCreate?: onEditPointCreate; +} + +/** + * 折线编辑(兼容线段) + */ +export class PolylineEditPlugin extends LineEditPlugin { + static Name = 'line_points_edit'; + options: IEditPointOptions; + constructor(g: ILineGraphic, options?: IEditPointOptions) { + super(g); + this.options = Object.assign({}, options); + this.name = PolylineEditPlugin.Name; + this.initEditPoints(); + } + + initEditPoints() { + const cps = this.graphic.localToCanvasPoints(...this.linePoints); + for (let i = 0; i < cps.length; i++) { + const p = cps[i]; + const dp = new DraggablePoint(p); + + dp.on('transforming', () => { + const tlp = this.graphic.canvasToLocalPoint(dp.position); + const cp = this.linePoints[i]; + cp.x = tlp.x; + cp.y = tlp.y; + this.graphic.repaint(); + }); + if (this.options.onEditPointCreate) { + this.options.onEditPointCreate(this.graphic, dp, i); + } + this.editedPoints.push(dp); + } + this.addChild(...this.editedPoints); + } + updateEditedPointsPosition() { + const cps = this.graphic.localToCanvasPoints(...this.linePoints); + if (cps.length === this.editedPoints.length) { + for (let i = 0; i < cps.length; i++) { + const cp = cps[i]; + this.editedPoints[i].position.copyFrom(cp); + } + } + } +} + +export interface BezierCurveEditPointOptions extends IEditPointOptions { + // 曲线控制点辅助连线颜色 + auxiliaryLineColor?: string; + // // 拖拽点颜色 + // pointColor?: string; + // 连接点处是否平滑(点左右控制点是否在一条直线),默认true + smooth?: boolean; + // 控制点是否完全对称(对称必平滑) + symmetry?: boolean; +} + +export interface ICompleteBezierCurveEditPointOptions + extends BezierCurveEditPointOptions { + smooth: boolean; +} + +export function addWayPoint( + graphic: ILineGraphic, + curve: boolean, + start: number, + end: number, + p: IPointData +) { + if (!curve) { + addLineWayPoint(graphic, start, end, p); + } else { + addBezierWayPoint(graphic, start, end, p); + } +} + +export function addLineWayPoint( + graphic: ILineGraphic, + start: number, + end: number, + p: IPointData +) { + const linePoints = graphic.linePoints; + const points = linePoints.slice(0, start + 1); + points.push(new Point(p.x, p.y)); + points.push(...linePoints.slice(end)); + graphic.linePoints = points; +} + +export function addPolygonSegmentingPoint( + graphic: ILineGraphic, + start: number, + end: number, + knife = 2 +) { + const linePoints = graphic.linePoints; + const points = linePoints.slice(0, start + 1); + points.push( + ...calculateLineSegmentingPoint(linePoints[start], linePoints[end], knife) + ); + points.push(...linePoints.slice(end)); + graphic.linePoints = points; +} + +function assertBezierWayPoint(i: number) { + const c = i % 3; + if (c !== 0) { + throw new Error(`i=${i}的点不是路径点`); + } +} + +export function addBezierWayPoint( + graphic: ILineGraphic, + start: number, + end: number, + p: IPointData +) { + if (start === end) { + console.error('添加贝塞尔曲线路径点开始结束点相等', start); + throw new Error('开始结束点不能一致'); + } + assertBezierWayPoint(start); + assertBezierWayPoint(end); + const linePoints = graphic.linePoints; + const points = linePoints.slice(0, start + 2); + const ap = new Point(p.x, p.y); + points.push(ap.clone(), ap.clone(), ap.clone()); + points.push(...linePoints.slice(end - 1)); + graphic.linePoints = points; +} + +export function removeWayPoint( + graphic: ILineGraphic, + curve: boolean, + i: number +) { + if (!curve) { + removeLineWayPoint(graphic, i); + } else { + removeBezierWayPoint(graphic, i); + } +} + +export function removeLineWayPoint(graphic: ILineGraphic, i: number) { + const linePoints = graphic.linePoints; + if (linePoints.length > 2) { + const points = linePoints.slice(0, i); + points.push(...linePoints.slice(i + 1)); + graphic.linePoints = points; + } +} + +export function removeBezierWayPoint(graphic: ILineGraphic, i: number) { + let points; + const linePoints = graphic.linePoints; + const c = i % 3; + if (c !== 0) { + throw new Error(`i=${i}的点${linePoints[i]}不是路径点`); + } + if (i === 0) { + // 第一个点 + if (linePoints.length > 4) { + points = linePoints.slice(3); + } else { + console.error('不能移除:剩余点数不足'); + } + } else if (i === linePoints.length - 1) { + // 最后一个点 + if (linePoints.length > 4) { + points = linePoints.slice(0, linePoints.length - 3); + } else { + console.error('无法移除:剩余点数不足'); + } + } else { + // 中间点 + points = linePoints.slice(0, i - 1); + points.push(...linePoints.slice(i + 2)); + } + if (points) { + graphic.linePoints = points; + } +} + +/** + * 清除路径点(只留端点),适用于直线和贝塞尔曲线 + * @param graphic + * @param curve + */ +export function clearWayPoint(graphic: ILineGraphic, curve: boolean) { + const linePoints = graphic.linePoints; + if (!curve) { + if (linePoints.length > 2) { + const points = linePoints.slice(0, 1); + points.push(...linePoints.slice(-1)); + graphic.linePoints = points; + } + } else { + if (linePoints.length > 4) { + const points = linePoints.slice(0, 2); + points.push(...linePoints.slice(-2)); + graphic.linePoints = points; + } + } +} + +/** + * 贝塞尔曲线编辑 + */ +export class BezierCurveEditPlugin extends LineEditPlugin { + static Name = 'bezier_curve_points_edit'; + options: ICompleteBezierCurveEditPointOptions; + // 曲线控制点辅助线 + auxiliaryLines: Graphics[] = []; + constructor(g: ILineGraphic, options?: BezierCurveEditPointOptions) { + super(g); + this.options = Object.assign({}, { smooth: true }, options); + this.name = BezierCurveEditPlugin.Name; + this.initEditPoints(); + } + + reset(): void { + this.auxiliaryLines.splice(0, this.auxiliaryLines.length); + super.reset(); + } + + initEditPoints() { + // console.log('initEditPoints'); + const cps = this.graphic.localToCanvasPoints(...this.linePoints); + for (let i = 0; i < cps.length; i++) { + const p = cps[i]; + const dp = new DraggablePoint(p); + const startOrEnd = i == 0 || i == cps.length - 1; + const c = i % 3; + if (c === 1) { + // 前一路径点的控制点 + dp.zIndex = 2; + const fp = cps[i - 1]; + const line = new Graphics(); + this.drawAuxiliaryLine(line, fp, p); + this.auxiliaryLines.push(line); + } else if (c === 2) { + // 后一路径点的控制点 + dp.zIndex = 3; + const np = cps[i + 1]; + const line = new Graphics(); + this.drawAuxiliaryLine(line, p, np); + this.auxiliaryLines.push(line); + } + dp.on('transforming', (e: GraphicTransformEvent) => { + const tlp = this.graphic.canvasToLocalPoint(dp.position); + const cp = this.linePoints[i]; + cp.x = tlp.x; + cp.y = tlp.y; + if (this.options.smooth || this.options.symmetry) { + if (c === 0 && !startOrEnd) { + const shiftData = e.getData(); + const fp = this.linePoints[i - 1]; + const np = this.linePoints[i + 1]; + fp.x = fp.x + shiftData.dx; + fp.y = fp.y + shiftData.dy; + np.x = np.x + shiftData.dx; + np.y = np.y + shiftData.dy; + } else if (c === 1 && i !== 1) { + const bp = this.linePoints[i - 1]; + const fp2 = this.linePoints[i - 2]; + let mp; + if (this.options.symmetry) { + mp = calculateMirrorPoint(bp, cp); + } else { + const distance = distance2(bp, fp2); + mp = calculateMirrorPoint(bp, cp, distance); + } + fp2.x = mp.x; + fp2.y = mp.y; + } else if (c === 2 && i !== cps.length - 2) { + const bp = this.linePoints[i + 1]; + const np2 = this.linePoints[i + 2]; + let mp; + if (this.options.symmetry) { + mp = calculateMirrorPoint(bp, cp); + } else { + const distance = distance2(bp, np2); + mp = calculateMirrorPoint(bp, cp, distance); + } + np2.x = mp.x; + np2.y = mp.y; + } + } + this.graphic.repaint(); + }); + if (this.options.onEditPointCreate) { + this.options.onEditPointCreate(this.graphic, dp, i); + } + this.editedPoints.push(dp); + if (this.auxiliaryLines.length > 0) { + this.addChild(...this.auxiliaryLines); + } + } + this.addChild(...this.editedPoints); + } + + drawAuxiliaryLine(line: Graphics, p1: IPointData, p2: IPointData) { + line.clear(); + if (this.options.auxiliaryLineColor) { + line.lineStyle(1, new Color(this.options.auxiliaryLineColor)); + } else { + line.lineStyle(1, new Color('blue')); + } + line.moveTo(p1.x, p1.y); + line.lineTo(p2.x, p2.y); + } + + updateEditedPointsPosition() { + const cps = this.graphic.localToCanvasPoints(...this.linePoints); + if (cps.length === this.editedPoints.length) { + for (let i = 0; i < cps.length; i++) { + const cp = cps[i]; + this.editedPoints[i].position.copyFrom(cp); + const c = i % 3; + const d = Math.floor(i / 3); + if (c === 1 || c === 2) { + const li = d * 2 + c - 1; + const line = this.auxiliaryLines[li]; + if (c === 1) { + const fp = cps[i - 1]; + this.drawAuxiliaryLine(line, fp, cp); + } else { + const np = cps[i + 1]; + this.drawAuxiliaryLine(line, cp, np); + } + } + } + } + } +} diff --git a/src/jl-graphic/plugins/GraphicTransformPlugin.ts b/src/jl-graphic/plugins/GraphicTransformPlugin.ts new file mode 100644 index 0000000..e80025d --- /dev/null +++ b/src/jl-graphic/plugins/GraphicTransformPlugin.ts @@ -0,0 +1,899 @@ +import { + Container, + DisplayObject, + Graphics, + IDestroyOptions, + Point, + Polygon, +} from 'pixi.js'; +import { + AppDragEvent, + InteractionPluginBase, + InteractionPluginType, + KeyListener, +} from '.'; +import { GraphicApp } from '../app'; +import { JlGraphic } from '../core'; +import { AbsorbablePosition, VectorText } from '../graphic'; +import { DraggablePoint } from '../graphic/DraggablePoint'; +import { + angleToAxisx, + calculateLineMidpoint, + convertRectangleToPolygonPoints, + distance, + recursiveChildren, +} from '../utils'; + +export class ShiftData { + /** + * 起始位置 + */ + startPosition: Point; + /** + * 上一次终点位置 + */ + lastPosition?: Point; + /** + * 当前位置 + */ + currentPosition?: Point; + constructor( + startPosition: Point, + currentPosition?: Point, + lastPosition?: Point + ) { + this.startPosition = startPosition; + this.lastPosition = lastPosition; + this.currentPosition = currentPosition; + } + static new( + startPosition: Point, + currentPosition?: Point, + lastPosition?: Point + ) { + return new ShiftData(startPosition, currentPosition, lastPosition); + } + + public get dx(): number { + if (!this.lastPosition || !this.currentPosition) { + throw new Error('错误的位移数据或阶段'); + } + return this.currentPosition.x - this.lastPosition.x; + } + + public get dy(): number { + if (!this.lastPosition || !this.currentPosition) { + throw new Error('错误的位移数据或阶段'); + } + return this.currentPosition.y - this.lastPosition.y; + } + + public get dsx(): number { + if (!this.currentPosition) { + throw new Error('错误的位移数据或阶段'); + } + return this.currentPosition.x - this.startPosition.x; + } + + public get dsy(): number { + if (!this.currentPosition) { + throw new Error('错误的位移数据或阶段'); + } + return this.currentPosition.y - this.startPosition.y; + } +} + +export class ScaleData { + start: Point; + current?: Point; + last?: Point; + constructor(start: Point, current?: Point, last?: Point) { + this.start = start; + this.current = current; + this.last = last; + } + static new(start: Point, current?: Point, last?: Point) { + return new ScaleData(start, current, last); + } +} + +export type TransformData = ShiftData | null; + +/** + * 图形平移事件 + */ +export class GraphicTransformEvent { + /** + * 图形对象 + */ + target: DisplayObject; + type: 'shift' | 'rotate' | 'scale' | 'skew'; + data: TransformData; + + constructor( + target: DisplayObject, + type: 'shift' | 'rotate' | 'scale' | 'skew', + data: TransformData + ) { + this.target = target; + this.type = type; + this.data = data; + } + + getData(): D { + return this.data as D; + } + + static shift(target: DisplayObject, data: ShiftData) { + return new GraphicTransformEvent(target, 'shift', data); + } + + static scale(target: DisplayObject) { + return new GraphicTransformEvent(target, 'scale', null); + } + + static rotate(target: DisplayObject) { + return new GraphicTransformEvent(target, 'rotate', null); + } + + static skew(target: DisplayObject) { + return new GraphicTransformEvent(target, 'skew', null); + } + + isShift(): boolean { + return this.type === 'shift'; + } + isRotate(): boolean { + return this.type === 'rotate'; + } + isScale(): boolean { + return this.type === 'scale'; + } + isSkew(): boolean { + return this.type === 'skew'; + } +} + +export class GraphicTransformPlugin extends InteractionPluginBase { + static Name = '__graphic_transform_plugin'; + + /** + * 可吸附位置列表 + */ + absorbablePositions?: AbsorbablePosition[]; + apContainer: Container; + static AbsorbablePosisiontsName = '__AbsorbablePosisionts'; + + constructor(app: GraphicApp) { + super(app, GraphicTransformPlugin.Name, InteractionPluginType.Other); + this.apContainer = new Container(); + this.apContainer.name = GraphicTransformPlugin.AbsorbablePosisiontsName; + this.app.canvas.addAssistantAppend(this.apContainer); + app.on('options-update', (options) => { + if (options.absorbablePositions) { + this.absorbablePositions = this.filterAbsorbablePositions( + options.absorbablePositions + ); + } + }); + } + + /** + * 过滤重复的吸附位置 + * @param positions + * @returns + */ + filterAbsorbablePositions( + positions: AbsorbablePosition[] + ): AbsorbablePosition[] { + const aps: AbsorbablePosition[] = []; + for (let i = 0; i < positions.length; i++) { + const ap1 = positions[i]; + let ap: AbsorbablePosition | null = ap1; + for (let j = positions.length - 1; j > i; j--) { + const ap2 = positions[j]; + if (ap.isOverlapping(ap2) && ap.compareTo(ap2) <= 0) { + ap = null; + break; + } + } + if (ap != null) { + aps.push(ap); + } + } + // console.log(positions, aps); + return aps; + } + + static new(app: GraphicApp) { + return new GraphicTransformPlugin(app); + } + + bind(): void { + this.app.on('drag_op_start', this.onDragStart, this); + this.app.on('drag_op_move', this.onDragMove, this); + this.app.on('drag_op_end', this.onDragEnd, this); + this.app.on('graphicselectedchange', this.onGraphicSelectedChange, this); + this.app.on( + 'graphicchildselectedchange', + this.onGraphicSelectedChange, + this + ); + } + unbind(): void { + this.app.off('drag_op_start', this.onDragStart, this); + this.app.off('drag_op_move', this.onDragMove, this); + this.app.off('drag_op_end', this.onDragEnd, this); + this.app.off('graphicselectedchange', this.onGraphicSelectedChange, this); + this.app.off( + 'graphicchildselectedchange', + this.onGraphicSelectedChange, + this + ); + } + + getDraggedTargets(e: AppDragEvent): DisplayObject[] { + const targets: DisplayObject[] = []; + if (e.target.isGraphicChild() && e.target.selected && e.target.draggable) { + const graphic = e.target.getGraphic() as JlGraphic; + // 图形子元素 + recursiveChildren(graphic, (child) => { + if (child.selected && child.draggable) { + targets.push(child); + } + }); + } else if ( + (e.target.isGraphic() || e.target.isGraphicChild()) && + e.target.getGraphic()?.draggable + ) { + // 图形对象 + targets.push(...this.app.selectedGraphics); + } else if (e.target.draggable) { + targets.push(e.target); + } + return targets; + } + onDragStart(e: AppDragEvent) { + if (!e.target.isCanvas() && e.isLeftButton) { + const targets: DisplayObject[] = this.getDraggedTargets(e); + if (targets.length > 0) { + targets.forEach((target) => { + target.shiftStartPoint = target.position.clone(); + target.emit( + 'transformstart', + GraphicTransformEvent.shift( + target, + ShiftData.new(target.shiftStartPoint) + ) + ); + }); + // 显示吸附图形 + if (this.absorbablePositions && this.absorbablePositions.length > 0) { + this.apContainer.removeChildren(); + this.apContainer.addChild(...this.absorbablePositions); + } + } + } + } + + onDragMove(e: AppDragEvent) { + if (!e.target.isCanvas() && e.isLeftButton) { + const targets: DisplayObject[] = this.getDraggedTargets(e); + if (targets.length > 0) { + // 处理位移 + targets.forEach((target) => { + if (target.shiftStartPoint) { + target.shiftLastPoint = target.position.clone(); + const { dx, dy } = e.toTargetShiftLen(target.parent); + target.position.set( + target.shiftStartPoint.x + dx, + target.shiftStartPoint.y + dy + ); + } + }); + // 处理吸附 + if (this.absorbablePositions) { + for (let i = 0; i < this.absorbablePositions.length; i++) { + const ap = this.absorbablePositions[i]; + ap.tryAbsorb(...targets); + } + } + // 事件发布 + targets.forEach((target) => { + if (target.shiftStartPoint && target.shiftLastPoint) { + target.emit( + 'transforming', + GraphicTransformEvent.shift( + target, + ShiftData.new( + target.shiftStartPoint, + target.position.clone(), + target.shiftLastPoint + ) + ) + ); + } + }); + } + } + } + + onDragEnd(e: AppDragEvent) { + if (!e.target.isCanvas() && e.isLeftButton) { + const targets: DisplayObject[] = this.getDraggedTargets(e); + targets.forEach((target) => { + if (target.shiftStartPoint) { + target.emit( + 'transformend', + GraphicTransformEvent.shift( + target, + ShiftData.new(target.shiftStartPoint, target.position.clone()) + ) + ); + } + target.shiftStartPoint = null; + }); + } + this.clearCache(); + } + + /** + * 清理缓存 + */ + clearCache() { + // 移除吸附图形 + this.absorbablePositions = []; + this.apContainer.removeChildren(); + } + + onGraphicSelectedChange(g: DisplayObject, selected: boolean) { + let br = g.getAssistantAppend(BoundsGraphic.Name); + if (!br) { + // 绘制辅助包围框 + br = new BoundsGraphic(g); + } + + if (selected) { + if (br) { + br.redraw(); + br.visible = true; + } + } else { + if (br) { + br.visible = false; + } + } + if (g.scalable || g.rotatable) { + // 缩放点 + let sp = g.getAssistantAppend(TransformPoints.Name); + if (!sp) { + sp = new TransformPoints(g); + } + if (selected) { + sp.update(); + sp.visible = true; + } else { + sp.visible = false; + } + } + } + + // onGraphicChildSelectedChange(child: DisplayObject, selected: boolean) { + // let br = child.getAssistantAppend(BoundsGraphic.Name); + // if (!br) { + // // 绘制辅助包围框 + // br = new BoundsGraphic(child); + // } + // if (selected) { + // br.redraw(); + // br.visible = true; + // } else { + // br.visible = false; + // } + // } +} + +/** + * 缩放、旋转辅助 + */ +export class TransformPoints extends Container { + static Name = 'transformPoints'; + static MinLength = 40; + static LeftTopName = 'lt-scale-point'; + static TopName = 't-scale-point'; + static RightTopName = 'rt-scale-point'; + static RightName = 'r-scale-point'; + static RightBottomName = 'rb-scale-point'; + static BottomName = 'b-scale-point'; + static LeftBottomName = 'lb-scale-point'; + static LeftName = 'l-scale-point'; + + static RotateName = 'rotate-point'; + obj: DisplayObject; + + ltScalePoint: DraggablePoint; + ltLocal: Point = new Point(); + tScalePoint: DraggablePoint; + tLocal: Point = new Point(); + tCanvas: Point = new Point(); + rtScalePoint: DraggablePoint; + rtLocal: Point = new Point(); + rScalePoint: DraggablePoint; + rLocal: Point = new Point(); + rbScalePoint: DraggablePoint; + rbLocal: Point = new Point(); + bScalePoint: DraggablePoint; + bLocal: Point = new Point(); + lbScalePoint: DraggablePoint; + lbLocal: Point = new Point(); + lScalePoint: DraggablePoint; + lLocal: Point = new Point(); + originScale: Point = new Point(); + scalePivot: Point = new Point(); + + /** + * 旋转拖拽点 + */ + rotatePoint: DraggablePoint; + /** + * 旋转中心坐标 + */ + rotatePivot: Point; + /** + * 起始旋转坐标 + */ + rotateLastPoint: Point; + /** + * 起始图形角度 + */ + startAngle = 0; + /** + * 当前角度信息文本辅助 + */ + angleAssistantText: VectorText; + /** + * 旋转角度步长 + */ + angleStep = 1; + /** + * 修改旋转步长键盘监听 + */ + rotateAngleStepKeyListeners: KeyListener[] = []; + + constructor(obj: DisplayObject) { + super(); + this.obj = obj; + this.name = TransformPoints.Name; + + this.angleAssistantText = new VectorText(''); + this.angleAssistantText.setVectorFontSize(16); + this.angleAssistantText.anchor.set(0.5); + + // 创建缩放拖拽点 + this.ltScalePoint = new DraggablePoint(new Point()); + this.ltScalePoint.name = TransformPoints.LeftTopName; + this.addChild(this.ltScalePoint); + this.tScalePoint = new DraggablePoint(new Point()); + this.tScalePoint.name = TransformPoints.TopName; + this.addChild(this.tScalePoint); + this.rtScalePoint = new DraggablePoint(new Point()); + this.rtScalePoint.name = TransformPoints.RightTopName; + this.addChild(this.rtScalePoint); + this.rScalePoint = new DraggablePoint(new Point()); + this.rScalePoint.name = TransformPoints.RightName; + this.addChild(this.rScalePoint); + this.rbScalePoint = new DraggablePoint(new Point()); + this.rbScalePoint.name = TransformPoints.RightBottomName; + this.addChild(this.rbScalePoint); + this.bScalePoint = new DraggablePoint(new Point()); + this.bScalePoint.name = TransformPoints.BottomName; + this.addChild(this.bScalePoint); + this.lbScalePoint = new DraggablePoint(new Point()); + this.lbScalePoint.name = TransformPoints.LeftBottomName; + this.addChild(this.lbScalePoint); + this.lScalePoint = new DraggablePoint(new Point()); + this.lScalePoint.name = TransformPoints.LeftName; + this.addChild(this.lScalePoint); + this.obj.on('transformstart', this.onObjTransformStart, this); + this.obj.on('transformend', this.onObjTransformEnd, this); + + if (this.obj.children && this.obj.children.length > 0) { + recursiveChildren(this.obj as Container, (child) => { + child.on('transformstart', this.onObjTransformStart, this); + child.on('transformend', this.onObjTransformEnd, this); + }); + } + const pg = this.obj.getGraphic(); + if (pg != null) { + pg.on('transformstart', this.onObjTransformStart, this); + pg.on('transformend', this.onObjTransformEnd, this); + } + + this.obj.on('repaint', this.onGraphicRepaint, this); + this.children.forEach((dp) => { + dp.on('transformstart', this.onScaleDragStart, this); + dp.on('transforming', this.onScaleDragMove, this); + dp.on('transformend', this.onScaleDragEnd, this); + }); + + // 创建旋转拖拽点 + this.rotatePoint = new DraggablePoint(new Point()); + this.addChild(this.rotatePoint); + this.rotatePoint.on('transformstart', this.onRotateStart, this); + this.rotatePoint.on('transforming', this.onRotateMove, this); + this.rotatePoint.on('transformend', this.onRotateEnd, this); + this.rotatePivot = new Point(); + this.rotateLastPoint = new Point(); + // 初始化旋转角度修改键盘监听器 + for (let i = 1; i < 10; i++) { + this.rotateAngleStepKeyListeners.push( + KeyListener.create({ + value: '' + i, + onPress: () => { + // console.log('修改角度step'); + this.angleStep = i; + }, + }) + ); + } + + this.obj.addAssistantAppend(this); + } + + onObjTransformStart() { + this.visible = false; + } + onObjTransformEnd() { + this.update(); + this.visible = true; + } + onGraphicRepaint() { + if (this.visible) { + this.update(); + } + } + + /** + * 旋转开始 + * @param de + */ + onRotateStart(de: GraphicTransformEvent) { + this.hideAll(); + const assistantPoint = this.obj.localToCanvasPoint(this.obj.pivot); + this.rotatePivot.copyFrom(assistantPoint); + this.rotateLastPoint.copyFrom(de.target.position); + this.startAngle = this.obj.angle; + const app = this.obj.getGraphicApp(); + this.rotateAngleStepKeyListeners.forEach((listener) => + app.addKeyboardListener(listener) + ); + this.obj.emit('transformstart', GraphicTransformEvent.rotate(this.obj)); + // app.emit('transformstart', app.selectedGraphics); + this.obj.getCanvas().addAssistantAppends(this.angleAssistantText); + this.updateAngleAssistantText(de); + } + updateAngleAssistantText(de: GraphicTransformEvent) { + this.angleAssistantText.text = this.obj.angle + '°'; + let cursorPoint = de.data?.startPosition; + if (de.data?.currentPosition) { + cursorPoint = de.data?.currentPosition; + } + if (cursorPoint) { + this.angleAssistantText.position.x = cursorPoint.x; + this.angleAssistantText.position.y = cursorPoint.y - 10; + } + } + /** + * 旋转移动 + * @param de + */ + onRotateMove(de: GraphicTransformEvent) { + // 旋转角度计算逻辑:取锚点y负方向一点作为旋转点,求旋转点和锚点所形成的直线与x轴角度,此角度+90°即为最终旋转角度,再将旋转角度限制到(-180,180]之间 + let angle = angleToAxisx(this.rotatePivot, de.target.position); + angle = Math.floor(angle / this.angleStep) * this.angleStep; + const parentAngle = this.obj.parent.worldAngle; + angle = (angle + 90 - parentAngle) % 360; + if (angle > 180) { + angle = angle - 360; + } + this.obj.angle = angle; + this.updateAngleAssistantText(de); + // this.obj.emit('rotatemove', this.obj); + } + /** + * 旋转结束 + * @param de + */ + onRotateEnd() { + this.showAll(); + this.obj.getCanvas().removeAssistantAppends(this.angleAssistantText); + this.rotateAngleStepKeyListeners.forEach((listener) => + this.obj.getGraphicApp().removeKeyboardListener(listener) + ); + this.obj.emit('transformend', GraphicTransformEvent.rotate(this.obj)); + } + + /** + * 缩放开始 + */ + onScaleDragStart() { + this.hideAll(); + const points = convertRectangleToPolygonPoints(this.obj.getLocalBounds()); + const p0 = points[0]; + const p1 = points[1]; + const p2 = points[2]; + const p3 = points[3]; + this.scalePivot = this.obj.pivot.clone(); + this.ltLocal.copyFrom(p0); + this.tCanvas.copyFrom( + this.obj.localToCanvasPoint(calculateLineMidpoint(p0, p1)) + ); + this.tLocal.copyFrom(calculateLineMidpoint(p0, p1)); + this.rtLocal.copyFrom(p1); + this.rLocal.copyFrom(calculateLineMidpoint(p1, p2)); + this.rbLocal.copyFrom(p2); + this.bLocal.copyFrom(calculateLineMidpoint(p2, p3)); + this.lbLocal.copyFrom(p3); + this.lLocal.copyFrom(calculateLineMidpoint(p0, p3)); + this.originScale = this.obj.scale.clone(); + this.obj.emit('transformstart', GraphicTransformEvent.scale(this.obj)); + } + + onScaleDragMove(e: GraphicTransformEvent) { + // 缩放计算逻辑:共8个方向缩放点,根据所拖拽的方向: + // 1,计算缩放为1时的此点在拖拽开始时的位置到锚点x、y距离, + // 2,计算拖拽点的当前位置到锚点的x、y方向距离, + // PS:以上两个计算都是在local(也就是图形对象本地)坐标系, + // 用当前距离除以原始距离即为缩放比例 + const defaultScale = new Point(1, 1); + let originWidth = 0; + let originHeight = 0; + let width = 0; + let height = 0; + this.obj.scale.copyFrom(defaultScale); + const point = this.obj.toLocal( + e.target.parent.localToScreenPoint(e.target.position) + ); + if (e.target === this.ltScalePoint) { + // 左上角 + originWidth = Math.abs(this.ltLocal.x - this.scalePivot.x); + originHeight = Math.abs(this.ltLocal.y - this.scalePivot.y); + width = Math.abs(point.x - this.scalePivot.x); + height = Math.abs(point.y - this.scalePivot.y); + } else if (e.target == this.tScalePoint) { + // 上 + originHeight = Math.abs(this.tLocal.y - this.scalePivot.y); + height = Math.abs(point.y - this.scalePivot.y); + } else if (e.target == this.rtScalePoint) { + // 右上 + originWidth = Math.abs(this.rtLocal.x - this.scalePivot.x); + originHeight = Math.abs(this.rtLocal.y - this.scalePivot.y); + width = Math.abs(point.x - this.scalePivot.x); + height = Math.abs(point.y - this.scalePivot.y); + } else if (e.target == this.rScalePoint) { + // 右 + originWidth = Math.abs(this.rLocal.x - this.scalePivot.x); + width = Math.abs(point.x - this.scalePivot.x); + } else if (e.target == this.rbScalePoint) { + // 右下 + originWidth = Math.abs(this.rbLocal.x - this.scalePivot.x); + originHeight = Math.abs(this.rbLocal.y - this.scalePivot.y); + width = Math.abs(point.x - this.scalePivot.x); + height = Math.abs(point.y - this.scalePivot.y); + } else if (e.target == this.bScalePoint) { + // 下 + originHeight = Math.abs(this.bLocal.y - this.scalePivot.y); + height = Math.abs(point.y - this.scalePivot.y); + } else if (e.target == this.lbScalePoint) { + // 左下 + originWidth = Math.abs(this.lbLocal.x - this.scalePivot.x); + originHeight = Math.abs(this.lbLocal.y - this.scalePivot.y); + width = Math.abs(point.x - this.scalePivot.x); + height = Math.abs(point.y - this.scalePivot.y); + } else { + // 左 + originWidth = Math.abs(this.lLocal.x - this.scalePivot.x); + width = Math.abs(point.x - this.scalePivot.x); + } + // 计算缩放比例,并根据是否保持纵横比两种情况进行缩放处理 + const sx = originWidth == 0 ? this.originScale.x : width / originWidth; + const sy = originHeight == 0 ? this.originScale.y : height / originHeight; + // console.log(originWidth, originHeight, width, height, sx, sy); + if (this.obj.keepAspectRatio) { + let max = Math.max(sx, sy); + if (originWidth == 0) { + max = sy; + } else if (originHeight == 0) { + max = sx; + } + this.obj.scale.set(max, max); + } else { + this.obj.scale.x = sx; + this.obj.scale.y = sy; + } + } + + onScaleDragEnd() { + this.showAll(); + this.obj.emit('transformend', GraphicTransformEvent.scale(this.obj)); + } + + hideOthers(dg: DisplayObject) { + this.children.forEach((child) => { + if (child.name !== dg.name) { + child.visible = false; + } + }); + } + + hideAll() { + this.children.forEach((child) => (child.visible = false)); + } + + showAll() { + this.update(); + this.children.forEach((child) => (child.visible = true)); + } + + getObjBounds(): { width: number; height: number } { + const points = this.obj.localBoundsToCanvasPoints(); + const p0 = points[0]; + const p1 = points[1]; + const p3 = points[3]; + const width = distance(p0.x, p0.y, p1.x, p1.y); + const height = distance(p0.x, p0.y, p3.x, p3.y); + return { width, height }; + } + + /** + * 更新位置和cursor + * @returns + */ + update() { + if (this.obj.scalable) { + this.updateScalePoints(); + } + if (this.obj.rotatable) { + this.updateRotatePoint(); + } + } + + updateRotatePoint() { + const rect = this.obj.getLocalBounds(); + const lp = this.obj.pivot.clone(); + const dy = 10 / this.obj.scale.y; + lp.y = rect.y - dy; + const p = this.obj.localToCanvasPoint(lp); + this.rotatePoint.position.copyFrom(p); + } + + updateScalePoints() { + const points = this.obj.localBoundsToCanvasPoints(); + this.ltScalePoint.position.copyFrom(points[0]); + this.tScalePoint.position.copyFrom( + calculateLineMidpoint(points[0], points[1]) + ); + this.rtScalePoint.position.copyFrom(points[1]); + this.rScalePoint.position.copyFrom( + calculateLineMidpoint(points[1], points[2]) + ); + this.rbScalePoint.position.copyFrom(points[2]); + this.bScalePoint.position.copyFrom( + calculateLineMidpoint(points[2], points[3]) + ); + this.lbScalePoint.position.copyFrom(points[3]); + this.lScalePoint.position.copyFrom( + calculateLineMidpoint(points[3], points[0]) + ); + const angle = this.obj.worldAngle; + const angle360 = (360 + angle) % 360; + if ( + (angle >= -22.5 && angle <= 22.5) || + (angle360 >= 180 - 22.5 && angle360 <= 180 + 22.5) + ) { + this.ltScalePoint.cursor = 'nw-resize'; + this.tScalePoint.cursor = 'n-resize'; + this.rtScalePoint.cursor = 'ne-resize'; + this.rScalePoint.cursor = 'e-resize'; + this.rbScalePoint.cursor = 'se-resize'; + this.bScalePoint.cursor = 's-resize'; + this.lbScalePoint.cursor = 'sw-resize'; + this.lScalePoint.cursor = 'w-resize'; + } else if ( + (angle >= 22.5 && angle <= 67.5) || + (angle360 >= 180 + 22.5 && angle360 <= 180 + 67.5) + ) { + this.ltScalePoint.cursor = 'n-resize'; + this.tScalePoint.cursor = 'ne-resize'; + this.rtScalePoint.cursor = 'e-resize'; + this.rScalePoint.cursor = 'se-resize'; + this.rbScalePoint.cursor = 's-resize'; + this.bScalePoint.cursor = 'sw-resize'; + this.lbScalePoint.cursor = 'w-resize'; + this.lScalePoint.cursor = 'nw-resize'; + } else if ( + (angle >= 67.5 && angle < 112.5) || + (angle360 >= 180 + 67.5 && angle360 <= 180 + 112.5) + ) { + this.ltScalePoint.cursor = 'ne-resize'; + this.tScalePoint.cursor = 'e-resize'; + this.rtScalePoint.cursor = 'se-resize'; + this.rScalePoint.cursor = 's-resize'; + this.rbScalePoint.cursor = 'sw-resize'; + this.bScalePoint.cursor = 'w-resize'; + this.lbScalePoint.cursor = 'nw-resize'; + this.lScalePoint.cursor = 'n-resize'; + } else { + this.ltScalePoint.cursor = 'e-resize'; + this.tScalePoint.cursor = 'se-resize'; + this.rtScalePoint.cursor = 's-resize'; + this.rScalePoint.cursor = 'sw-resize'; + this.rbScalePoint.cursor = 'w-resize'; + this.bScalePoint.cursor = 'nw-resize'; + this.lbScalePoint.cursor = 'n-resize'; + this.lScalePoint.cursor = 'ne-resize'; + } + } +} + +/** + * 包围盒矩形图形,现使用外边框转画布多边形实现 + */ +export class BoundsGraphic extends Graphics { + static Name = '_BoundsRect'; + static BoundsLineStyle = { + width: 1, + color: 0x29b6f2, + alpha: 1, + }; + obj: DisplayObject; + constructor(graphic: DisplayObject) { + super(); + this.obj = graphic; + this.name = BoundsGraphic.Name; + this.visible = false; + this.obj.on('transformstart', this.onObjTransformStart, this); + this.obj.on('transformend', this.onObjTransformEnd, this); + if (this.obj.children && this.obj.children.length > 0) { + recursiveChildren(this.obj as Container, (child) => { + child.on('transformstart', this.onObjTransformStart, this); + child.on('transformend', this.onObjTransformEnd, this); + }); + } + const pg = this.obj.getGraphic(); + if (pg != null) { + pg.on('transformstart', this.onObjTransformStart, this); + pg.on('transformend', this.onObjTransformEnd, this); + } + this.obj.on('repaint', this.onGraphicRepaint, this); + graphic.addAssistantAppend(this); + } + + onObjTransformStart(): void { + this.visible = false; + } + onObjTransformEnd(): void { + this.redraw(); + this.visible = true; + } + + onGraphicRepaint(): void { + if (this.visible) { + this.redraw(); + this.visible = true; + } + } + + destroy(options?: boolean | IDestroyOptions | undefined): void { + if (this.obj.isGraphic()) { + this.obj.off('repaint', this.onGraphicRepaint, this); + } + super.destroy(options); + } + + redraw() { + this.visible = false; // 屏蔽包围框本身 + const bounds = new Polygon(this.obj.localBoundsToCanvasPoints()); + this.clear().lineStyle(BoundsGraphic.BoundsLineStyle).drawShape(bounds); + } +} diff --git a/src/jl-graphic/plugins/InteractionPlugin.ts b/src/jl-graphic/plugins/InteractionPlugin.ts new file mode 100644 index 0000000..70226d6 --- /dev/null +++ b/src/jl-graphic/plugins/InteractionPlugin.ts @@ -0,0 +1,489 @@ +import { + DisplayObject, + FederatedMouseEvent, + FederatedPointerEvent, + Point, +} from 'pixi.js'; +import { GraphicApp, IGraphicAppConfig } from '../app/JlGraphicApp'; +import { JlGraphic } from '../core/JlGraphic'; + +export enum InteractionPluginType { + App = 'app', + Graphic = 'graphic', + Other = 'other', +} + +/** + * 交互插件 + */ +export interface InteractionPlugin { + readonly _type: string; + name: string; // 唯一标识 + app: GraphicApp; + + /** + * 恢复 + */ + resume(): void; + /** + * 停止 + */ + pause(): void; + /** + * 是否生效 + */ + isActive(): boolean; + isAppPlugin(): boolean; + isOtherPlugin(): boolean; + isGraphicPlugin(): boolean; +} + +export abstract class InteractionPluginBase implements InteractionPlugin { + readonly _type: string; + name: string; // 唯一标识 + app: GraphicApp; + _pause: boolean; + + constructor(app: GraphicApp, name: string, type: string) { + this._type = type; + this.app = app; + this.name = name; + this._pause = true; + app.registerInteractionPlugin(this); + } + + /** + * 恢复 + */ + resume(): void { + this.bind(); + this._pause = false; + this.app.emit('interaction-plugin-resume', this); + } + /** + * 停止 + */ + pause(): void { + this.unbind(); + this._pause = true; + this.app.emit('interaction-plugin-pause', this); + } + + abstract bind(): void; + abstract unbind(): void; + /** + * 是否生效 + */ + isActive(): boolean { + return !this._pause; + } + isGraphicPlugin(): boolean { + return this._type === InteractionPluginType.Graphic; + } + isAppPlugin(): boolean { + return this._type === InteractionPluginType.App; + } + isOtherPlugin(): boolean { + return this._type === InteractionPluginType.Other; + } +} + +export abstract class OtherInteractionPlugin extends InteractionPluginBase { + constructor(app: GraphicApp, name: string) { + super(app, name, InteractionPluginType.Other); + } +} + +export class AppDragEvent { + app: GraphicApp; + type: 'start' | 'move' | 'end'; + target: DisplayObject; + original: FederatedPointerEvent; + start: Point; // 画布坐标 + constructor( + app: GraphicApp, + type: 'start' | 'move' | 'end', + target: DisplayObject, + original: FederatedPointerEvent, + start: Point + ) { + this.app = app; + this.type = type; + this.target = target; + this.original = original; + this.start = start; + } + + public get isMouse(): boolean { + return this.original.pointerType === 'mouse'; + } + + public get isLeftButton(): boolean { + return ( + this.isMouse && + ((this.original.button === -1 && this.original.buttons === 1) || + (this.original.button === 0 && this.original.buttons === 0)) + ); + } + + public get isRightButton(): boolean { + return ( + this.isMouse && + ((this.original.button === -1 && this.original.buttons === 2) || + (this.original.button === 2 && this.original.buttons === 0)) + ); + } + + public get isMiddleButton(): boolean { + return ( + this.isMouse && + ((this.original.button === -1 && this.original.buttons === 4) || + (this.original.button === 1 && this.original.buttons === 0)) + ); + } + + public get isTouch(): boolean { + return this.original.pointerType === 'touch'; + } + + /** + * 终点坐标(画布坐标) + */ + public get end(): Point { + return this.app.toCanvasCoordinates(this.original.global); + } + + public get dx(): number { + const move = this.original.movement; + return move.x / this.app.viewport.scaled; + } + + public get dy(): number { + const move = this.original.movement; + return move.y / this.app.viewport.scaled; + } + + public get dsx(): number { + return this.end.x - this.start.x; + } + + public get dsy(): number { + return this.end.y - this.start.y; + } + + /** + * 转换为目标对象的位移距离 + */ + toTargetShiftLen(target: DisplayObject): { dx: number; dy: number } { + const sl = target.canvasToLocalPoint(this.start); + const el = target.canvasToLocalPoint(this.end); + return { dx: el.x - sl.x, dy: el.y - sl.y }; + } +} + +/** + * 拖拽操作插件 + */ +export class DragPlugin extends OtherInteractionPlugin { + static Name = '__drag_operation_plugin'; + private threshold = 3; + target: DisplayObject | null = null; + start: Point | null = null; + startClientPoint: Point | null = null; + drag = false; + constructor(app: GraphicApp) { + super(app, DragPlugin.Name); + app.on('options-update', (options: IGraphicAppConfig) => { + if (options.threshold !== undefined) { + this.threshold = options.threshold; + } + }); + } + static new(app: GraphicApp) { + return new DragPlugin(app); + } + bind(): void { + const canvas = this.app.canvas; + canvas.on('pointerdown', this.onPointerDown, this); + } + unbind(): void { + const canvas = this.app.canvas; + canvas.off('pointerdown', this.onPointerDown, this); + canvas.off('pointerup', this.onPointerUp, this); + canvas.off('pointerupoutside', this.onPointerUp, this); + } + onPointerDown(e: FederatedPointerEvent) { + this.target = e.target as DisplayObject; + this.start = this.app.toCanvasCoordinates(e.global); + this.startClientPoint = e.global.clone(); + const canvas = this.app.canvas; + canvas.on('pointermove', this.onPointerMove, this); + canvas.on('pointerup', this.onPointerUp, this); + canvas.on('pointerupoutside', this.onPointerUp, this); + } + onPointerMove(e: FederatedPointerEvent) { + if (this.start && this.startClientPoint) { + const current = e.global; + const sgp = this.startClientPoint; + const dragStart = + Math.abs(current.x - sgp.x) > this.threshold || + Math.abs(current.y - sgp.y) > this.threshold; + if (this.target && this.start && !this.drag && dragStart) { + this.app.emit( + 'drag_op_start', + new AppDragEvent(this.app, 'start', this.target, e, this.start) + ); + this.drag = true; + } + + // drag移动处理 + if (this.target && this.drag && this.start) { + // console.log('drag move', e.movement); + this.app.emit( + 'drag_op_move', + new AppDragEvent(this.app, 'move', this.target, e, this.start) + ); + } + } + } + + onPointerUp(e: FederatedPointerEvent) { + if (this.target && this.drag && this.start) { + // console.log('drag end'); + this.app.emit( + 'drag_op_end', + new AppDragEvent(this.app, 'end', this.target, e, this.start) + ); + } else if (this.target && this.start && !this.drag) { + // this.target.emit('click', this.target); + const ade = new AppDragEvent(this.app, 'end', this.target, e, this.start); + const graphic = this.target.getGraphic(); + if (ade.isRightButton) { + this.target.emit('_rightclick', e); + if (graphic != null) { + graphic.emit('_rightclick', e); + } + } else if (ade.isLeftButton) { + this.target.emit('_leftclick', e); + if (graphic != null) { + graphic.emit('_leftclick', e); + } + } + } + const canvas = this.app.canvas; + canvas.off('mousemove', this.onPointerMove, this); + canvas.off('mouseup', this.onPointerUp, this); + canvas.off('mouseupoutside', this.onPointerUp, this); + this.clearCache(); + } + /** + * 清理缓存 + */ + clearCache() { + this.drag = false; + this.start = null; + this.startClientPoint = null; + this.target = null; + } +} + +/** + * 视口移动插件 + */ +export class ViewportMovePlugin extends OtherInteractionPlugin { + static Name = '__viewport_move_plugin'; + + static MoveInterval = 20; // 移动间隔,单位ms + static TriggerRange = 100; // 边界触发范围,单位px + static DefaultMoveSpeed = 200 / ViewportMovePlugin.MoveInterval; // 默认移动速度 + + moveHandler: NodeJS.Timeout | null = null; + moveSpeedx = 0; + moveSpeedy = 0; + + constructor(app: GraphicApp) { + super(app, ViewportMovePlugin.Name); + } + + static new(app: GraphicApp): ViewportMovePlugin { + return new ViewportMovePlugin(app); + } + pause(): void { + super.pause(); + this.stopMove(); + } + bind(): void { + this.app.canvas.on('pointermove', this.viewportMove, this); + } + + unbind(): void { + this.app.canvas.off('pointermove', this.viewportMove, this); + } + + startMove(moveSpeedx: number, moveSpeedy: number) { + this.moveSpeedx = moveSpeedx; + this.moveSpeedy = moveSpeedy; + if (this.moveHandler == null) { + const viewport = this.app.viewport; + this.moveHandler = setInterval(() => { + viewport.moveCorner( + viewport.corner.x + this.moveSpeedx, + viewport.corner.y + this.moveSpeedy + ); + }, ViewportMovePlugin.MoveInterval); + } + } + + stopMove() { + if (this.moveHandler != null) { + clearInterval(this.moveHandler); + this.moveHandler = null; + this.app.canvas.cursor = 'auto'; + } + } + + private calculateBoundaryMoveSpeed(sp: Point): { + moveSpeedx: number; + moveSpeedy: number; + } { + let moveSpeedx = 0; + let moveSpeedy = 0; + const range = ViewportMovePlugin.TriggerRange; + const viewport = this.app.viewport; + if (sp.x < range) { + moveSpeedx = this.calculateMoveSpeed(sp.x - range); + } else if (sp.x > viewport.screenWidth - range) { + moveSpeedx = this.calculateMoveSpeed(sp.x + range - viewport.screenWidth); + } else { + moveSpeedx = 0; + } + if (sp.y < range) { + moveSpeedy = this.calculateMoveSpeed(sp.y - range); + } else if (sp.y > viewport.screenHeight - range) { + moveSpeedy = this.calculateMoveSpeed( + sp.y + range - viewport.screenHeight + ); + } else { + moveSpeedy = 0; + } + return { moveSpeedx, moveSpeedy }; + } + + calculateMoveSpeed(dd: number): number { + return ( + (dd / ViewportMovePlugin.TriggerRange) * + ViewportMovePlugin.DefaultMoveSpeed + ); + } + + viewportMove(e: FederatedMouseEvent) { + const sp = e.global; + const { moveSpeedx, moveSpeedy } = this.calculateBoundaryMoveSpeed(sp); + if (moveSpeedx == 0 && moveSpeedy == 0) { + this.app.canvas.cursor = 'auto'; + this.stopMove(); + } else { + this.app.canvas.cursor = 'grab'; + this.startMove(moveSpeedx, moveSpeedy); + } + } +} + +/** + * 应用交互插件,同时只能生效一个 + */ +export abstract class AppInteractionPlugin extends InteractionPluginBase { + constructor(name: string, app: GraphicApp) { + super(app, name, InteractionPluginType.App); + } + + /** + * 恢复,app交互插件同时只能生效一个 + */ + resume(): void { + this.app.pauseAppInteractionPlugins(); + super.resume(); + } +} + +/** + * 图形交互插件,可同时生效 + */ +export abstract class GraphicInteractionPlugin + implements InteractionPlugin +{ + readonly _type = InteractionPluginType.Graphic; + app: GraphicApp; + name: string; // 唯一标识 + _pause: boolean; + constructor(name: string, app: GraphicApp) { + this.app = app; + this.name = name; + this._pause = true; + app.registerInteractionPlugin(this); + this.resume(); + // 新增的图形对象绑定 + this.app.on('graphicstored', (g) => { + if (this.isActive()) { + this.binds(this.filter(g)); + } + }); + this.app.on('graphicdeleted', (g) => { + if (this.isActive()) { + this.unbinds(this.filter(g)); + } + }); + } + + isActive(): boolean { + return !this._pause; + } + isAppPlugin(): boolean { + return false; + } + isOtherPlugin(): boolean { + return false; + } + isGraphicPlugin(): boolean { + return true; + } + + resume(): void { + const list = this.filter(...this.app.queryStore.getAllGraphics()); + this.binds(list); + this._pause = false; + this.app.emit('interaction-plugin-resume', this); + } + pause(): void { + const list = this.filter(...this.app.queryStore.getAllGraphics()); + this.unbinds(list); + this._pause = true; + this.app.emit('interaction-plugin-pause', this); + } + + /** + * 过滤需要的图形对象 + */ + abstract filter(...grahpics: JlGraphic[]): G[] | undefined; + + binds(list?: G[]): void { + if (list) { + list.forEach((g) => this.bind(g)); + } + } + unbinds(list?: G[]): void { + if (list) { + list.forEach((g) => this.unbind(g)); + } + } + /** + * 绑定图形对象的交互处理 + * @param g 图形对象 + */ + abstract bind(g: G): void; + /** + * 取消图形对象的交互处理 + * @param g 图形对象 + */ + abstract unbind(g: G): void; +} diff --git a/src/jl-graphic/plugins/KeyboardPlugin.ts b/src/jl-graphic/plugins/KeyboardPlugin.ts new file mode 100644 index 0000000..31cd104 --- /dev/null +++ b/src/jl-graphic/plugins/KeyboardPlugin.ts @@ -0,0 +1,351 @@ +import { GraphicApp } from '../app/JlGraphicApp'; + +let target: Node | undefined; + +export class GlobalKeyboardHelper { + appKeyboardPluginMap: JlGraphicAppKeyboardPlugin[] = []; + + constructor() { + window.onkeydown = (e: KeyboardEvent) => { + this.appKeyboardPluginMap.forEach((plugin) => { + const listenerMap = plugin.getKeyListener(e); + listenerMap?.forEach((listener) => { + if (listener.global) { + listener.press(e, plugin.app); + } + }); + }); + if (e.ctrlKey) { + if (e.code == 'KeyS') { + // 屏蔽全局Ctrl+S保存操作 + // console.log('屏蔽全局Ctrl+S') + return false; + } + } + if (target && target.nodeName == 'CANVAS') { + // 事件的目标是画布时,屏蔽总的键盘操作操作 + if (e.ctrlKey) { + if (e.code == 'KeyA' || e.code == 'KeyS') { + // 屏蔽Canvas上的Ctrl+A、Ctrl+S操作 + return false; + } + } + } + return true; + }; + window.onkeyup = (e: KeyboardEvent) => { + this.appKeyboardPluginMap.forEach((plugin) => { + const listenerMap = plugin.getKeyListener(e); + listenerMap?.forEach((listener) => { + if (listener.global) { + listener.release(e, plugin.app); + } + }); + }); + }; + } + + registerGAKPlugin(plugin: JlGraphicAppKeyboardPlugin) { + if (!this.appKeyboardPluginMap.find((pg) => pg == plugin)) { + this.appKeyboardPluginMap.push(plugin); + } + } + + removeGAKPlugin(plugin: JlGraphicAppKeyboardPlugin) { + const index = this.appKeyboardPluginMap.findIndex((pg) => pg == plugin); + if (index >= 0) { + this.appKeyboardPluginMap.splice(index, 1); + } + } +} + +const GlobalKeyboardPlugin = new GlobalKeyboardHelper(); + +export class JlGraphicAppKeyboardPlugin { + app: GraphicApp; + /** + * 结构为Map> + */ + keyListenerMap: Map> = new Map< + number | string, + Map + >(); // 键值监听map + keyListenerStackMap: Map = new Map< + string, + KeyListener[] + >(); // 键值监听栈(多次注册相同的监听会把之前注册的监听器入栈,移除最新的监听会从栈中弹出一个作为指定事件监听处理器) + + constructor(app: GraphicApp) { + this.app = app; + GlobalKeyboardPlugin.registerGAKPlugin(this); + const onMouseUpdateTarget = (e: MouseEvent) => { + const node = e.target as Node; + target = node; + // console.log('Mousedown Event', node.nodeName, node.nodeType, node.nodeValue) + }; + const keydownHandle = (e: KeyboardEvent) => { + console.debug(e.key, e.code, e.keyCode); + if (target && target == this.app.dom.getElementsByTagName('canvas')[0]) { + const listenerMap = this.getKeyListener(e); + listenerMap?.forEach((listener) => { + if (!listener.global) { + listener.press(e, this.app); + } + }); + } + }; + const keyupHandle = (e: KeyboardEvent) => { + if (target && target == this.app.dom.getElementsByTagName('canvas')[0]) { + const listenerMap = this.getKeyListener(e); + listenerMap?.forEach((listener) => { + if (!listener.global) { + listener.release(e, this.app); + } + }); + } + }; + + document.addEventListener('mousedown', onMouseUpdateTarget, false); + document.addEventListener('keydown', keydownHandle, false); + document.addEventListener('keyup', keyupHandle, false); + this.app.on('destroy', () => { + document.removeEventListener('mousedown', onMouseUpdateTarget, false); + document.removeEventListener('keydown', keydownHandle, false); + document.removeEventListener('keyup', keyupHandle, false); + }); + } + + private getOrInit(key: string | number): Map { + let map = this.keyListenerMap.get(key); + if (map === undefined) { + map = new Map(); + this.keyListenerMap.set(key, map); + } + return map; + } + + private getOrInitStack(key: string): KeyListener[] { + let stack = this.keyListenerStackMap.get(key); + if (stack === undefined) { + stack = []; + this.keyListenerStackMap.set(key, stack); + } + return stack; + } + + /** + * 注册按键监听,若有旧的,旧的入栈 + * @param keyListener + */ + addKeyListener(keyListener: KeyListener) { + const map = this.getOrInit(keyListener.value); + // 查询是否有旧的监听,若有入栈 + const old = map.get(keyListener.identifier); + if (old) { + const stack = this.getOrInitStack(keyListener.identifier); + stack.push(old); + } + map.set(keyListener.identifier, keyListener); + // console.log(this.getAllListenedKeys()); + } + /** + * 移除按键监听,若是当前注册的监听,尝试从栈中取出作为按键监听器,若是旧的,则同时移除栈中的监听 + * @param keyListener + */ + removeKeyListener(keyListener: KeyListener) { + keyListener.onRemove(); + const map = this.getOrInit(keyListener.value); + const old = map.get(keyListener.identifier); + map.delete(keyListener.identifier); + const stack = this.getOrInitStack(keyListener.identifier); + if (old && old === keyListener) { + // 是旧的监听 + const listener = stack.pop(); + if (listener) { + map.set(keyListener.identifier, listener); + } + } else { + // 移除栈中的 + const index = stack.findIndex((ls) => ls === keyListener); + if (index >= 0) { + stack.splice(index, 1); + } + } + // console.log(this); + } + + getKeyListenerBy(key: string | number): Map | undefined { + return this.keyListenerMap.get(key); + } + + getKeyListener(e: KeyboardEvent): Map | undefined { + return ( + this.getKeyListenerBy(e.key) || + this.getKeyListenerBy(e.code) || + this.getKeyListenerBy(e.keyCode) + ); + } + + isKeyListened(key: string | number): boolean { + return this.getOrInit(key).size > 0; + } + + /** + * 获取所有注册监听的键值(组合键) + */ + getAllListenedKeys(): string[] { + const keys: string[] = []; + this.keyListenerMap.forEach((v) => + v.forEach((_listener, ck) => keys.push(ck)) + ); + return keys; + } +} + +type KeyboardKeyHandler = (e: KeyboardEvent, app: GraphicApp) => void; + +export enum CombinationKey { + Ctrl = 'Ctrl', + Alt = 'Alt', + Shift = 'Shift', +} +export interface KeyListenerOptions { + // 具体的键值,可以是key/code/keycode(keycode已经弃用,建议优先使用key或code),例如:KeyA/(a/A)分别表示键盘A建,其中KeyA为键盘事件的code字段,a/A为键盘事件的key字段 + value: string | number; + // 组合键 + combinations?: CombinationKey[]; + // 是否监听全局,为false则只在画布为焦点时才处理 + global?: boolean; + // 按下操作处理 + onPress?: KeyboardKeyHandler; + // 按下操作是否每次触发,默认一次 + pressTriggerAsOriginalEvent?: boolean; + // 释放/抬起操作处理 + onRelease?: KeyboardKeyHandler; +} + +export interface ICompleteKeyListenerOptions { + // 具体的键值,可以是key/code/keycode(keycode已经弃用,建议优先使用key或code),例如:KeyA/(a/A)分别表示键盘A建,其中KeyA为键盘事件的code字段,a/A为键盘事件的key字段 + value: string | number; + // 组合键 + combinations: CombinationKey[]; + // 是否监听全局,为false则只在画布为焦点时才处理 + global: boolean; + // 按下操作处理 + onPress?: KeyboardKeyHandler; + pressTriggerAsOriginalEvent: boolean; + // 释放/抬起操作处理 + onRelease?: KeyboardKeyHandler; +} + +const DefaultKeyListenerOptions: ICompleteKeyListenerOptions = { + value: '', + combinations: [], + global: false, + onPress: undefined, + pressTriggerAsOriginalEvent: false, + onRelease: undefined, +}; + +export class KeyListener { + // value 支持keyCode,key,code三种值 + readonly options: ICompleteKeyListenerOptions; + private isPress = false; + + constructor(options: KeyListenerOptions) { + this.options = Object.assign({}, DefaultKeyListenerOptions, options); + } + + static create(options: KeyListenerOptions): KeyListener { + return new KeyListener(options); + } + + public get value(): string | number { + return this.options.value; + } + + public get combinations(): string[] { + return this.options.combinations; + } + + public get identifier(): string { + return this.options.combinations.join('+') + '+' + this.options.value; + } + + public get global(): boolean | undefined { + return this.options.global; + } + + public get onPress(): KeyboardKeyHandler | undefined { + return this.options.onPress; + } + + public set onPress(v: KeyboardKeyHandler | undefined) { + this.options.onPress = v; + } + + public get onRelease(): KeyboardKeyHandler | undefined { + return this.options.onRelease; + } + + public set onRelease(v: KeyboardKeyHandler | undefined) { + this.options.onRelease = v; + } + + public get pressTriggerEveryTime(): boolean { + return this.options.pressTriggerAsOriginalEvent; + } + + public set pressTriggerEveryTime(v: boolean) { + this.options.pressTriggerAsOriginalEvent = v; + } + + press(e: KeyboardEvent, app: GraphicApp): void { + if (!this.checkCombinations(e)) { + console.debug('组合键不匹配, 不执行press', e, this); + return; + } + if (this.pressTriggerEveryTime || !this.isPress) { + // console.log('Keydown: ', e, this.onPress); + this.isPress = true; + if (this.onPress) { + this.onPress(e, app); + } + } + } + /** + * 检查组合键是否匹配 + */ + checkCombinations(e: KeyboardEvent): boolean { + const cbs = this.combinations; + if (cbs.length > 0) { + if ( + ((e.altKey && cbs.includes(CombinationKey.Alt)) || + (!e.altKey && !cbs.includes(CombinationKey.Alt))) && + ((e.ctrlKey && cbs.includes(CombinationKey.Ctrl)) || + (!e.ctrlKey && !cbs.includes(CombinationKey.Ctrl))) && + ((e.shiftKey && cbs.includes(CombinationKey.Shift)) || + (!e.shiftKey && !cbs.includes(CombinationKey.Shift))) + ) { + return true; + } + } else { + return !e.altKey && !e.ctrlKey && !e.shiftKey; + } + return false; + } + + release(e: KeyboardEvent, app: GraphicApp): void { + if (this.isPress) { + // console.log('Keyup : ', e.key, e); + this.isPress = false; + if (this.onRelease) { + this.onRelease(e, app); + } + } + } + onRemove(): void { + // 重置按下状态 + this.isPress = false; + } +} diff --git a/src/jl-graphic/plugins/index.ts b/src/jl-graphic/plugins/index.ts new file mode 100644 index 0000000..75c00d9 --- /dev/null +++ b/src/jl-graphic/plugins/index.ts @@ -0,0 +1,6 @@ +export * from './InteractionPlugin'; +export * from './CommonMousePlugin'; +export * from './KeyboardPlugin'; +export * from './CopyPlugin'; +export * from './GraphicTransformPlugin'; +export * from './AnimationManager'; diff --git a/src/jl-graphic/ui/ContextMenu.ts b/src/jl-graphic/ui/ContextMenu.ts new file mode 100644 index 0000000..f69746a --- /dev/null +++ b/src/jl-graphic/ui/ContextMenu.ts @@ -0,0 +1,774 @@ +import { Color, Container, Graphics, Point, Rectangle, Text } from 'pixi.js'; +import { GraphicApp } from '../app'; +import { OutOfBound } from '../utils'; +import { + DefaultWhiteMenuOptions, + MenuCompletionItemStyle, + MenuCompletionOptions, + MenuCompletionStyleOptions, + MenuGroupOptions, + MenuItemOptions, + MenuOptions, +} from './Menu'; + +export class ContextMenuPlugin { + app: GraphicApp; + contextMenuMap: Map = new Map(); + + constructor(app: GraphicApp) { + this.app = app; + const canvas = this.app.canvas; + canvas.on('pointerdown', () => { + this.contextMenuMap.forEach((menu) => { + menu.close(); + }); + }); + } + + registerMenu(menu: ContextMenu) { + this.contextMenuMap.set(menu.menuName, menu); + menu.plugin = this; + } + + /** + * 获取视口屏幕宽度 + */ + public get screenWidth(): number { + return this.app.viewport.screenWidth; + } + + /** + * 获取视口屏幕高度 + */ + public get screenHeight(): number { + return this.app.viewport.screenHeight; + } + + /** + * 打开菜单 + * @param menu + * @param global + */ + open(menu: ContextMenu, global: Point) { + if (!menu.opened) { + menu.opened = true; + this.app.app.stage.addChild(menu); + } + // 处理超出显示范围 + const screenHeight = this.screenHeight; + const bottomY = global.y + menu.height; + + let oob = this.oob(menu, global); + const pos = global.clone(); + if (oob.right) { + pos.x = global.x - menu.width; + } + if (oob.bottom) { + const py = global.y - menu.height; + if (py > 0) { + pos.y = py; + } else { + pos.y = global.y - (bottomY - screenHeight); + } + } + // 移动后是否左上超出 + oob = this.oob(menu, pos); + if (oob.left) { + pos.x = 0; + } + if (oob.top) { + pos.y = 0; + } + menu.position.copyFrom(pos); + } + /** + * 关闭菜单 + * @param menu + */ + close(menu: ContextMenu) { + if (menu.opened) { + menu.opened = false; + this.app.app.stage.removeChild(menu); + } + } + /** + * 越界检查 + * @param menu + * @param global + * @returns + */ + oob(menu: ContextMenu, global: Point): OutOfBound { + const screenWidth = this.screenWidth; + const screenHeight = this.screenHeight; + const bound = new Rectangle(0, 0, screenWidth, screenHeight); + const menuRect = new Rectangle(global.x, global.y, menu.width, menu.height); + return OutOfBound.check(menuRect, bound); + } +} + +/** + * 上下文菜单,多级嵌套 + */ +export class ContextMenu extends Container { + _plugin?: ContextMenuPlugin; + parentMenuItem?: ContextMenuItem; + openedSubMenu?: ContextMenu; + menuOptions: MenuCompletionOptions; + opened = false; + bg: Graphics; + title?: Text; + groups: MenuGroup[]; + private padding = 5; + _active = false; // 激活状态 + timeoutCloseHandle?: NodeJS.Timeout; + + constructor(menuOptions: MenuOptions, parentMenuItem?: ContextMenuItem) { + super(); + this.menuOptions = Object.assign({}, DefaultWhiteMenuOptions, menuOptions); + this.name = this.menuOptions.name; + this.bg = new Graphics(); + this.addChild(this.bg); + this.groups = []; + this.init(); + this.parentMenuItem = parentMenuItem; + } + + static init(options: MenuOptions): ContextMenu { + return new ContextMenu(options); + } + + public get style(): MenuCompletionStyleOptions { + return this.menuOptions.style; + } + + /** + * 父级菜单 + */ + public get parentMenu(): ContextMenu | undefined { + return this.parentMenuItem?.menu; + } + + /** + * 最顶级菜单 + */ + public get rootMenu(): ContextMenu { + if (this.parentMenu) { + return this.parentMenu.rootMenu; + } + return this; + } + + /** + * 是否存在激活的菜单项 + * @returns + */ + hasActiveItem(): boolean { + for (let i = 0; i < this.groups.length; i++) { + const group = this.groups[i]; + if (group.hasActiveItem()) { + return true; + } + } + return false; + } + + public get active(): boolean { + return ( + this._active || + this.hasActiveItem() || + (this.parentMenuItem != undefined && this.parentMenuItem._active) + ); + } + + public set active(v: boolean) { + this._active = v; + this.onActiveChanged(); + } + + onActiveChanged() { + if (this.parentMenuItem) { + this.parentMenuItem.onActiveChanged(); + if (!this.active) { + this.timeoutCloseHandle = setTimeout(() => { + this.close(); + }, 500); + } else { + if (this.timeoutCloseHandle) { + clearTimeout(this.timeoutCloseHandle); + } + } + } + } + + setOptions(menuOptions: MenuOptions) { + this.menuOptions = Object.assign({}, DefaultWhiteMenuOptions, menuOptions); + this.init(); + } + + /** + * 初始化 + */ + init() { + // this.initTitle(); + this.groups = []; + const options = this.menuOptions; + let maxItemWidth = 0; + let borderHeight = 0; + options.groups.forEach((group) => { + const menuGroup = new MenuGroup(this, group); + this.groups.push(menuGroup); + borderHeight += menuGroup.totalHeight; + if (menuGroup.maxWidth > maxItemWidth) { + maxItemWidth = menuGroup.maxWidth; + } + }); + + const splitLineWidth = 1; + + const bgWidth = maxItemWidth + this.padding * 2; + const bgHeight = + borderHeight + + this.groups.length * this.padding * 2 + + (this.groups.length - 1) * splitLineWidth; + + if (options.style.border) { + this.bg.lineStyle( + options.style.borderWidth, + new Color(options.style.borderColor) + ); + } + this.bg.beginFill(new Color(options.style.backgroundColor)); + if (options.style.borderRoundRadius > 0) { + this.bg.drawRoundedRect( + 0, + 0, + bgWidth, + bgHeight, + options.style.borderRoundRadius + ); + } else { + this.bg.drawRect(0, 0, bgWidth, bgHeight); + } + this.bg.endFill(); + let groupHeight = 0; + this.bg.lineStyle(splitLineWidth, new Color(options.style.borderColor)); + for (let i = 0; i < this.groups.length; i++) { + const group = this.groups[i]; + group.updateItemBox(maxItemWidth); + group.position.set(this.padding, groupHeight + this.padding); + if (i === this.groups.length - 1) { + // 最后一个 + break; + } + const splitLineY = groupHeight + group.height + this.padding * 2; + this.bg.moveTo(0, splitLineY); + this.bg.lineTo(bgWidth, splitLineY); + groupHeight = splitLineY + splitLineWidth; + } + + this.addChild(...this.groups); + + this.eventMode = 'static'; + this.on('pointerover', () => { + this.active = true; + }); + this.on('pointerout', () => { + this.active = false; + }); + } + + initGroups() { + this.groups = []; + const options = this.menuOptions; + options.groups.forEach((group) => { + const menuGroup = new MenuGroup(this, group); + this.groups.push(menuGroup); + }); + this.addChild(...this.groups); + } + + initTitle() { + if (this.menuOptions.title) { + this.title = new Text(this.menuOptions.title, { align: 'left' }); + } + } + + updateBg() { + this.bg.clear(); + const options = this.menuOptions; + let maxItemWidth = 0; + let borderHeight = 0; + const splitLineWidth = 1; + + this.groups.forEach((menuGroup) => { + borderHeight += menuGroup.totalHeight; + if (menuGroup.maxWidth > maxItemWidth) { + maxItemWidth = menuGroup.maxWidth; + } + }); + + const bgWidth = maxItemWidth + this.padding * 2; + const bgHeight = + borderHeight + + this.groups.length * this.padding * 2 + + (this.groups.length - 1) * splitLineWidth; + + if (options.style.border) { + this.bg.lineStyle( + options.style.borderWidth, + new Color(options.style.borderColor) + ); + } + this.bg.beginFill(new Color(options.style.backgroundColor)); + if (options.style.borderRoundRadius > 0) { + this.bg.drawRoundedRect( + 0, + 0, + bgWidth, + bgHeight, + options.style.borderRoundRadius + ); + } else { + this.bg.drawRect(0, 0, bgWidth, bgHeight); + } + this.bg.endFill(); + let groupHeight = 0; + this.bg.lineStyle(splitLineWidth, new Color(options.style.borderColor)); + for (let i = 0; i < this.groups.length; i++) { + const group = this.groups[i]; + group.updateItemBox(maxItemWidth); + group.position.set(this.padding, groupHeight + this.padding); + if (i === this.groups.length - 1) { + // 最后一个 + break; + } + const splitLineY = groupHeight + group.height + this.padding * 2; + this.bg.moveTo(0, splitLineY); + this.bg.lineTo(bgWidth, splitLineY); + groupHeight = splitLineY + splitLineWidth; + } + } + + update() { + this.groups.forEach((group) => group.update()); + this.updateBg(); + } + + public get menuName(): string { + return this.menuOptions.name; + } + + public get plugin(): ContextMenuPlugin { + if (this.parentMenu) { + return this.parentMenu.plugin; + } + if (this._plugin) { + return this._plugin; + } + throw new Error(`上下文菜单name=${this.menuOptions.name}没有添加到插件中`); + } + + public set plugin(v: ContextMenuPlugin) { + this._plugin = v; + } + + /** + * 显示菜单 + */ + open(global: Point): void { + if (this.parentMenu) { + this.parentMenu.openSub(this, global); + } else { + this.update(); + this.plugin.open(this, global); + } + } + + /** + * 关闭菜单 + */ + close(): void { + if (this.openedSubMenu) { + this.openedSubMenu.close(); + this.openedSubMenu = undefined; + } + this.plugin.close(this); + } + + /** + * 打开子菜单 + * @param subMenu + * @param global + */ + private openSub(subMenu: ContextMenu, global: Point) { + if (this.openedSubMenu) { + this.openedSubMenu.close(); + } + const pos = global.clone(); + const oob = this.plugin.oob(subMenu, global); + if (oob.right) { + pos.x = this.position.x - subMenu.width + this.padding; + } + if (oob.bottom) { + pos.y = this.plugin.screenHeight - subMenu.height - this.padding; + } + this.plugin.open(subMenu, pos); + this.openedSubMenu = subMenu; + } +} + +class MenuGroup extends Container { + private gutter = 3; // 名称、快捷键、箭头文本间隙 + config: MenuGroupOptions; + menu: ContextMenu; + items: ContextMenuItem[] = []; + constructor(menu: ContextMenu, config: MenuGroupOptions) { + super(); + this.config = config; + this.menu = menu; + config.items.forEach((item) => { + this.items.push(new ContextMenuItem(menu, item)); + }); + + this.addChild(...this.items); + } + + hasActiveItem(): boolean { + for (let i = 0; i < this.items.length; i++) { + const item = this.items[i]; + if (item.active) { + return true; + } + } + return false; + } + + public get maxWidth(): number { + const maxNameWidth = this.items + .map((item) => item.nameBounds.width) + .sort((a, b) => a - b) + .reverse()[0]; + const maxShortcutWidth = this.items + .map((item) => item.shortcutKeyBounds.width) + .sort((a, b) => a - b) + .reverse()[0]; + const maxWidth = + maxNameWidth + + this.gutter + + maxShortcutWidth + + this.items[0].paddingLeft + + this.items[0].paddingRight; + return maxWidth; + } + + public get totalHeight(): number { + let total = 0; + this.items.forEach((item) => (total += item.totalHeight)); + return total; + } + + update() { + let i = 0; + this.items.forEach((item) => { + item.update(); + if (item.visible) { + item.position.y = i * item.totalHeight; + i++; + } + }); + // this.items.forEach() + // for (let i = 0; i < this.items.length; i++) { + // const item = this.items[i]; + // if (item.visible) { + // item.position.y = i * item.totalHeight; + // } + // } + } + + updateItemBox(maxItemWidth: number) { + this.items.forEach((item) => + item.updateBox(maxItemWidth, item.totalHeight) + ); + } +} + +/** + * 菜单项 + */ +class ContextMenuItem extends Container { + menu: ContextMenu; + config: MenuItemOptions; + /** + * 名称文本 + */ + nameText: Text; + /** + * 快捷键文本 + */ + shortcutKeyText?: Text; + private gutter = 3; // 名称、快捷键、箭头文本间隙 + arrowText?: Text; + box: Graphics; + subMenu?: ContextMenu; + _active = false; // 激活状态 + + constructor(menu: ContextMenu, config: MenuItemOptions) { + super(); + this.menu = menu; + this.config = config; + this.box = new Graphics(); + this.addChild(this.box); + + this.nameText = new Text(this.config.name, { + fontSize: this.fontSize, + fill: this.fontColor, + }); + this.addChild(this.nameText); + + this.initShortcutKeyText(); + this.initSubMenu(); + } + + registerEventHandler() { + this.eventMode = 'static'; + this.cursor = 'pointer'; + this.on('pointerover', () => { + this.active = true; + if (this.config.disabled) { + this.cursor = 'not-allowed'; + } else { + this.cursor = 'pointer'; + } + if (this.subMenu) { + const p = this.toGlobal(new Point(this.width)); + this.subMenu.open(p); + } + }); + this.on('pointerout', () => { + this.active = false; + }); + this.on('pointertap', () => { + if (this.config.disabled) { + // 禁用,不处理 + return; + } + if (this.config.handler) { + this.menu.plugin.app.emit('pre-menu-handle', this.config); + this.config.handler(); + this.menu.plugin.app.emit('post-menu-handle', this.config); + } + if (!this.config.subMenu || this.config.subMenu.length === 0) { + this.active = false; + this.menu.active = false; + this.menu.rootMenu.close(); + } + }); + } + + public get active(): boolean { + return this._active || (this.subMenu != undefined && this.subMenu.active); + } + + public set active(v: boolean) { + this._active = v; + if (this.subMenu) { + this.subMenu.onActiveChanged(); + } + this.onActiveChanged(); + } + + onActiveChanged() { + if (this.active) { + this.box.alpha = 1; + } else { + this.box.alpha = 0; + } + } + + public get textWidth(): number { + return this.nameBounds.width + this.shortcutKeyBounds.width + this.gutter; + } + + public get nameGraphic(): Text { + if (this.nameText) { + return this.nameText; + } + throw new Error(`菜单项name=${this.config.name}没有初始化名称图形对象`); + } + + public get totalHeight(): number { + if (this.config.visible === false) { + return 0; + } else { + return this.paddingTop + this.paddingBottom + this.nameGraphic.height; + } + } + + public get nameBounds(): Rectangle { + return this.nameGraphic.getLocalBounds(); + } + + public get shortcutKeyBounds(): Rectangle { + if (this.shortcutKeyText) { + return this.shortcutKeyText.getLocalBounds(); + } else { + return new Rectangle(0, 0, 0, 0); + } + } + + public get style(): MenuCompletionItemStyle { + return this.menu.style.itemStyle; + } + + private checkPadding(padding: number | number[]) { + if (Array.isArray(padding)) { + if (padding.length !== 2 && padding.length !== 4) { + throw new Error('错误的padding数据'); + } + } + } + + private toWholePadding(padding: number | number[]): number[] { + this.checkPadding(padding); + if (Array.isArray(padding)) { + if (padding.length == 2) { + return [padding[0], padding[1], padding[0], padding[1]]; + } else { + return padding; + } + } else { + return [padding, padding, padding, padding]; + } + } + + public get paddingTop(): number { + return this.toWholePadding(this.menu.style.itemStyle.padding)[0]; + } + public get paddingBottom(): number { + return this.toWholePadding(this.menu.style.itemStyle.padding)[2]; + } + public get paddingLeft(): number { + return this.toWholePadding(this.menu.style.itemStyle.padding)[3]; + } + public get paddingRight(): number { + return this.toWholePadding(this.menu.style.itemStyle.padding)[1]; + } + + public get hoverColor(): string { + return this.style.hoverColor; + } + + public get fontSize(): number { + return this.style.fontSize; + } + + public get fontColor(): string { + if (this.config.disabled) { + return this.style.disabledFontColor; + } else if (this.config.fontColor) { + return this.config.fontColor; + } + return this.style.fontColor; + } + + initShortcutKeyText(): Text | undefined { + if (this.config.shortcutKeys && this.config.shortcutKeys.length > 0) { + this.shortcutKeyText = new Text(this.config.shortcutKeys.join('+'), { + fontSize: this.fontSize, + fill: this.fontColor, + }); + this.addChild(this.shortcutKeyText); + return this.shortcutKeyText; + } + return undefined; + } + + initSubMenu() { + if (this.config.subMenu && this.config.subMenu.length > 0) { + this.arrowText = new Text('>', { + fontSize: this.fontSize, + fill: this.fontColor, + }); + this.addChild(this.arrowText); + this.subMenu = new ContextMenu( + { + name: `${this.config.name}子菜单`, + groups: this.config.subMenu, + style: this.menu.style, + }, + this + ); + } + } + + updateBackground(width: number, height: number) { + this.box.clear(); + const box = this.box; + const style = this.menu.style; + if (!style.itemStyle.hoverColor) { + throw new Error('未设置菜单项的hoverColor'); + } + let hoverColor = style.itemStyle.hoverColor; + if (this.style && this.style.hoverColor) { + hoverColor = this.style.hoverColor; + } + box.beginFill(new Color(hoverColor)); + if (style.borderRoundRadius > 0) { + box.drawRoundedRect(0, 0, width, height, style.borderRoundRadius); + } else { + box.drawRect(0, 0, width, height); + } + box.endFill(); + box.alpha = 0; + } + + updateBox(width: number, height: number) { + this.removeAllListeners(); + this.updateBackground(width, height); + this.nameText?.position.set(this.paddingLeft, this.paddingTop); + if (this.shortcutKeyText) { + const skTextWidth = this.shortcutKeyBounds.width; + this.shortcutKeyText.position.set( + width - skTextWidth - this.paddingRight, + this.paddingTop + ); + } + if (this.arrowText) { + this.arrowText.position.set( + width - this.paddingRight - this.gutter, + this.paddingTop + ); + } + + // 事件监听 + this.hitArea = new Rectangle(0, 0, width, height); + this.registerEventHandler(); + } + + update() { + if (this.config.visible === false) { + this.visible = false; + return; + } + this.visible = true; + this.nameText.text = this.config.name; + this.nameText.style.fontSize = this.fontSize; + this.nameText.style.fill = this.fontColor; + + if (this.shortcutKeyText) { + if (this.config.shortcutKeys && this.config.shortcutKeys.length > 0) { + this.shortcutKeyText.text = this.config.shortcutKeys.join('+'); + this.shortcutKeyText.style.fontSize = this.fontSize; + this.shortcutKeyText.style.fill = this.fontColor; + } else { + this.shortcutKeyText.visible = false; + } + } else { + this.initShortcutKeyText(); + } + + if (this.subMenu) { + this.subMenu.update(); + } + } +} diff --git a/src/jl-graphic/ui/Menu.ts b/src/jl-graphic/ui/Menu.ts new file mode 100644 index 0000000..a500216 --- /dev/null +++ b/src/jl-graphic/ui/Menu.ts @@ -0,0 +1,177 @@ +/** + * 菜单配置项 + */ +export interface MenuOptions { + /** + * 菜单名称,需唯一 + */ + name: string; + /** + * 菜单标题 + */ + title?: string; + /** + * 菜单分组 + */ + groups: MenuGroupOptions[]; + /** + * 菜单样式 + */ + style?: MenuStyleOptions; +} +/** + * 菜单分组 + */ +export interface MenuGroupOptions { + /** + * 分组命名 + */ + name?: string; + /** + * 菜单项 + */ + items: MenuItemOptions[]; +} + +export interface MenuCompletionOptions extends MenuOptions { + style: MenuCompletionStyleOptions; +} +/** + * 菜单样式配置项 + */ +export interface MenuStyleOptions { + /** + * 菜单标题样式 + */ + titleStyle?: MenuItemStyle; + /** + * 菜单背景色 + */ + backgroundColor?: string; + /** + * 菜单边框线宽度,默认1,0为无线框 + */ + borderWidth?: number; + /** + * 菜单边框颜色 + */ + borderColor?: string; + /** + * 包围框是否圆角,圆角的半径,0为直角 + */ + borderRoundRadius?: number; + /** + * 菜单项样式 + */ + itemStyle?: MenuItemStyle; +} + +export interface MenuCompletionStyleOptions extends MenuStyleOptions { + titleStyle: MenuItemStyle; + backgroundColor: string; + border: boolean; + borderWidth: number; + borderColor: string; + borderRoundRadius: number; + itemStyle: MenuCompletionItemStyle; +} + +export interface MenuItemOptions { + /** + * 名称 + */ + name: string; + /** + * 是否禁用,默认不禁用 + */ + disabled?: boolean; + /** + * 是否显示,默认显示 + */ + visible?: boolean; + /** + * 快捷键 + */ + shortcutKeys?: string[]; + /** + * 菜单逻辑处理 + */ + handler?: () => void; + fontColor?: string; + /** + * 子菜单 + */ + subMenu?: MenuGroupOptions[]; +} + +export interface MenuItemStyle { + /** + * 字体大小 + */ + fontSize: number; + /** + * 字体颜色 + */ + fontColor?: string; + /** + * hover颜色 + */ + hoverColor?: string; + /** + * 禁用下字体颜色 + */ + disabledFontColor?: string; + /** + * 内边距 + */ + padding: number[] | number; // 内边距 +} +export interface MenuCompletionItemStyle extends MenuItemStyle { + /** + * 文字颜色 + */ + fontColor: string; + /** + * 激活颜色 + */ + hoverColor: string; + /** + * 禁用下字体颜色 + */ + disabledFontColor: string; +} + +/** + * 默认的白色样式 + */ +export const DefaultWhiteStyleOptions: MenuCompletionStyleOptions = { + titleStyle: { + fontSize: 16, + fontColor: '#000000', + padding: [5, 15], + }, + backgroundColor: '#ffffff', + border: true, + borderWidth: 1, + borderColor: '#4C4C4C', + /** + * 默认圆角 + */ + borderRoundRadius: 5, + itemStyle: { + fontSize: 16, + fontColor: '#000000', + padding: [5, 25], + hoverColor: '#1E78DB', + disabledFontColor: '#9D9D9D', + }, +}; + +/** + * 默认的白色菜单配置 + */ +export const DefaultWhiteMenuOptions: MenuCompletionOptions = { + name: '', + style: DefaultWhiteStyleOptions, + groups: [], +}; diff --git a/src/jl-graphic/utils/GraphicUtils.ts b/src/jl-graphic/utils/GraphicUtils.ts new file mode 100644 index 0000000..b8e5109 --- /dev/null +++ b/src/jl-graphic/utils/GraphicUtils.ts @@ -0,0 +1,695 @@ +import { + Container, + DisplayObject, + IPointData, + Point, + Rectangle, +} from 'pixi.js'; +import { floatEquals, isZero } from '../math'; +import Vector2 from '../math/Vector2'; + +/** + * 递归父节点执行逻辑 + * @param obj + * @param handler + */ +export function recursiveParents( + obj: DisplayObject, + handler: (parent: Container) => void +): void { + if (obj.parent) { + handler(obj.parent); + recursiveParents(obj.parent, handler); + } +} + +/** + * 递归父节点查询父节点对象 + * @param obj + * @param finder + * @returns + */ +export function recursiveFindParent( + obj: DisplayObject, + finder: (parent: Container) => boolean +): Container | null { + if (obj.parent) { + if (finder(obj.parent)) { + return obj.parent; + } else { + return recursiveFindParent(obj.parent, finder); + } + } + return null; +} + +/** + * 递归子节点执行逻辑 + * @param container + * @param handler + */ +export function recursiveChildren( + container: Container, + handler: (child: DisplayObject) => void +): void { + container.children.forEach((child) => { + handler(child); + if (child.children) { + recursiveChildren(child as Container, handler); + } + }); +} + +/** + * 递归子节点查询子节点对象 + */ +export function recursiveFindChild( + container: Container, + finder: (child: DisplayObject) => boolean +): DisplayObject | null { + let result = null; + for (let i = 0; i < container.children.length; i++) { + const child = container.children[i]; + if (finder(child)) { + return child; + } else if (child.children) { + result = recursiveFindChild(child as Container, finder); + } + } + return result; +} + +export interface BezierParam { + p1: IPointData; + p2: IPointData; + cp1: IPointData; + cp2: IPointData; +} + +/** + * 判断贝塞尔曲线数据是否正确 + * @param points + */ +export function assertBezierPoints(points: IPointData[]) { + if (points.length < 4 || points.length % 3 !== 1) { + throw new Error(`bezierCurve 数据错误: ${points}`); + } +} + +/** + * 转换为贝塞尔曲线参数 + * @param points + * @returns + */ +export function convertToBezierParams(points: IPointData[]): BezierParam[] { + assertBezierPoints(points); + const bps: BezierParam[] = []; + for (let i = 0; i < points.length - 3; i += 3) { + const p1 = new Point(points[i].x, points[i].y); + const p2 = new Point(points[i + 3].x, points[i + 3].y); + const cp1 = new Point(points[i + 1].x, points[i + 1].y); + const cp2 = new Point(points[i + 2].x, points[i + 2].y); + bps.push({ + p1, + p2, + cp1, + cp2, + }); + } + return bps; +} + +/** + * 根据分段数计算贝塞尔曲线所有点坐标 + * @param basePoints + * @param segmentsCount + * @returns + */ +export function calculateBezierPoints( + basePoints: IPointData[], + segmentsCount: number +): Point[] { + const bps = convertToBezierParams(basePoints); + const points: Point[] = []; + bps.forEach((bp) => { + points.push( + ...calculateOneBezierPoints(bp.p1, bp.p2, bp.cp1, bp.cp2, segmentsCount) + ); + }); + return points; +} + +/** + * 根据分段数计算贝塞尔曲线所有点坐标 + * @param basePoints + * @param segmentsCount + * @returns + */ +export function calculateOneBezierPoints( + p1: IPointData, + p2: IPointData, + cp1: IPointData, + cp2: IPointData, + segmentsCount: number +): Point[] { + const points: Point[] = []; + const fromX = p1.x; + const fromY = p1.y; + const n = segmentsCount; + let dt = 0; + let dt2 = 0; + let dt3 = 0; + let t2 = 0; + let t3 = 0; + const cpX = cp1.x; + const cpY = cp1.y; + const cpX2 = cp2.x; + const cpY2 = cp2.y; + const toX = p2.x; + const toY = p2.y; + points.push(new Point(p1.x, p1.y)); + for (let i = 1, j = 0; i <= n; ++i) { + j = i / n; + dt = 1 - j; + dt2 = dt * dt; + dt3 = dt2 * dt; + t2 = j * j; + t3 = t2 * j; + const px = dt3 * fromX + 3 * dt2 * j * cpX + 3 * dt * t2 * cpX2 + t3 * toX; + const py = dt3 * fromY + 3 * dt2 * j * cpY + 3 * dt * t2 * cpY2 + t3 * toY; + points.push(new Point(px, py)); + } + return points; +} + +/** + * 计算矩形中点 + */ +export function getRectangleCenter(rectangle: Rectangle): Point { + return new Point( + rectangle.x + rectangle.width / 2, + rectangle.y + rectangle.height / 2 + ); +} + +/** + * 计算两个矩形中心对齐的坐标, PS: 计算的是较大包围框的中心 + * @param rect1 + * @param rect2 + * @returns + */ +export function getCenterOfTwoRectangle( + rect1: Rectangle, + rect2: Rectangle +): Point { + const x = Math.abs(rect1.width - rect2.width) / 2; + const y = Math.abs(rect1.height - rect2.height) / 2; + return new Point(x, y); +} + +/** + * 序列化图形变换 + * @param obj + * @returns + */ +export function serializeTransform(obj: DisplayObject): number[] { + const position = obj.position; + const scale = obj.scale; + const angle = obj.angle; + const skew = obj.skew; + return [position.x, position.y, scale.x, scale.y, angle, skew.x, skew.y]; +} +/** + * 反序列化变换数据到图形对象 + * @param obj + * @param transform + */ +export function deserializeTransformInto( + obj: DisplayObject, + transform: number[] +): void { + if (transform.length === 7) { + obj.position.set(transform[0], transform[1]); + obj.scale.set(transform[2], transform[3]); + obj.angle = transform[4]; + obj.skew.set(transform[5], transform[6]); + } else if (transform.length > 0) { + console.warn('错误的变换数据', transform); + } +} + +/** + * 将直线转换为多边形 + * @param p1 + * @param p2 + * @param thick + * @returns + */ +export function convertLineToPolygonPoints( + p1: IPointData, + p2: IPointData, + thick: number +): IPointData[] { + const angle = Math.atan2(p2.y - p1.y, p2.x - p1.x) - Math.PI / 2; + const half = thick / 2; + const cos = Math.cos(angle) * half; + const sin = Math.sin(angle) * half; + return [ + new Point(p1.x - cos, p1.y - sin), + new Point(p2.x - cos, p2.y - sin), + new Point(p2.x + cos, p2.y + sin), + new Point(p1.x + cos, p1.y + sin), + ]; +} + +/** + * 转换矩形为多边形点坐标 + * @param rect 矩形 + * @returns + */ +export function convertRectangleToPolygonPoints(rect: Rectangle): IPointData[] { + return [ + new Point(rect.x, rect.y), + new Point(rect.x + rect.width, rect.y), + new Point(rect.x + rect.width, rect.y + rect.height), + new Point(rect.x, rect.y + rect.height), + ]; +} + +/** + * 计算线段中点坐标 + * @param p1 + * @param p2 + * @returns + */ +export function calculateLineMidpoint(p1: IPointData, p2: IPointData): Point { + const x = (p1.x + p2.x) / 2; + const y = (p1.y + p2.y) / 2; + return new Point(x, y); +} + +/** + * 计算线段细分坐标--线段分成几份 + * @param p1 + * @param p2 + * @param knife + * @returns + */ +export function calculateLineSegmentingPoint( + p1: IPointData, + p2: IPointData, + knife: number +): IPointData[] { + const segmentingPoints: IPointData[] = []; + const x = p1.x < p2.x ? p1.x : p2.x; + const y = p1.y < p2.y ? p1.y : p2.y; + const w = Math.abs(p1.x - p2.x); + const h = Math.abs(p1.y - p2.y); + for (let i = 0; i < knife - 1; i++) { + const pointX = x + (w * (i + 1)) / knife; + const pointy = y + (h * (i + 1)) / knife; + segmentingPoints.push(new Point(pointX, pointy)); + } + return segmentingPoints; +} + +/** + * 计算点到直线距离 + * @param p1 + * @param p2 + * @param p + */ +export function calculateDistanceFromPointToLine( + p1: IPointData, + p2: IPointData, + p: IPointData +): number { + // 求直线的一般方程参数ABC,直线的一般式方程AX+BY+C=0 + const A = p1.y - p2.y; + const B = p2.x - p1.x; + const C = p1.x * p2.y - p1.y * p2.x; + // 计算点到直线垂直距离: d = |Ax+By+C|/sqrt(A*A+B*B),其中x,y为点坐标 + const dl = Math.abs(A * p.x + B * p.y + C) / Math.sqrt(A * A + B * B); + return dl; +} + +/** + * 计算点到直线的垂足坐标 + * @param p + * @param p1 + * @param p2 + */ +export function calculateFootPointFromPointToLine( + p1: IPointData, + p2: IPointData, + p: IPointData +): Point { + if (p1.x == p2.x && p1.y == p2.y) { + throw new Error(`直线两坐标点相等:${p1}`); + } + const k = -( + ((p1.x - p.x) * (p2.x - p1.x) + (p1.y - p.y) * (p2.y - p1.y)) / + (Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)) + ); + if (isZero(k)) { + return new Point(p.x, p.y); + } + const xf = k * (p2.x - p1.x) + p1.x; + const yf = k * (p2.y - p1.y) + p1.y; + return new Point(xf, yf); +} + +/** + * 计算直线与圆的交点 + * 1用直线到圆心的距离和半径相比,判断是否和圆有交点; + * 2求出圆心在直线上面的垂点; + * 3算出直线的单位向量e; + * 4求出一侧交点(Intersection)到projectPoint的长度(sideLength); + * 5求出sideLength和这侧端点到projectPoint距离的比例(ratio); + * 6projectPoint +/- ratio * e = 两侧交点; + * @param p0 圆心坐标 + * @param radius 圆半径 + * @param p1 直线坐标1 + * @param p2 直线坐标2 + * @returns 交点坐标,可能2/1/0个 + */ +export function calculateIntersectionPointOfCircleAndLine( + p0: IPointData, + radius: number, + p1: IPointData, + p2: IPointData +): Point[] { + const distance = calculateDistanceFromPointToLine(p1, p2, p0); + if (distance <= radius) { + // 有交点 + // 计算垂点 + const pr = calculateFootPointFromPointToLine(p1, p2, p0); + if (floatEquals(distance, radius)) { + // 切线 + return [pr]; + } + const vpr = new Vector2([pr.x, pr.y]); + const vc = new Vector2([p0.x, p0.y]); + // 计算直线单位向量 + const v1 = new Vector2([p1.x, p1.y]); + const v2 = new Vector2([p2.x, p2.y]); + const ve = Vector2.direction(v2, v1); + const base = Math.sqrt( + Math.abs(radius * radius - Vector2.difference(vpr, vc).squaredLength()) + ); + const vl = ve.scale(base); + const ip1 = Vector2.sum(vpr, vl); + const ip2 = Vector2.difference(vpr, vl); + return [new Point(ip1.x, ip1.y), new Point(ip2.x, ip2.y)]; + } else { + // 无交点 + return []; + } +} + +/** + * 计算圆心与圆心外一点与圆的交点(取圆心到点的向量与圆的交点) + * @param p0 圆心坐标 + * @param radius 圆半径 + * @param p 点坐标 + * @returns + */ +export function calculateIntersectionPointOfCircleAndPoint( + p0: IPointData, + radius: number, + p: IPointData +): Point { + const points = calculateIntersectionPointOfCircleAndLine(p0, radius, p0, p); + const vc = new Vector2([p0.x, p0.y]); + const vp = new Vector2([p.x, p.y]); + const vecp = Vector2.direction(vp, vc); + for (let i = 0; i < points.length; i++) { + const ip = points[i]; + const ve = Vector2.direction(new Vector2([ip.x, ip.y]), vc); + if (ve.equals(vecp)) { + return ip; + } + } + throw new Error('计算圆心与圆心外一点与圆的交点逻辑错误'); +} + +/** + * 计算点基于点的镜像点坐标 + * @param bp 基准点 + * @param p 待镜像的点坐标 + * @param distance 镜像点到基准点的距离,默认为p到基准点的距离,即对称 + * @returns + */ +export function calculateMirrorPoint( + bp: IPointData, + p: IPointData, + distance?: number +): Point { + const vbp = Vector2.from(bp); + const vp = Vector2.from(p); + const direction = Vector2.direction(vbp, vp); + if (distance == undefined) { + distance = Vector2.distance(vbp, vp); + } + const vmp = Vector2.sum(vbp, direction.scale(distance)); + return new Point(vmp.x, vmp.y); +} + +/** + * 计算基于给定轴的给定点的镜像点坐标 + * @param pa 给定轴线的坐标 + * @param pb 给定轴线的坐标 + * @param p 待镜像点坐标 + * @param distance + * @returns + */ +export function calculateMirrorPointBasedOnAxis( + pa: IPointData, + pb: IPointData, + p: IPointData, + distance?: number +): Point { + const fp = calculateFootPointFromPointToLine(pa, pb, p); + if (fp.equals(p)) { + return fp; + } else { + return calculateMirrorPoint(fp, p, distance); + } +} + +/** + * 计算直线与水平夹角,角度按顺时针,从0开始 + * @param p1 + * @param p2 + * @returns 角度,范围[0, 360) + */ +export function angleToAxisx(p1: IPointData, p2: IPointData): number { + if (p1.x == p2.x && p1.y == p2.y) { + throw new Error('一个点无法计算角度'); + } + const dx = Math.abs(p1.x - p2.x); + const dy = Math.abs(p1.y - p2.y); + + if (p2.x == p1.x) { + if (p2.y > p1.y) { + return 90; + } else { + return 270; + } + } + if (p2.y == p1.y) { + if (p2.x > p1.x) { + return 0; + } else { + return 180; + } + } + const angle = (Math.atan2(dy, dx) * 180) / Math.PI; + if (p2.x > p1.x) { + if (p2.y > p1.y) { + return angle; + } else if (p2.y < p1.y) { + return 360 - angle; + } + } else if (p2.x < p1.x) { + if (p2.y > p1.y) { + return 180 - angle; + } else { + return 180 + angle; + } + } + return angle; +} + +/** + * 计算两线夹角,pc与pa,pb的夹角,顺时针为正,逆时针为负 + * @param pa 交点 + * @param pb 锚定 + * @param pc + * @returns 夹角, [-180, 180] + */ +export function angleOfIncludedAngle( + pa: IPointData, + pb: IPointData, + pc: IPointData +): number { + const abAngle = angleToAxisx(pa, pb); + const acAngle = angleToAxisx(pa, pc); + let angle = acAngle - abAngle; + if (angle < -180) { + angle = 360 + angle; + } else if (angle > 180) { + angle = -(360 - angle); + } + return angle; +} + +/** + * 计算两点连线的法向量 + * @param point1 + * @param point2 + * @returns 单位法向量 + */ +export function getNormalVector( + point1: IPointData, + point2: IPointData +): number[] { + const x1 = point1.x, + y1 = point1.y; + const x2 = point2.x, + y2 = point2.y; + const length = Math.sqrt((y2 - y1) ** 2 + (x2 - x1) ** 2); + return [(y2 - y1) / length, (x1 - x2) / length]; +} + +/** + * 点延向量方向移动 + * @param point + * @param normal 单位向量 + * @param length 平移长度 + * @returns 移动后的点 + */ +export function movePointAlongNormal( + point: IPointData, + normal: number[], + length: number +): Point { + const newPoint = new Point( + point.x + length * normal[0], + point.y + length * normal[1] + ); + return newPoint; +} + +/** + * 计算两组点各自组成直线的相交点(若两线平行 返回第一组坐标第一个点) + * @param line1 两点坐标列表 + * @param line2 两点坐标列表 + * @returns 相交点 + */ +export function getIntersectionPoint(line1: number[], line2: number[]) { + const a1 = line1[0], + b1 = line1[1]; + const a2 = line1[2], + b2 = line1[3]; + const a3 = line2[0], + b3 = line2[1]; + const a4 = line2[2], + b4 = line2[3]; + const denominator = (a3 - a4) * (b1 - b2) - (a1 - a2) * (b3 - b4); + if (denominator === 0) { + return new Point(a1, b1); + } + const x = + ((a3 - a4) * (a2 * b1 - a1 * b2) - (a1 - a2) * (a4 * b3 - a3 * b4)) / + denominator; + const y = + ((b3 - b4) * (b2 * a1 - b1 * a2) - (b1 - b2) * (b4 * a3 - b3 * a4)) / + -denominator; + return new Point(x, y); +} + +/** + * 是否平行线 + * @param p1 + * @param p2 + * @param pa + * @param pb + * @returns + */ +export function isParallelLines( + p1: IPointData, + p2: IPointData, + pa: IPointData, + pb: IPointData +): boolean { + const vle1 = Vector2.direction(Vector2.from(p1), Vector2.from(p2)); + const vle2 = Vector2.direction(Vector2.from(pa), Vector2.from(pb)); + if (vle2.equals(vle1)) { + return true; + } + return vle1.equals(Vector2.direction(Vector2.from(pb), Vector2.from(pa))); +} + +/** + * 点是否在线段上 + * @param p1 + * @param p2 + * @param p + * @returns + */ +export function isPointOnLine( + p1: IPointData, + p2: IPointData, + p: IPointData +): boolean { + const vp1 = Vector2.from(p1); + const vp2 = Vector2.from(p2); + const vp = Vector2.from(p); + if (vp1.equals(vp) || vp2.equals(vp)) { + return true; + } + const vle = Vector2.direction(vp1, Vector2.from(p2)); + const vpe = Vector2.direction(vp1, vp); + if (vle.equals(vpe)) { + return ( + Vector2.difference(vp1, vp2).squaredLength() >= + Vector2.difference(vp1, vp).squaredLength() + ); + } + return false; +} +/** + * 两条线段是否存在包含关系 + * @param line1 + * @param line2 + * @returns + */ +export function isLineContainOther( + line1: { p1: IPointData; p2: IPointData }, + line2: { p1: IPointData; p2: IPointData } +): boolean { + return ( + (isPointOnLine(line1.p1, line1.p2, line2.p1) && + isPointOnLine(line1.p1, line1.p2, line2.p2)) || + (isPointOnLine(line2.p1, line2.p2, line1.p1) && + isPointOnLine(line2.p1, line2.p2, line1.p2)) + ); +} + +/** 均分线段, 返回各线段端点 */ +export function splitLineEvenly( + p1: IPointData, + p2: IPointData, + count: number +): IPointData[][] { + const [stepX, stepY] = [(p2.x - p1.x) / count, (p2.y - p1.y) / count]; + return Array(count) + .fill(1) + .map((_, i) => { + return [ + { x: p1.x + stepX * i, y: p1.y + stepY * i }, + { x: p1.x + stepX * (i + 1), y: p1.y + stepY * (i + 1) }, + ]; + }); +} diff --git a/src/jl-graphic/utils/IntersectUtils.ts b/src/jl-graphic/utils/IntersectUtils.ts new file mode 100644 index 0000000..2217a28 --- /dev/null +++ b/src/jl-graphic/utils/IntersectUtils.ts @@ -0,0 +1,362 @@ +import { IPointData, Point, Rectangle } from 'pixi.js'; +// /** +// * 点线碰撞检测 +// * @param pa 线段a端坐标 +// * @param pb 线段b端坐标 +// * @param p 点坐标 +// * @param tolerance 容忍度,越大检测范围越大 +// * @returns +// */ +// export function linePoint(pa: Point, pb: Point, p: Point, tolerance: number): boolean { +// return (Math.abs(distanceSquared(pa.x, pa.y, pb.x, pb.y) - (distanceSquared(pa.x, pa.y, p.x, p.y) + distanceSquared(pb.x, pb.y, p.x, p.y))) <= tolerance) +// } + +/** + * 根据点到直线的垂直距离计算碰撞 + * @param pa 线段a端坐标 + * @param pb 线段b端坐标 + * @param p 点坐标 + * @param lineWidth 线宽 + * @param exact 是否精确(使用给定线宽,否则线宽会设置为8) + * @returns + */ +export function linePoint( + pa: IPointData, + pb: IPointData, + p: IPointData, + lineWidth: number, + exact = false +): boolean { + if (!exact && lineWidth < 6) { + lineWidth = 6; + } + // 求直线的一般方程参数ABC,直线的一般式方程AX+BY+C=0 + const A = pa.y - pb.y; + const B = pb.x - pa.x; + const C = pa.x * pb.y - pa.y * pb.x; + // 计算点到直线垂直距离: d = |Ax+By+C|/sqrt(A*A+B*B),其中x,y为点坐标 + const dl = Math.abs(A * p.x + B * p.y + C) / Math.sqrt(A * A + B * B); + const intersect = dl <= lineWidth / 2; + if (intersect) { + // 距离在线宽范围内,再判断点是否超过线段两端点范围外(两端点外会有一点误差,两端点线宽一半半径的圆范围内) + const da = distance(pa.x, pa.y, p.x, p.y); + const db = distance(pb.x, pb.y, p.x, p.y); + const dab = distance(pa.x, pa.y, pb.x, pb.y); + return da <= dl + dab && db <= dl + dab; + } + return false; +} + +/** + * 折线与点碰撞 + * @param points 折线端点列表 + * @param p 点座标 + * @param lineWidth 线宽 + */ +export function polylinePoint( + points: IPointData[], + p: IPointData, + lineWidth: number +) { + const len = points.length; + for (let i = 0; i < len - 1; i++) { + if (linePoint(points[i], points[i + 1], p, lineWidth)) { + return true; + } + } + return false; +} + +/** + * 线线碰撞检测 + * @param pa 线段1a端坐标 + * @param pb 线段1b端坐标 + * @param p1 线段2a端坐标 + * @param p2 线段2b端坐标 + * @returns + */ +export function lineLine( + pa: IPointData, + pb: IPointData, + p1: IPointData, + p2: IPointData +): boolean { + const x1 = pa.x; + const y1 = pa.y; + const x2 = pb.x; + const y2 = pb.y; + const x3 = p1.x; + const y3 = p1.y; + const x4 = p2.x; + const y4 = p2.y; + const s1_x = x2 - x1; + const s1_y = y2 - y1; + const s2_x = x4 - x3; + const s2_y = y4 - y3; + const s = + (-s1_y * (x1 - x3) + s1_x * (y1 - y3)) / (-s2_x * s1_y + s1_x * s2_y); + const t = + (s2_x * (y1 - y3) - s2_y * (x1 - x3)) / (-s2_x * s1_y + s1_x * s2_y); + return s >= 0 && s <= 1 && t >= 0 && t <= 1; +} +/** + * 点和矩形碰撞检测 + * @param p 点作弊 + * @param rect 矩形 + * @returns + */ +export function pointBox(p: IPointData, rect: Rectangle): boolean { + const { x, y, width, height } = rect; + const x2 = p.x; + const y2 = p.y; + return x2 >= x && x2 <= x + width && y2 >= y && y2 <= y + height; +} +/** + * 线和矩形碰撞检测 + * @param pa 线段a端坐标 + * @param pb 线段b端坐标 + * @param rect 矩形 + * @returns + */ +export function lineBox( + pa: IPointData, + pb: IPointData, + rect: Rectangle +): boolean { + if (pointBox(pa, rect) || pointBox(pb, rect)) { + return true; + } + const { x, y, width, height } = rect; + const rp1 = new Point(x, y); + const rp2 = new Point(x + width, y); + const rp3 = new Point(x + width, y + height); + const rp4 = new Point(x, y + height); + return ( + lineLine(pa, pb, rp1, rp2) || + lineLine(pa, pb, rp2, rp3) || + lineLine(pa, pb, rp3, rp4) || + lineLine(pa, pb, rp1, rp4) + ); +} + +/** + * 多线段和矩形碰撞检测 + * @param points + * @param rect + * @returns false / 碰撞的线段序号 + */ +export function polylineBox(points: IPointData[], rect: Rectangle): boolean { + if (points.length < 2) { + return false; + } + + for (let i = 0; i < points.length - 1; i++) { + const p1 = points[i]; + const p2 = points[i + 1]; + + if (lineBox(p1, p2, rect)) { + return true; + } + } + return false; +} + +/** + * 两点碰撞检测 + * @param p1 + * @param p2 + * @param tolerance + * @returns + */ +export function pointPoint2( + p1: IPointData, + p2: IPointData, + tolerance: number +): boolean { + return pointPoint(p1.x, p1.y, p2.x, p2.y, tolerance); +} + +/** + * 两点碰撞检测 + * @param x1 + * @param y1 + * @param x2 + * @param y2 + * @param tolerance 容忍度/两点半径和 + * @returns + */ +export function pointPoint( + x1: number, + y1: number, + x2: number, + y2: number, + tolerance: number +): boolean { + return distance(x1, y1, x2, y2) <= tolerance; +} + +/** + * 两点距离 + * @param x1 + * @param y1 + * @param x2 + * @param y2 + * @returns + */ +export function distance(x1: number, y1: number, x2: number, y2: number) { + return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)); +} + +/** + * 两点距离 + * @param p1 + * @param p2 + * @returns + */ +export function distance2(p1: IPointData, p2: IPointData): number { + return distance(p1.x, p1.y, p2.x, p2.y); +} + +/** + * 圆和点的碰撞检测 + * @param x1 圆心x + * @param y1 圆心y + * @param r1 圆半径 + * @param x2 点x + * @param y2 点y + * @returns + */ +export function circlePoint( + x1: number, + y1: number, + r1: number, + x2: number, + y2: number +) { + const x = x2 - x1; + const y = y2 - y1; + return x * x + y * y <= r1 * r1; +} + +/** + * 圆和点的碰撞检测--不包括圆内部 + */ +export function circlePoint2( + x1: number, + y1: number, + r1: number, + x2: number, + y2: number, + tolerance: number +) { + const x = x2 - x1; + const y = y2 - y1; + return ( + x * x + y * y <= (r1 + tolerance) * (r1 + tolerance) && + x * x + y * y >= (r1 - tolerance) * (r1 - tolerance) + ); +} + +/** + * 点和多边形碰撞检测 + */ +export function pointPolygon( + p: IPointData, + points: IPointData[], + lineWidth: number +): boolean { + const { x, y } = p; + const length = points.length; + let c = false; + let i, j; + for (i = 0, j = length - 1; i < length; i++) { + if ( + points[i].y > y !== points[j].y > y && + x < + ((points[j].x - points[i].x) * (y - points[i].y)) / + (points[j].y - points[i].y) + + points[i].x + ) { + c = !c; + } + j = i; + } + if (c) { + return true; + } + for (i = 0; i < length - 1; i++) { + let p1, p2; + if (i === length - 1) { + p1 = points[i]; + p2 = points[0]; + } else { + p1 = points[i]; + p2 = points[i + 1]; + } + if (linePoint(p1, p2, p, lineWidth)) { + return true; + } + } + return false; +} + +/** + * 线和多边形碰撞检测 + * @param p1 + * @param p2 + * @param points + * @param tolerance 多边形包围线宽 + * @returns + */ +export function linePolygon( + p1: IPointData, + p2: IPointData, + points: IPointData[], + lineWidth: number, + polygonWidth: number +): boolean { + if (pointPolygon(p1, points, polygonWidth)) { + return true; + } + const length = points.length; + for (let i = 0; i < length; i++) { + let pa, pb; + if (i === length - 1) { + pa = points[i]; + pb = points[0]; + } else { + pa = points[i]; + pb = points[i + 1]; + } + // TODO:此处后续需考虑有线宽的情况 + if (lineLine(pa, pb, p1, p2)) { + return true; + } + } + return false; +} + +/** + * 多边线与多边形碰撞检测 + * @param polylinePoints 多边线所有点坐标 + * @param polygonPoints 多边形所有点坐标 + * @param polylineWidth 多边线的线宽 + * @param polygonWidth 多边形线宽 + * @returns + */ +export function polylinePolygon( + polylinePoints: IPointData[], + polygonPoints: IPointData[], + polylineWidth: number, + polygonWidth: number +): boolean { + const length = polylinePoints.length; + for (let i = 0; i < length - 1; i++) { + const p1 = polylinePoints[i]; + const p2 = polylinePoints[i + 1]; + if (linePolygon(p1, p2, polygonPoints, polylineWidth, polygonWidth)) { + return true; + } + } + return false; +} diff --git a/src/jl-graphic/utils/index.ts b/src/jl-graphic/utils/index.ts new file mode 100644 index 0000000..57ec464 --- /dev/null +++ b/src/jl-graphic/utils/index.ts @@ -0,0 +1,53 @@ +import { Point, Rectangle } from 'pixi.js'; + +export * from './GraphicUtils'; +export * from './IntersectUtils'; + +export const UP: Point = new Point(0, -1); +export const DOWN: Point = new Point(0, 1); +export const LEFT: Point = new Point(-1, 0); +export const RIGHT: Point = new Point(1, 0); + +/** + * 越界结果 + */ +export class OutOfBound { + left: boolean; + top: boolean; + right: boolean; + bottom: boolean; + constructor(left: boolean, top: boolean, right: boolean, bottom: boolean) { + this.left = left; + this.top = top; + this.right = right; + this.bottom = bottom; + } + static check(rect: Rectangle, bound: Rectangle): OutOfBound { + const left = rect.left < bound.left; + const top = rect.top < bound.top; + const right = rect.right > bound.right; + const bottom = rect.bottom > bound.bottom; + return new OutOfBound(left, top, right, bottom); + } + static none(): OutOfBound { + return new OutOfBound(false, false, false, false); + } + static leftOut(): OutOfBound { + return new OutOfBound(true, false, false, false); + } + static topOut(): OutOfBound { + return new OutOfBound(false, true, false, false); + } + static rightOut(): OutOfBound { + return new OutOfBound(false, false, true, false); + } + static bottomOut(): OutOfBound { + return new OutOfBound(false, false, false, true); + } + static leftTopOut(): OutOfBound { + return new OutOfBound(true, true, false, false); + } + static rightBottomOut(): OutOfBound { + return new OutOfBound(false, false, true, true); + } +} diff --git a/src/layouts/DrawLayout.vue b/src/layouts/DrawLayout.vue new file mode 100644 index 0000000..e6b6726 --- /dev/null +++ b/src/layouts/DrawLayout.vue @@ -0,0 +1,361 @@ + + + diff --git a/src/layouts/LineLayout.vue b/src/layouts/LineLayout.vue new file mode 100644 index 0000000..404f66b --- /dev/null +++ b/src/layouts/LineLayout.vue @@ -0,0 +1,81 @@ + + + diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue new file mode 100644 index 0000000..356ecc8 --- /dev/null +++ b/src/layouts/MainLayout.vue @@ -0,0 +1,74 @@ + + + diff --git a/src/pages/DraftManage.vue b/src/pages/DraftManage.vue new file mode 100644 index 0000000..a157213 --- /dev/null +++ b/src/pages/DraftManage.vue @@ -0,0 +1,365 @@ + + + diff --git a/src/pages/ErrorNotFound.vue b/src/pages/ErrorNotFound.vue new file mode 100644 index 0000000..f4e0bb8 --- /dev/null +++ b/src/pages/ErrorNotFound.vue @@ -0,0 +1,27 @@ + + + diff --git a/src/pages/IndexPage.vue b/src/pages/IndexPage.vue new file mode 100644 index 0000000..d0684cb --- /dev/null +++ b/src/pages/IndexPage.vue @@ -0,0 +1,7 @@ + + + diff --git a/src/pages/LineInfoManage.vue b/src/pages/LineInfoManage.vue new file mode 100644 index 0000000..a348f11 --- /dev/null +++ b/src/pages/LineInfoManage.vue @@ -0,0 +1,270 @@ + + + diff --git a/src/pages/LineMonitorPage.vue b/src/pages/LineMonitorPage.vue new file mode 100644 index 0000000..abd5510 --- /dev/null +++ b/src/pages/LineMonitorPage.vue @@ -0,0 +1,69 @@ + + + diff --git a/src/pages/MonitorPage.vue b/src/pages/MonitorPage.vue new file mode 100644 index 0000000..38ec6b1 --- /dev/null +++ b/src/pages/MonitorPage.vue @@ -0,0 +1,91 @@ + + + diff --git a/src/pages/PublishManage.vue b/src/pages/PublishManage.vue new file mode 100644 index 0000000..4faa6d5 --- /dev/null +++ b/src/pages/PublishManage.vue @@ -0,0 +1,182 @@ + + + diff --git a/src/pages/UserLogin.vue b/src/pages/UserLogin.vue new file mode 100644 index 0000000..1e0c96c --- /dev/null +++ b/src/pages/UserLogin.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/src/pages/UserManage.vue b/src/pages/UserManage.vue new file mode 100644 index 0000000..43f81ba --- /dev/null +++ b/src/pages/UserManage.vue @@ -0,0 +1,215 @@ + + + diff --git a/src/pages/UserRegister.vue b/src/pages/UserRegister.vue new file mode 100644 index 0000000..901f83b --- /dev/null +++ b/src/pages/UserRegister.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/src/protos/Device.ts b/src/protos/Device.ts new file mode 100644 index 0000000..ce53f65 --- /dev/null +++ b/src/protos/Device.ts @@ -0,0 +1,566 @@ +/** + * Generated by the protoc-gen-ts. DO NOT EDIT! + * compiler version: 4.23.1 + * source: Device.proto + * git: https://github.com/thesayyn/protoc-gen-ts */ +import * as pb_1 from "google-protobuf"; +export class Device extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + lineId?: number; + reportId?: number; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("lineId" in data && data.lineId != undefined) { + this.lineId = data.lineId; + } + if ("reportId" in data && data.reportId != undefined) { + this.reportId = data.reportId; + } + } + } + get lineId() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set lineId(value: number) { + pb_1.Message.setField(this, 1, value); + } + get reportId() { + return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; + } + set reportId(value: number) { + pb_1.Message.setField(this, 2, value); + } + static fromObject(data: { + lineId?: number; + reportId?: number; + }): Device { + const message = new Device({}); + if (data.lineId != null) { + message.lineId = data.lineId; + } + if (data.reportId != null) { + message.reportId = data.reportId; + } + return message; + } + toObject() { + const data: { + lineId?: number; + reportId?: number; + } = {}; + if (this.lineId != null) { + data.lineId = this.lineId; + } + if (this.reportId != null) { + data.reportId = this.reportId; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.lineId != 0) + writer.writeInt32(1, this.lineId); + if (this.reportId != 0) + writer.writeInt32(2, this.reportId); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Device { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Device(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.lineId = reader.readInt32(); + break; + case 2: + message.reportId = reader.readInt32(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Device { + return Device.deserialize(bytes); + } +} +export class DeviceDetail extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + deviceType?: string; + deviceName?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("deviceType" in data && data.deviceType != undefined) { + this.deviceType = data.deviceType; + } + if ("deviceName" in data && data.deviceName != undefined) { + this.deviceName = data.deviceName; + } + } + } + get deviceType() { + return pb_1.Message.getFieldWithDefault(this, 1, "") as string; + } + set deviceType(value: string) { + pb_1.Message.setField(this, 1, value); + } + get deviceName() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set deviceName(value: string) { + pb_1.Message.setField(this, 2, value); + } + static fromObject(data: { + deviceType?: string; + deviceName?: string; + }): DeviceDetail { + const message = new DeviceDetail({}); + if (data.deviceType != null) { + message.deviceType = data.deviceType; + } + if (data.deviceName != null) { + message.deviceName = data.deviceName; + } + return message; + } + toObject() { + const data: { + deviceType?: string; + deviceName?: string; + } = {}; + if (this.deviceType != null) { + data.deviceType = this.deviceType; + } + if (this.deviceName != null) { + data.deviceName = this.deviceName; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.deviceType.length) + writer.writeString(1, this.deviceType); + if (this.deviceName.length) + writer.writeString(2, this.deviceName); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): DeviceDetail { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new DeviceDetail(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.deviceType = reader.readString(); + break; + case 2: + message.deviceName = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): DeviceDetail { + return DeviceDetail.deserialize(bytes); + } +} +export class Track extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + device?: Device; + detail?: DeviceDetail; + speedLimit?: number; + limitType?: number; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("device" in data && data.device != undefined) { + this.device = data.device; + } + if ("detail" in data && data.detail != undefined) { + this.detail = data.detail; + } + if ("speedLimit" in data && data.speedLimit != undefined) { + this.speedLimit = data.speedLimit; + } + if ("limitType" in data && data.limitType != undefined) { + this.limitType = data.limitType; + } + } + } + get device() { + return pb_1.Message.getWrapperField(this, Device, 1) as Device; + } + set device(value: Device) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_device() { + return pb_1.Message.getField(this, 1) != null; + } + get detail() { + return pb_1.Message.getWrapperField(this, DeviceDetail, 2) as DeviceDetail; + } + set detail(value: DeviceDetail) { + pb_1.Message.setWrapperField(this, 2, value); + } + get has_detail() { + return pb_1.Message.getField(this, 2) != null; + } + get speedLimit() { + return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; + } + set speedLimit(value: number) { + pb_1.Message.setField(this, 3, value); + } + get limitType() { + return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; + } + set limitType(value: number) { + pb_1.Message.setField(this, 4, value); + } + static fromObject(data: { + device?: ReturnType; + detail?: ReturnType; + speedLimit?: number; + limitType?: number; + }): Track { + const message = new Track({}); + if (data.device != null) { + message.device = Device.fromObject(data.device); + } + if (data.detail != null) { + message.detail = DeviceDetail.fromObject(data.detail); + } + if (data.speedLimit != null) { + message.speedLimit = data.speedLimit; + } + if (data.limitType != null) { + message.limitType = data.limitType; + } + return message; + } + toObject() { + const data: { + device?: ReturnType; + detail?: ReturnType; + speedLimit?: number; + limitType?: number; + } = {}; + if (this.device != null) { + data.device = this.device.toObject(); + } + if (this.detail != null) { + data.detail = this.detail.toObject(); + } + if (this.speedLimit != null) { + data.speedLimit = this.speedLimit; + } + if (this.limitType != null) { + data.limitType = this.limitType; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_device) + writer.writeMessage(1, this.device, () => this.device.serialize(writer)); + if (this.has_detail) + writer.writeMessage(2, this.detail, () => this.detail.serialize(writer)); + if (this.speedLimit != 0) + writer.writeFloat(3, this.speedLimit); + if (this.limitType != 0) + writer.writeInt32(4, this.limitType); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Track { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Track(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.device, () => message.device = Device.deserialize(reader)); + break; + case 2: + reader.readMessage(message.detail, () => message.detail = DeviceDetail.deserialize(reader)); + break; + case 3: + message.speedLimit = reader.readFloat(); + break; + case 4: + message.limitType = reader.readInt32(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Track { + return Track.deserialize(bytes); + } +} +export class Platform extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + device?: Device; + detail?: DeviceDetail; + stopTime?: number; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("device" in data && data.device != undefined) { + this.device = data.device; + } + if ("detail" in data && data.detail != undefined) { + this.detail = data.detail; + } + if ("stopTime" in data && data.stopTime != undefined) { + this.stopTime = data.stopTime; + } + } + } + get device() { + return pb_1.Message.getWrapperField(this, Device, 1) as Device; + } + set device(value: Device) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_device() { + return pb_1.Message.getField(this, 1) != null; + } + get detail() { + return pb_1.Message.getWrapperField(this, DeviceDetail, 2) as DeviceDetail; + } + set detail(value: DeviceDetail) { + pb_1.Message.setWrapperField(this, 2, value); + } + get has_detail() { + return pb_1.Message.getField(this, 2) != null; + } + get stopTime() { + return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; + } + set stopTime(value: number) { + pb_1.Message.setField(this, 3, value); + } + static fromObject(data: { + device?: ReturnType; + detail?: ReturnType; + stopTime?: number; + }): Platform { + const message = new Platform({}); + if (data.device != null) { + message.device = Device.fromObject(data.device); + } + if (data.detail != null) { + message.detail = DeviceDetail.fromObject(data.detail); + } + if (data.stopTime != null) { + message.stopTime = data.stopTime; + } + return message; + } + toObject() { + const data: { + device?: ReturnType; + detail?: ReturnType; + stopTime?: number; + } = {}; + if (this.device != null) { + data.device = this.device.toObject(); + } + if (this.detail != null) { + data.detail = this.detail.toObject(); + } + if (this.stopTime != null) { + data.stopTime = this.stopTime; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_device) + writer.writeMessage(1, this.device, () => this.device.serialize(writer)); + if (this.has_detail) + writer.writeMessage(2, this.detail, () => this.detail.serialize(writer)); + if (this.stopTime != 0) + writer.writeInt32(3, this.stopTime); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Platform { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Platform(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.device, () => message.device = Device.deserialize(reader)); + break; + case 2: + reader.readMessage(message.detail, () => message.detail = DeviceDetail.deserialize(reader)); + break; + case 3: + message.stopTime = reader.readInt32(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Platform { + return Platform.deserialize(bytes); + } +} +export class Switch extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + device?: Device; + detail?: DeviceDetail; + speedLimit?: number; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("device" in data && data.device != undefined) { + this.device = data.device; + } + if ("detail" in data && data.detail != undefined) { + this.detail = data.detail; + } + if ("speedLimit" in data && data.speedLimit != undefined) { + this.speedLimit = data.speedLimit; + } + } + } + get device() { + return pb_1.Message.getWrapperField(this, Device, 1) as Device; + } + set device(value: Device) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_device() { + return pb_1.Message.getField(this, 1) != null; + } + get detail() { + return pb_1.Message.getWrapperField(this, DeviceDetail, 2) as DeviceDetail; + } + set detail(value: DeviceDetail) { + pb_1.Message.setWrapperField(this, 2, value); + } + get has_detail() { + return pb_1.Message.getField(this, 2) != null; + } + get speedLimit() { + return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; + } + set speedLimit(value: number) { + pb_1.Message.setField(this, 3, value); + } + static fromObject(data: { + device?: ReturnType; + detail?: ReturnType; + speedLimit?: number; + }): Switch { + const message = new Switch({}); + if (data.device != null) { + message.device = Device.fromObject(data.device); + } + if (data.detail != null) { + message.detail = DeviceDetail.fromObject(data.detail); + } + if (data.speedLimit != null) { + message.speedLimit = data.speedLimit; + } + return message; + } + toObject() { + const data: { + device?: ReturnType; + detail?: ReturnType; + speedLimit?: number; + } = {}; + if (this.device != null) { + data.device = this.device.toObject(); + } + if (this.detail != null) { + data.detail = this.detail.toObject(); + } + if (this.speedLimit != null) { + data.speedLimit = this.speedLimit; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_device) + writer.writeMessage(1, this.device, () => this.device.serialize(writer)); + if (this.has_detail) + writer.writeMessage(2, this.detail, () => this.detail.serialize(writer)); + if (this.speedLimit != 0) + writer.writeFloat(3, this.speedLimit); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Switch { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Switch(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.device, () => message.device = Device.deserialize(reader)); + break; + case 2: + reader.readMessage(message.detail, () => message.detail = DeviceDetail.deserialize(reader)); + break; + case 3: + message.speedLimit = reader.readFloat(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Switch { + return Switch.deserialize(bytes); + } +} diff --git a/src/protos/LineNetTrainOffset.ts b/src/protos/LineNetTrainOffset.ts new file mode 100644 index 0000000..5b99242 --- /dev/null +++ b/src/protos/LineNetTrainOffset.ts @@ -0,0 +1,234 @@ +/** + * Generated by the protoc-gen-ts. DO NOT EDIT! + * compiler version: 4.23.1 + * source: LineNetTrainOffset.proto + * git: https://github.com/thesayyn/protoc-gen-ts */ +import * as pb_1 from "google-protobuf"; +export class LineNetTrainOffset extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + lineId?: number; + groupId?: string; + dir?: number; + show?: boolean; + windowNo?: number; + windowOffset?: number; + destinationId?: string; + backId?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("lineId" in data && data.lineId != undefined) { + this.lineId = data.lineId; + } + if ("groupId" in data && data.groupId != undefined) { + this.groupId = data.groupId; + } + if ("dir" in data && data.dir != undefined) { + this.dir = data.dir; + } + if ("show" in data && data.show != undefined) { + this.show = data.show; + } + if ("windowNo" in data && data.windowNo != undefined) { + this.windowNo = data.windowNo; + } + if ("windowOffset" in data && data.windowOffset != undefined) { + this.windowOffset = data.windowOffset; + } + if ("destinationId" in data && data.destinationId != undefined) { + this.destinationId = data.destinationId; + } + if ("backId" in data && data.backId != undefined) { + this.backId = data.backId; + } + } + } + get lineId() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set lineId(value: number) { + pb_1.Message.setField(this, 1, value); + } + get groupId() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set groupId(value: string) { + pb_1.Message.setField(this, 2, value); + } + get dir() { + return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; + } + set dir(value: number) { + pb_1.Message.setField(this, 3, value); + } + get show() { + return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean; + } + set show(value: boolean) { + pb_1.Message.setField(this, 4, value); + } + get windowNo() { + return pb_1.Message.getFieldWithDefault(this, 5, 0) as number; + } + set windowNo(value: number) { + pb_1.Message.setField(this, 5, value); + } + get windowOffset() { + return pb_1.Message.getFieldWithDefault(this, 6, 0) as number; + } + set windowOffset(value: number) { + pb_1.Message.setField(this, 6, value); + } + get destinationId() { + return pb_1.Message.getFieldWithDefault(this, 7, "") as string; + } + set destinationId(value: string) { + pb_1.Message.setField(this, 7, value); + } + get backId() { + return pb_1.Message.getFieldWithDefault(this, 8, "") as string; + } + set backId(value: string) { + pb_1.Message.setField(this, 8, value); + } + static fromObject(data: { + lineId?: number; + groupId?: string; + dir?: number; + show?: boolean; + windowNo?: number; + windowOffset?: number; + destinationId?: string; + backId?: string; + }): LineNetTrainOffset { + const message = new LineNetTrainOffset({}); + if (data.lineId != null) { + message.lineId = data.lineId; + } + if (data.groupId != null) { + message.groupId = data.groupId; + } + if (data.dir != null) { + message.dir = data.dir; + } + if (data.show != null) { + message.show = data.show; + } + if (data.windowNo != null) { + message.windowNo = data.windowNo; + } + if (data.windowOffset != null) { + message.windowOffset = data.windowOffset; + } + if (data.destinationId != null) { + message.destinationId = data.destinationId; + } + if (data.backId != null) { + message.backId = data.backId; + } + return message; + } + toObject() { + const data: { + lineId?: number; + groupId?: string; + dir?: number; + show?: boolean; + windowNo?: number; + windowOffset?: number; + destinationId?: string; + backId?: string; + } = {}; + if (this.lineId != null) { + data.lineId = this.lineId; + } + if (this.groupId != null) { + data.groupId = this.groupId; + } + if (this.dir != null) { + data.dir = this.dir; + } + if (this.show != null) { + data.show = this.show; + } + if (this.windowNo != null) { + data.windowNo = this.windowNo; + } + if (this.windowOffset != null) { + data.windowOffset = this.windowOffset; + } + if (this.destinationId != null) { + data.destinationId = this.destinationId; + } + if (this.backId != null) { + data.backId = this.backId; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.lineId != 0) + writer.writeInt32(1, this.lineId); + if (this.groupId.length) + writer.writeString(2, this.groupId); + if (this.dir != 0) + writer.writeInt32(3, this.dir); + if (this.show != false) + writer.writeBool(4, this.show); + if (this.windowNo != 0) + writer.writeInt32(5, this.windowNo); + if (this.windowOffset != 0) + writer.writeInt32(6, this.windowOffset); + if (this.destinationId.length) + writer.writeString(7, this.destinationId); + if (this.backId.length) + writer.writeString(8, this.backId); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): LineNetTrainOffset { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new LineNetTrainOffset(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.lineId = reader.readInt32(); + break; + case 2: + message.groupId = reader.readString(); + break; + case 3: + message.dir = reader.readInt32(); + break; + case 4: + message.show = reader.readBool(); + break; + case 5: + message.windowNo = reader.readInt32(); + break; + case 6: + message.windowOffset = reader.readInt32(); + break; + case 7: + message.destinationId = reader.readString(); + break; + case 8: + message.backId = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): LineNetTrainOffset { + return LineNetTrainOffset.deserialize(bytes); + } +} diff --git a/src/protos/LineNetTrainOffsetDiagram.ts b/src/protos/LineNetTrainOffsetDiagram.ts new file mode 100644 index 0000000..392c1e5 --- /dev/null +++ b/src/protos/LineNetTrainOffsetDiagram.ts @@ -0,0 +1,236 @@ +/** + * Generated by the protoc-gen-ts. DO NOT EDIT! + * compiler version: 4.23.1 + * source: LineNetTrainOffsetDiagram.proto + * git: https://github.com/thesayyn/protoc-gen-ts */ +import * as pb_1 from "google-protobuf"; +export namespace diagram { + export class LineNetTrainOffsetDiagram extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + lineId?: number; + groupId?: string; + dir?: number; + show?: boolean; + windowNo?: number; + windowOffset?: number; + destinationId?: string; + backId?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("lineId" in data && data.lineId != undefined) { + this.lineId = data.lineId; + } + if ("groupId" in data && data.groupId != undefined) { + this.groupId = data.groupId; + } + if ("dir" in data && data.dir != undefined) { + this.dir = data.dir; + } + if ("show" in data && data.show != undefined) { + this.show = data.show; + } + if ("windowNo" in data && data.windowNo != undefined) { + this.windowNo = data.windowNo; + } + if ("windowOffset" in data && data.windowOffset != undefined) { + this.windowOffset = data.windowOffset; + } + if ("destinationId" in data && data.destinationId != undefined) { + this.destinationId = data.destinationId; + } + if ("backId" in data && data.backId != undefined) { + this.backId = data.backId; + } + } + } + get lineId() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set lineId(value: number) { + pb_1.Message.setField(this, 1, value); + } + get groupId() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set groupId(value: string) { + pb_1.Message.setField(this, 2, value); + } + get dir() { + return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; + } + set dir(value: number) { + pb_1.Message.setField(this, 3, value); + } + get show() { + return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean; + } + set show(value: boolean) { + pb_1.Message.setField(this, 4, value); + } + get windowNo() { + return pb_1.Message.getFieldWithDefault(this, 5, 0) as number; + } + set windowNo(value: number) { + pb_1.Message.setField(this, 5, value); + } + get windowOffset() { + return pb_1.Message.getFieldWithDefault(this, 6, 0) as number; + } + set windowOffset(value: number) { + pb_1.Message.setField(this, 6, value); + } + get destinationId() { + return pb_1.Message.getFieldWithDefault(this, 7, "") as string; + } + set destinationId(value: string) { + pb_1.Message.setField(this, 7, value); + } + get backId() { + return pb_1.Message.getFieldWithDefault(this, 8, "") as string; + } + set backId(value: string) { + pb_1.Message.setField(this, 8, value); + } + static fromObject(data: { + lineId?: number; + groupId?: string; + dir?: number; + show?: boolean; + windowNo?: number; + windowOffset?: number; + destinationId?: string; + backId?: string; + }): LineNetTrainOffsetDiagram { + const message = new LineNetTrainOffsetDiagram({}); + if (data.lineId != null) { + message.lineId = data.lineId; + } + if (data.groupId != null) { + message.groupId = data.groupId; + } + if (data.dir != null) { + message.dir = data.dir; + } + if (data.show != null) { + message.show = data.show; + } + if (data.windowNo != null) { + message.windowNo = data.windowNo; + } + if (data.windowOffset != null) { + message.windowOffset = data.windowOffset; + } + if (data.destinationId != null) { + message.destinationId = data.destinationId; + } + if (data.backId != null) { + message.backId = data.backId; + } + return message; + } + toObject() { + const data: { + lineId?: number; + groupId?: string; + dir?: number; + show?: boolean; + windowNo?: number; + windowOffset?: number; + destinationId?: string; + backId?: string; + } = {}; + if (this.lineId != null) { + data.lineId = this.lineId; + } + if (this.groupId != null) { + data.groupId = this.groupId; + } + if (this.dir != null) { + data.dir = this.dir; + } + if (this.show != null) { + data.show = this.show; + } + if (this.windowNo != null) { + data.windowNo = this.windowNo; + } + if (this.windowOffset != null) { + data.windowOffset = this.windowOffset; + } + if (this.destinationId != null) { + data.destinationId = this.destinationId; + } + if (this.backId != null) { + data.backId = this.backId; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.lineId != 0) + writer.writeInt32(1, this.lineId); + if (this.groupId.length) + writer.writeString(2, this.groupId); + if (this.dir != 0) + writer.writeInt32(3, this.dir); + if (this.show != false) + writer.writeBool(4, this.show); + if (this.windowNo != 0) + writer.writeInt32(5, this.windowNo); + if (this.windowOffset != 0) + writer.writeInt32(6, this.windowOffset); + if (this.destinationId.length) + writer.writeString(7, this.destinationId); + if (this.backId.length) + writer.writeString(8, this.backId); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): LineNetTrainOffsetDiagram { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new LineNetTrainOffsetDiagram(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.lineId = reader.readInt32(); + break; + case 2: + message.groupId = reader.readString(); + break; + case 3: + message.dir = reader.readInt32(); + break; + case 4: + message.show = reader.readBool(); + break; + case 5: + message.windowNo = reader.readInt32(); + break; + case 6: + message.windowOffset = reader.readInt32(); + break; + case 7: + message.destinationId = reader.readString(); + break; + case 8: + message.backId = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): LineNetTrainOffsetDiagram { + return LineNetTrainOffsetDiagram.deserialize(bytes); + } + } +} diff --git a/src/protos/device_info.ts b/src/protos/device_info.ts new file mode 100644 index 0000000..baa1e88 --- /dev/null +++ b/src/protos/device_info.ts @@ -0,0 +1,327 @@ +/** + * Generated by the protoc-gen-ts. DO NOT EDIT! + * compiler version: 4.23.1 + * source: device_info.proto + * git: https://github.com/thesayyn/protoc-gen-ts */ +import * as dependency_1 from "./stationLayoutGraphics"; +import * as pb_1 from "google-protobuf"; +export namespace state { + export class Section extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + id?: string; + code?: string; + type?: dependency_1.graphicData.Section.SectionType; + children?: Section[]; + kilometerSystem?: dependency_1.graphicData.KilometerSystem[]; + convertKilometer?: number[]; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [4, 5, 7], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("type" in data && data.type != undefined) { + this.type = data.type; + } + if ("children" in data && data.children != undefined) { + this.children = data.children; + } + if ("kilometerSystem" in data && data.kilometerSystem != undefined) { + this.kilometerSystem = data.kilometerSystem; + } + if ("convertKilometer" in data && data.convertKilometer != undefined) { + this.convertKilometer = data.convertKilometer; + } + } + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 1, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 1, value); + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get type() { + return pb_1.Message.getFieldWithDefault(this, 3, dependency_1.graphicData.Section.SectionType.Physical) as dependency_1.graphicData.Section.SectionType; + } + set type(value: dependency_1.graphicData.Section.SectionType) { + pb_1.Message.setField(this, 3, value); + } + get children() { + return pb_1.Message.getRepeatedWrapperField(this, Section, 4) as Section[]; + } + set children(value: Section[]) { + pb_1.Message.setRepeatedWrapperField(this, 4, value); + } + get kilometerSystem() { + return pb_1.Message.getRepeatedWrapperField(this, dependency_1.graphicData.KilometerSystem, 5) as dependency_1.graphicData.KilometerSystem[]; + } + set kilometerSystem(value: dependency_1.graphicData.KilometerSystem[]) { + pb_1.Message.setRepeatedWrapperField(this, 5, value); + } + get convertKilometer() { + return pb_1.Message.getFieldWithDefault(this, 7, []) as number[]; + } + set convertKilometer(value: number[]) { + pb_1.Message.setField(this, 7, value); + } + static fromObject(data: { + id?: string; + code?: string; + type?: dependency_1.graphicData.Section.SectionType; + children?: ReturnType[]; + kilometerSystem?: ReturnType[]; + convertKilometer?: number[]; + }): Section { + const message = new Section({}); + if (data.id != null) { + message.id = data.id; + } + if (data.code != null) { + message.code = data.code; + } + if (data.type != null) { + message.type = data.type; + } + if (data.children != null) { + message.children = data.children.map(item => Section.fromObject(item)); + } + if (data.kilometerSystem != null) { + message.kilometerSystem = data.kilometerSystem.map(item => dependency_1.graphicData.KilometerSystem.fromObject(item)); + } + if (data.convertKilometer != null) { + message.convertKilometer = data.convertKilometer; + } + return message; + } + toObject() { + const data: { + id?: string; + code?: string; + type?: dependency_1.graphicData.Section.SectionType; + children?: ReturnType[]; + kilometerSystem?: ReturnType[]; + convertKilometer?: number[]; + } = {}; + if (this.id != null) { + data.id = this.id; + } + if (this.code != null) { + data.code = this.code; + } + if (this.type != null) { + data.type = this.type; + } + if (this.children != null) { + data.children = this.children.map((item: Section) => item.toObject()); + } + if (this.kilometerSystem != null) { + data.kilometerSystem = this.kilometerSystem.map((item: dependency_1.graphicData.KilometerSystem) => item.toObject()); + } + if (this.convertKilometer != null) { + data.convertKilometer = this.convertKilometer; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.id.length) + writer.writeString(1, this.id); + if (this.code.length) + writer.writeString(2, this.code); + if (this.type != dependency_1.graphicData.Section.SectionType.Physical) + writer.writeEnum(3, this.type); + if (this.children.length) + writer.writeRepeatedMessage(4, this.children, (item: Section) => item.serialize(writer)); + if (this.kilometerSystem.length) + writer.writeRepeatedMessage(5, this.kilometerSystem, (item: dependency_1.graphicData.KilometerSystem) => item.serialize(writer)); + if (this.convertKilometer.length) + writer.writePackedInt64(7, this.convertKilometer); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Section { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Section(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.id = reader.readString(); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + message.type = reader.readEnum(); + break; + case 4: + reader.readMessage(message.children, () => pb_1.Message.addToRepeatedWrapperField(message, 4, Section.deserialize(reader), Section)); + break; + case 5: + reader.readMessage(message.kilometerSystem, () => pb_1.Message.addToRepeatedWrapperField(message, 5, dependency_1.graphicData.KilometerSystem.deserialize(reader), dependency_1.graphicData.KilometerSystem)); + break; + case 7: + message.convertKilometer = reader.readPackedInt64(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Section { + return Section.deserialize(bytes); + } + } + export class Switch extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + id?: string; + code?: string; + kilometerSystem?: dependency_1.graphicData.KilometerSystem[]; + convertKilometer?: number[]; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [3, 4], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("kilometerSystem" in data && data.kilometerSystem != undefined) { + this.kilometerSystem = data.kilometerSystem; + } + if ("convertKilometer" in data && data.convertKilometer != undefined) { + this.convertKilometer = data.convertKilometer; + } + } + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 1, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 1, value); + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get kilometerSystem() { + return pb_1.Message.getRepeatedWrapperField(this, dependency_1.graphicData.KilometerSystem, 3) as dependency_1.graphicData.KilometerSystem[]; + } + set kilometerSystem(value: dependency_1.graphicData.KilometerSystem[]) { + pb_1.Message.setRepeatedWrapperField(this, 3, value); + } + get convertKilometer() { + return pb_1.Message.getFieldWithDefault(this, 4, []) as number[]; + } + set convertKilometer(value: number[]) { + pb_1.Message.setField(this, 4, value); + } + static fromObject(data: { + id?: string; + code?: string; + kilometerSystem?: ReturnType[]; + convertKilometer?: number[]; + }): Switch { + const message = new Switch({}); + if (data.id != null) { + message.id = data.id; + } + if (data.code != null) { + message.code = data.code; + } + if (data.kilometerSystem != null) { + message.kilometerSystem = data.kilometerSystem.map(item => dependency_1.graphicData.KilometerSystem.fromObject(item)); + } + if (data.convertKilometer != null) { + message.convertKilometer = data.convertKilometer; + } + return message; + } + toObject() { + const data: { + id?: string; + code?: string; + kilometerSystem?: ReturnType[]; + convertKilometer?: number[]; + } = {}; + if (this.id != null) { + data.id = this.id; + } + if (this.code != null) { + data.code = this.code; + } + if (this.kilometerSystem != null) { + data.kilometerSystem = this.kilometerSystem.map((item: dependency_1.graphicData.KilometerSystem) => item.toObject()); + } + if (this.convertKilometer != null) { + data.convertKilometer = this.convertKilometer; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.id.length) + writer.writeString(1, this.id); + if (this.code.length) + writer.writeString(2, this.code); + if (this.kilometerSystem.length) + writer.writeRepeatedMessage(3, this.kilometerSystem, (item: dependency_1.graphicData.KilometerSystem) => item.serialize(writer)); + if (this.convertKilometer.length) + writer.writePackedInt64(4, this.convertKilometer); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Switch { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Switch(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.id = reader.readString(); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + reader.readMessage(message.kilometerSystem, () => pb_1.Message.addToRepeatedWrapperField(message, 3, dependency_1.graphicData.KilometerSystem.deserialize(reader), dependency_1.graphicData.KilometerSystem)); + break; + case 4: + message.convertKilometer = reader.readPackedInt64(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Switch { + return Switch.deserialize(bytes); + } + } +} diff --git a/src/protos/device_status.ts b/src/protos/device_status.ts new file mode 100644 index 0000000..0aecd19 --- /dev/null +++ b/src/protos/device_status.ts @@ -0,0 +1,4489 @@ +/** + * Generated by the protoc-gen-ts. DO NOT EDIT! + * compiler version: 4.23.1 + * source: device_status.proto + * git: https://github.com/thesayyn/protoc-gen-ts */ +import * as pb_1 from "google-protobuf"; +export namespace state { + export enum DeviceType { + UNKNOW = 0, + RTU = 1, + STATION = 2, + SIGNAL = 3, + SWITCH = 4, + TRACK = 5, + ENTRY = 6, + PLATFORM = 7, + SCADA = 8, + WATERPROOF_DOOR = 9, + WORK_AREA = 10, + GAMA = 11 + } + export class Rtu extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + ipRtuStusDown?: boolean; + ipRtuStusInLocalCtrl?: boolean; + ipRtuStusInCentralCtrl?: boolean; + ipRtuStusInEmergencyCtrl?: boolean; + id?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("ipRtuStusDown" in data && data.ipRtuStusDown != undefined) { + this.ipRtuStusDown = data.ipRtuStusDown; + } + if ("ipRtuStusInLocalCtrl" in data && data.ipRtuStusInLocalCtrl != undefined) { + this.ipRtuStusInLocalCtrl = data.ipRtuStusInLocalCtrl; + } + if ("ipRtuStusInCentralCtrl" in data && data.ipRtuStusInCentralCtrl != undefined) { + this.ipRtuStusInCentralCtrl = data.ipRtuStusInCentralCtrl; + } + if ("ipRtuStusInEmergencyCtrl" in data && data.ipRtuStusInEmergencyCtrl != undefined) { + this.ipRtuStusInEmergencyCtrl = data.ipRtuStusInEmergencyCtrl; + } + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + } + } + get ipRtuStusDown() { + return pb_1.Message.getFieldWithDefault(this, 1, false) as boolean; + } + set ipRtuStusDown(value: boolean) { + pb_1.Message.setField(this, 1, value); + } + get ipRtuStusInLocalCtrl() { + return pb_1.Message.getFieldWithDefault(this, 2, false) as boolean; + } + set ipRtuStusInLocalCtrl(value: boolean) { + pb_1.Message.setField(this, 2, value); + } + get ipRtuStusInCentralCtrl() { + return pb_1.Message.getFieldWithDefault(this, 3, false) as boolean; + } + set ipRtuStusInCentralCtrl(value: boolean) { + pb_1.Message.setField(this, 3, value); + } + get ipRtuStusInEmergencyCtrl() { + return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean; + } + set ipRtuStusInEmergencyCtrl(value: boolean) { + pb_1.Message.setField(this, 4, value); + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 5, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 5, value); + } + static fromObject(data: { + ipRtuStusDown?: boolean; + ipRtuStusInLocalCtrl?: boolean; + ipRtuStusInCentralCtrl?: boolean; + ipRtuStusInEmergencyCtrl?: boolean; + id?: string; + }): Rtu { + const message = new Rtu({}); + if (data.ipRtuStusDown != null) { + message.ipRtuStusDown = data.ipRtuStusDown; + } + if (data.ipRtuStusInLocalCtrl != null) { + message.ipRtuStusInLocalCtrl = data.ipRtuStusInLocalCtrl; + } + if (data.ipRtuStusInCentralCtrl != null) { + message.ipRtuStusInCentralCtrl = data.ipRtuStusInCentralCtrl; + } + if (data.ipRtuStusInEmergencyCtrl != null) { + message.ipRtuStusInEmergencyCtrl = data.ipRtuStusInEmergencyCtrl; + } + if (data.id != null) { + message.id = data.id; + } + return message; + } + toObject() { + const data: { + ipRtuStusDown?: boolean; + ipRtuStusInLocalCtrl?: boolean; + ipRtuStusInCentralCtrl?: boolean; + ipRtuStusInEmergencyCtrl?: boolean; + id?: string; + } = {}; + if (this.ipRtuStusDown != null) { + data.ipRtuStusDown = this.ipRtuStusDown; + } + if (this.ipRtuStusInLocalCtrl != null) { + data.ipRtuStusInLocalCtrl = this.ipRtuStusInLocalCtrl; + } + if (this.ipRtuStusInCentralCtrl != null) { + data.ipRtuStusInCentralCtrl = this.ipRtuStusInCentralCtrl; + } + if (this.ipRtuStusInEmergencyCtrl != null) { + data.ipRtuStusInEmergencyCtrl = this.ipRtuStusInEmergencyCtrl; + } + if (this.id != null) { + data.id = this.id; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.ipRtuStusDown != false) + writer.writeBool(1, this.ipRtuStusDown); + if (this.ipRtuStusInLocalCtrl != false) + writer.writeBool(2, this.ipRtuStusInLocalCtrl); + if (this.ipRtuStusInCentralCtrl != false) + writer.writeBool(3, this.ipRtuStusInCentralCtrl); + if (this.ipRtuStusInEmergencyCtrl != false) + writer.writeBool(4, this.ipRtuStusInEmergencyCtrl); + if (this.id.length) + writer.writeString(5, this.id); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Rtu { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Rtu(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.ipRtuStusDown = reader.readBool(); + break; + case 2: + message.ipRtuStusInLocalCtrl = reader.readBool(); + break; + case 3: + message.ipRtuStusInCentralCtrl = reader.readBool(); + break; + case 4: + message.ipRtuStusInEmergencyCtrl = reader.readBool(); + break; + case 5: + message.id = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Rtu { + return Rtu.deserialize(bytes); + } + } + export class Station extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + ipStaStusTermMode1?: boolean; + ipStaStusTermMode2?: boolean; + ipStaStusTermMode3?: boolean; + ipStaStusTermMode4?: boolean; + ipStaStusTermMode5?: boolean; + ipStaStusTermMode6?: boolean; + ipStaStusExpectTermMode1?: boolean; + ipStaStusExpectTermMode2?: boolean; + ipStaStusExpectTermMode3?: boolean; + ipStaStusExpectTermMode4?: boolean; + ipStaStusExpectTermMode5?: boolean; + ipStaStusExpectTermMode6?: boolean; + ipStaStusInCycle1?: boolean; + ipStaStusInCycle2?: boolean; + ipStaStusInCycle3?: boolean; + ipStaStusInCycle4?: boolean; + ipStaStusInCycle5?: boolean; + ipStaStusInCycle6?: boolean; + ipStaStusExpectCycle1?: boolean; + ipStaStusExpectCycle2?: boolean; + ipStaStusExpectCycle3?: boolean; + ipStaStusExpectCycle4?: boolean; + ipStaStusExpectCycle5?: boolean; + ipStaStusExpectCycle6?: boolean; + id?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("ipStaStusTermMode1" in data && data.ipStaStusTermMode1 != undefined) { + this.ipStaStusTermMode1 = data.ipStaStusTermMode1; + } + if ("ipStaStusTermMode2" in data && data.ipStaStusTermMode2 != undefined) { + this.ipStaStusTermMode2 = data.ipStaStusTermMode2; + } + if ("ipStaStusTermMode3" in data && data.ipStaStusTermMode3 != undefined) { + this.ipStaStusTermMode3 = data.ipStaStusTermMode3; + } + if ("ipStaStusTermMode4" in data && data.ipStaStusTermMode4 != undefined) { + this.ipStaStusTermMode4 = data.ipStaStusTermMode4; + } + if ("ipStaStusTermMode5" in data && data.ipStaStusTermMode5 != undefined) { + this.ipStaStusTermMode5 = data.ipStaStusTermMode5; + } + if ("ipStaStusTermMode6" in data && data.ipStaStusTermMode6 != undefined) { + this.ipStaStusTermMode6 = data.ipStaStusTermMode6; + } + if ("ipStaStusExpectTermMode1" in data && data.ipStaStusExpectTermMode1 != undefined) { + this.ipStaStusExpectTermMode1 = data.ipStaStusExpectTermMode1; + } + if ("ipStaStusExpectTermMode2" in data && data.ipStaStusExpectTermMode2 != undefined) { + this.ipStaStusExpectTermMode2 = data.ipStaStusExpectTermMode2; + } + if ("ipStaStusExpectTermMode3" in data && data.ipStaStusExpectTermMode3 != undefined) { + this.ipStaStusExpectTermMode3 = data.ipStaStusExpectTermMode3; + } + if ("ipStaStusExpectTermMode4" in data && data.ipStaStusExpectTermMode4 != undefined) { + this.ipStaStusExpectTermMode4 = data.ipStaStusExpectTermMode4; + } + if ("ipStaStusExpectTermMode5" in data && data.ipStaStusExpectTermMode5 != undefined) { + this.ipStaStusExpectTermMode5 = data.ipStaStusExpectTermMode5; + } + if ("ipStaStusExpectTermMode6" in data && data.ipStaStusExpectTermMode6 != undefined) { + this.ipStaStusExpectTermMode6 = data.ipStaStusExpectTermMode6; + } + if ("ipStaStusInCycle1" in data && data.ipStaStusInCycle1 != undefined) { + this.ipStaStusInCycle1 = data.ipStaStusInCycle1; + } + if ("ipStaStusInCycle2" in data && data.ipStaStusInCycle2 != undefined) { + this.ipStaStusInCycle2 = data.ipStaStusInCycle2; + } + if ("ipStaStusInCycle3" in data && data.ipStaStusInCycle3 != undefined) { + this.ipStaStusInCycle3 = data.ipStaStusInCycle3; + } + if ("ipStaStusInCycle4" in data && data.ipStaStusInCycle4 != undefined) { + this.ipStaStusInCycle4 = data.ipStaStusInCycle4; + } + if ("ipStaStusInCycle5" in data && data.ipStaStusInCycle5 != undefined) { + this.ipStaStusInCycle5 = data.ipStaStusInCycle5; + } + if ("ipStaStusInCycle6" in data && data.ipStaStusInCycle6 != undefined) { + this.ipStaStusInCycle6 = data.ipStaStusInCycle6; + } + if ("ipStaStusExpectCycle1" in data && data.ipStaStusExpectCycle1 != undefined) { + this.ipStaStusExpectCycle1 = data.ipStaStusExpectCycle1; + } + if ("ipStaStusExpectCycle2" in data && data.ipStaStusExpectCycle2 != undefined) { + this.ipStaStusExpectCycle2 = data.ipStaStusExpectCycle2; + } + if ("ipStaStusExpectCycle3" in data && data.ipStaStusExpectCycle3 != undefined) { + this.ipStaStusExpectCycle3 = data.ipStaStusExpectCycle3; + } + if ("ipStaStusExpectCycle4" in data && data.ipStaStusExpectCycle4 != undefined) { + this.ipStaStusExpectCycle4 = data.ipStaStusExpectCycle4; + } + if ("ipStaStusExpectCycle5" in data && data.ipStaStusExpectCycle5 != undefined) { + this.ipStaStusExpectCycle5 = data.ipStaStusExpectCycle5; + } + if ("ipStaStusExpectCycle6" in data && data.ipStaStusExpectCycle6 != undefined) { + this.ipStaStusExpectCycle6 = data.ipStaStusExpectCycle6; + } + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + } + } + get ipStaStusTermMode1() { + return pb_1.Message.getFieldWithDefault(this, 1, false) as boolean; + } + set ipStaStusTermMode1(value: boolean) { + pb_1.Message.setField(this, 1, value); + } + get ipStaStusTermMode2() { + return pb_1.Message.getFieldWithDefault(this, 2, false) as boolean; + } + set ipStaStusTermMode2(value: boolean) { + pb_1.Message.setField(this, 2, value); + } + get ipStaStusTermMode3() { + return pb_1.Message.getFieldWithDefault(this, 3, false) as boolean; + } + set ipStaStusTermMode3(value: boolean) { + pb_1.Message.setField(this, 3, value); + } + get ipStaStusTermMode4() { + return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean; + } + set ipStaStusTermMode4(value: boolean) { + pb_1.Message.setField(this, 4, value); + } + get ipStaStusTermMode5() { + return pb_1.Message.getFieldWithDefault(this, 5, false) as boolean; + } + set ipStaStusTermMode5(value: boolean) { + pb_1.Message.setField(this, 5, value); + } + get ipStaStusTermMode6() { + return pb_1.Message.getFieldWithDefault(this, 6, false) as boolean; + } + set ipStaStusTermMode6(value: boolean) { + pb_1.Message.setField(this, 6, value); + } + get ipStaStusExpectTermMode1() { + return pb_1.Message.getFieldWithDefault(this, 7, false) as boolean; + } + set ipStaStusExpectTermMode1(value: boolean) { + pb_1.Message.setField(this, 7, value); + } + get ipStaStusExpectTermMode2() { + return pb_1.Message.getFieldWithDefault(this, 8, false) as boolean; + } + set ipStaStusExpectTermMode2(value: boolean) { + pb_1.Message.setField(this, 8, value); + } + get ipStaStusExpectTermMode3() { + return pb_1.Message.getFieldWithDefault(this, 9, false) as boolean; + } + set ipStaStusExpectTermMode3(value: boolean) { + pb_1.Message.setField(this, 9, value); + } + get ipStaStusExpectTermMode4() { + return pb_1.Message.getFieldWithDefault(this, 10, false) as boolean; + } + set ipStaStusExpectTermMode4(value: boolean) { + pb_1.Message.setField(this, 10, value); + } + get ipStaStusExpectTermMode5() { + return pb_1.Message.getFieldWithDefault(this, 11, false) as boolean; + } + set ipStaStusExpectTermMode5(value: boolean) { + pb_1.Message.setField(this, 11, value); + } + get ipStaStusExpectTermMode6() { + return pb_1.Message.getFieldWithDefault(this, 12, false) as boolean; + } + set ipStaStusExpectTermMode6(value: boolean) { + pb_1.Message.setField(this, 12, value); + } + get ipStaStusInCycle1() { + return pb_1.Message.getFieldWithDefault(this, 13, false) as boolean; + } + set ipStaStusInCycle1(value: boolean) { + pb_1.Message.setField(this, 13, value); + } + get ipStaStusInCycle2() { + return pb_1.Message.getFieldWithDefault(this, 14, false) as boolean; + } + set ipStaStusInCycle2(value: boolean) { + pb_1.Message.setField(this, 14, value); + } + get ipStaStusInCycle3() { + return pb_1.Message.getFieldWithDefault(this, 15, false) as boolean; + } + set ipStaStusInCycle3(value: boolean) { + pb_1.Message.setField(this, 15, value); + } + get ipStaStusInCycle4() { + return pb_1.Message.getFieldWithDefault(this, 16, false) as boolean; + } + set ipStaStusInCycle4(value: boolean) { + pb_1.Message.setField(this, 16, value); + } + get ipStaStusInCycle5() { + return pb_1.Message.getFieldWithDefault(this, 17, false) as boolean; + } + set ipStaStusInCycle5(value: boolean) { + pb_1.Message.setField(this, 17, value); + } + get ipStaStusInCycle6() { + return pb_1.Message.getFieldWithDefault(this, 18, false) as boolean; + } + set ipStaStusInCycle6(value: boolean) { + pb_1.Message.setField(this, 18, value); + } + get ipStaStusExpectCycle1() { + return pb_1.Message.getFieldWithDefault(this, 19, false) as boolean; + } + set ipStaStusExpectCycle1(value: boolean) { + pb_1.Message.setField(this, 19, value); + } + get ipStaStusExpectCycle2() { + return pb_1.Message.getFieldWithDefault(this, 20, false) as boolean; + } + set ipStaStusExpectCycle2(value: boolean) { + pb_1.Message.setField(this, 20, value); + } + get ipStaStusExpectCycle3() { + return pb_1.Message.getFieldWithDefault(this, 21, false) as boolean; + } + set ipStaStusExpectCycle3(value: boolean) { + pb_1.Message.setField(this, 21, value); + } + get ipStaStusExpectCycle4() { + return pb_1.Message.getFieldWithDefault(this, 22, false) as boolean; + } + set ipStaStusExpectCycle4(value: boolean) { + pb_1.Message.setField(this, 22, value); + } + get ipStaStusExpectCycle5() { + return pb_1.Message.getFieldWithDefault(this, 23, false) as boolean; + } + set ipStaStusExpectCycle5(value: boolean) { + pb_1.Message.setField(this, 23, value); + } + get ipStaStusExpectCycle6() { + return pb_1.Message.getFieldWithDefault(this, 24, false) as boolean; + } + set ipStaStusExpectCycle6(value: boolean) { + pb_1.Message.setField(this, 24, value); + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 25, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 25, value); + } + static fromObject(data: { + ipStaStusTermMode1?: boolean; + ipStaStusTermMode2?: boolean; + ipStaStusTermMode3?: boolean; + ipStaStusTermMode4?: boolean; + ipStaStusTermMode5?: boolean; + ipStaStusTermMode6?: boolean; + ipStaStusExpectTermMode1?: boolean; + ipStaStusExpectTermMode2?: boolean; + ipStaStusExpectTermMode3?: boolean; + ipStaStusExpectTermMode4?: boolean; + ipStaStusExpectTermMode5?: boolean; + ipStaStusExpectTermMode6?: boolean; + ipStaStusInCycle1?: boolean; + ipStaStusInCycle2?: boolean; + ipStaStusInCycle3?: boolean; + ipStaStusInCycle4?: boolean; + ipStaStusInCycle5?: boolean; + ipStaStusInCycle6?: boolean; + ipStaStusExpectCycle1?: boolean; + ipStaStusExpectCycle2?: boolean; + ipStaStusExpectCycle3?: boolean; + ipStaStusExpectCycle4?: boolean; + ipStaStusExpectCycle5?: boolean; + ipStaStusExpectCycle6?: boolean; + id?: string; + }): Station { + const message = new Station({}); + if (data.ipStaStusTermMode1 != null) { + message.ipStaStusTermMode1 = data.ipStaStusTermMode1; + } + if (data.ipStaStusTermMode2 != null) { + message.ipStaStusTermMode2 = data.ipStaStusTermMode2; + } + if (data.ipStaStusTermMode3 != null) { + message.ipStaStusTermMode3 = data.ipStaStusTermMode3; + } + if (data.ipStaStusTermMode4 != null) { + message.ipStaStusTermMode4 = data.ipStaStusTermMode4; + } + if (data.ipStaStusTermMode5 != null) { + message.ipStaStusTermMode5 = data.ipStaStusTermMode5; + } + if (data.ipStaStusTermMode6 != null) { + message.ipStaStusTermMode6 = data.ipStaStusTermMode6; + } + if (data.ipStaStusExpectTermMode1 != null) { + message.ipStaStusExpectTermMode1 = data.ipStaStusExpectTermMode1; + } + if (data.ipStaStusExpectTermMode2 != null) { + message.ipStaStusExpectTermMode2 = data.ipStaStusExpectTermMode2; + } + if (data.ipStaStusExpectTermMode3 != null) { + message.ipStaStusExpectTermMode3 = data.ipStaStusExpectTermMode3; + } + if (data.ipStaStusExpectTermMode4 != null) { + message.ipStaStusExpectTermMode4 = data.ipStaStusExpectTermMode4; + } + if (data.ipStaStusExpectTermMode5 != null) { + message.ipStaStusExpectTermMode5 = data.ipStaStusExpectTermMode5; + } + if (data.ipStaStusExpectTermMode6 != null) { + message.ipStaStusExpectTermMode6 = data.ipStaStusExpectTermMode6; + } + if (data.ipStaStusInCycle1 != null) { + message.ipStaStusInCycle1 = data.ipStaStusInCycle1; + } + if (data.ipStaStusInCycle2 != null) { + message.ipStaStusInCycle2 = data.ipStaStusInCycle2; + } + if (data.ipStaStusInCycle3 != null) { + message.ipStaStusInCycle3 = data.ipStaStusInCycle3; + } + if (data.ipStaStusInCycle4 != null) { + message.ipStaStusInCycle4 = data.ipStaStusInCycle4; + } + if (data.ipStaStusInCycle5 != null) { + message.ipStaStusInCycle5 = data.ipStaStusInCycle5; + } + if (data.ipStaStusInCycle6 != null) { + message.ipStaStusInCycle6 = data.ipStaStusInCycle6; + } + if (data.ipStaStusExpectCycle1 != null) { + message.ipStaStusExpectCycle1 = data.ipStaStusExpectCycle1; + } + if (data.ipStaStusExpectCycle2 != null) { + message.ipStaStusExpectCycle2 = data.ipStaStusExpectCycle2; + } + if (data.ipStaStusExpectCycle3 != null) { + message.ipStaStusExpectCycle3 = data.ipStaStusExpectCycle3; + } + if (data.ipStaStusExpectCycle4 != null) { + message.ipStaStusExpectCycle4 = data.ipStaStusExpectCycle4; + } + if (data.ipStaStusExpectCycle5 != null) { + message.ipStaStusExpectCycle5 = data.ipStaStusExpectCycle5; + } + if (data.ipStaStusExpectCycle6 != null) { + message.ipStaStusExpectCycle6 = data.ipStaStusExpectCycle6; + } + if (data.id != null) { + message.id = data.id; + } + return message; + } + toObject() { + const data: { + ipStaStusTermMode1?: boolean; + ipStaStusTermMode2?: boolean; + ipStaStusTermMode3?: boolean; + ipStaStusTermMode4?: boolean; + ipStaStusTermMode5?: boolean; + ipStaStusTermMode6?: boolean; + ipStaStusExpectTermMode1?: boolean; + ipStaStusExpectTermMode2?: boolean; + ipStaStusExpectTermMode3?: boolean; + ipStaStusExpectTermMode4?: boolean; + ipStaStusExpectTermMode5?: boolean; + ipStaStusExpectTermMode6?: boolean; + ipStaStusInCycle1?: boolean; + ipStaStusInCycle2?: boolean; + ipStaStusInCycle3?: boolean; + ipStaStusInCycle4?: boolean; + ipStaStusInCycle5?: boolean; + ipStaStusInCycle6?: boolean; + ipStaStusExpectCycle1?: boolean; + ipStaStusExpectCycle2?: boolean; + ipStaStusExpectCycle3?: boolean; + ipStaStusExpectCycle4?: boolean; + ipStaStusExpectCycle5?: boolean; + ipStaStusExpectCycle6?: boolean; + id?: string; + } = {}; + if (this.ipStaStusTermMode1 != null) { + data.ipStaStusTermMode1 = this.ipStaStusTermMode1; + } + if (this.ipStaStusTermMode2 != null) { + data.ipStaStusTermMode2 = this.ipStaStusTermMode2; + } + if (this.ipStaStusTermMode3 != null) { + data.ipStaStusTermMode3 = this.ipStaStusTermMode3; + } + if (this.ipStaStusTermMode4 != null) { + data.ipStaStusTermMode4 = this.ipStaStusTermMode4; + } + if (this.ipStaStusTermMode5 != null) { + data.ipStaStusTermMode5 = this.ipStaStusTermMode5; + } + if (this.ipStaStusTermMode6 != null) { + data.ipStaStusTermMode6 = this.ipStaStusTermMode6; + } + if (this.ipStaStusExpectTermMode1 != null) { + data.ipStaStusExpectTermMode1 = this.ipStaStusExpectTermMode1; + } + if (this.ipStaStusExpectTermMode2 != null) { + data.ipStaStusExpectTermMode2 = this.ipStaStusExpectTermMode2; + } + if (this.ipStaStusExpectTermMode3 != null) { + data.ipStaStusExpectTermMode3 = this.ipStaStusExpectTermMode3; + } + if (this.ipStaStusExpectTermMode4 != null) { + data.ipStaStusExpectTermMode4 = this.ipStaStusExpectTermMode4; + } + if (this.ipStaStusExpectTermMode5 != null) { + data.ipStaStusExpectTermMode5 = this.ipStaStusExpectTermMode5; + } + if (this.ipStaStusExpectTermMode6 != null) { + data.ipStaStusExpectTermMode6 = this.ipStaStusExpectTermMode6; + } + if (this.ipStaStusInCycle1 != null) { + data.ipStaStusInCycle1 = this.ipStaStusInCycle1; + } + if (this.ipStaStusInCycle2 != null) { + data.ipStaStusInCycle2 = this.ipStaStusInCycle2; + } + if (this.ipStaStusInCycle3 != null) { + data.ipStaStusInCycle3 = this.ipStaStusInCycle3; + } + if (this.ipStaStusInCycle4 != null) { + data.ipStaStusInCycle4 = this.ipStaStusInCycle4; + } + if (this.ipStaStusInCycle5 != null) { + data.ipStaStusInCycle5 = this.ipStaStusInCycle5; + } + if (this.ipStaStusInCycle6 != null) { + data.ipStaStusInCycle6 = this.ipStaStusInCycle6; + } + if (this.ipStaStusExpectCycle1 != null) { + data.ipStaStusExpectCycle1 = this.ipStaStusExpectCycle1; + } + if (this.ipStaStusExpectCycle2 != null) { + data.ipStaStusExpectCycle2 = this.ipStaStusExpectCycle2; + } + if (this.ipStaStusExpectCycle3 != null) { + data.ipStaStusExpectCycle3 = this.ipStaStusExpectCycle3; + } + if (this.ipStaStusExpectCycle4 != null) { + data.ipStaStusExpectCycle4 = this.ipStaStusExpectCycle4; + } + if (this.ipStaStusExpectCycle5 != null) { + data.ipStaStusExpectCycle5 = this.ipStaStusExpectCycle5; + } + if (this.ipStaStusExpectCycle6 != null) { + data.ipStaStusExpectCycle6 = this.ipStaStusExpectCycle6; + } + if (this.id != null) { + data.id = this.id; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.ipStaStusTermMode1 != false) + writer.writeBool(1, this.ipStaStusTermMode1); + if (this.ipStaStusTermMode2 != false) + writer.writeBool(2, this.ipStaStusTermMode2); + if (this.ipStaStusTermMode3 != false) + writer.writeBool(3, this.ipStaStusTermMode3); + if (this.ipStaStusTermMode4 != false) + writer.writeBool(4, this.ipStaStusTermMode4); + if (this.ipStaStusTermMode5 != false) + writer.writeBool(5, this.ipStaStusTermMode5); + if (this.ipStaStusTermMode6 != false) + writer.writeBool(6, this.ipStaStusTermMode6); + if (this.ipStaStusExpectTermMode1 != false) + writer.writeBool(7, this.ipStaStusExpectTermMode1); + if (this.ipStaStusExpectTermMode2 != false) + writer.writeBool(8, this.ipStaStusExpectTermMode2); + if (this.ipStaStusExpectTermMode3 != false) + writer.writeBool(9, this.ipStaStusExpectTermMode3); + if (this.ipStaStusExpectTermMode4 != false) + writer.writeBool(10, this.ipStaStusExpectTermMode4); + if (this.ipStaStusExpectTermMode5 != false) + writer.writeBool(11, this.ipStaStusExpectTermMode5); + if (this.ipStaStusExpectTermMode6 != false) + writer.writeBool(12, this.ipStaStusExpectTermMode6); + if (this.ipStaStusInCycle1 != false) + writer.writeBool(13, this.ipStaStusInCycle1); + if (this.ipStaStusInCycle2 != false) + writer.writeBool(14, this.ipStaStusInCycle2); + if (this.ipStaStusInCycle3 != false) + writer.writeBool(15, this.ipStaStusInCycle3); + if (this.ipStaStusInCycle4 != false) + writer.writeBool(16, this.ipStaStusInCycle4); + if (this.ipStaStusInCycle5 != false) + writer.writeBool(17, this.ipStaStusInCycle5); + if (this.ipStaStusInCycle6 != false) + writer.writeBool(18, this.ipStaStusInCycle6); + if (this.ipStaStusExpectCycle1 != false) + writer.writeBool(19, this.ipStaStusExpectCycle1); + if (this.ipStaStusExpectCycle2 != false) + writer.writeBool(20, this.ipStaStusExpectCycle2); + if (this.ipStaStusExpectCycle3 != false) + writer.writeBool(21, this.ipStaStusExpectCycle3); + if (this.ipStaStusExpectCycle4 != false) + writer.writeBool(22, this.ipStaStusExpectCycle4); + if (this.ipStaStusExpectCycle5 != false) + writer.writeBool(23, this.ipStaStusExpectCycle5); + if (this.ipStaStusExpectCycle6 != false) + writer.writeBool(24, this.ipStaStusExpectCycle6); + if (this.id.length) + writer.writeString(25, this.id); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Station { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Station(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.ipStaStusTermMode1 = reader.readBool(); + break; + case 2: + message.ipStaStusTermMode2 = reader.readBool(); + break; + case 3: + message.ipStaStusTermMode3 = reader.readBool(); + break; + case 4: + message.ipStaStusTermMode4 = reader.readBool(); + break; + case 5: + message.ipStaStusTermMode5 = reader.readBool(); + break; + case 6: + message.ipStaStusTermMode6 = reader.readBool(); + break; + case 7: + message.ipStaStusExpectTermMode1 = reader.readBool(); + break; + case 8: + message.ipStaStusExpectTermMode2 = reader.readBool(); + break; + case 9: + message.ipStaStusExpectTermMode3 = reader.readBool(); + break; + case 10: + message.ipStaStusExpectTermMode4 = reader.readBool(); + break; + case 11: + message.ipStaStusExpectTermMode5 = reader.readBool(); + break; + case 12: + message.ipStaStusExpectTermMode6 = reader.readBool(); + break; + case 13: + message.ipStaStusInCycle1 = reader.readBool(); + break; + case 14: + message.ipStaStusInCycle2 = reader.readBool(); + break; + case 15: + message.ipStaStusInCycle3 = reader.readBool(); + break; + case 16: + message.ipStaStusInCycle4 = reader.readBool(); + break; + case 17: + message.ipStaStusInCycle5 = reader.readBool(); + break; + case 18: + message.ipStaStusInCycle6 = reader.readBool(); + break; + case 19: + message.ipStaStusExpectCycle1 = reader.readBool(); + break; + case 20: + message.ipStaStusExpectCycle2 = reader.readBool(); + break; + case 21: + message.ipStaStusExpectCycle3 = reader.readBool(); + break; + case 22: + message.ipStaStusExpectCycle4 = reader.readBool(); + break; + case 23: + message.ipStaStusExpectCycle5 = reader.readBool(); + break; + case 24: + message.ipStaStusExpectCycle6 = reader.readBool(); + break; + case 25: + message.id = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Station { + return Station.deserialize(bytes); + } + } + export class Signal extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + redOpen?: boolean; + redFlash?: boolean; + greenOpen?: boolean; + greenFlash?: boolean; + yellowOpen?: boolean; + yellowFlash?: boolean; + whiteOpen?: boolean; + whiteFlash?: boolean; + blueOpen?: boolean; + blueFlash?: boolean; + fleetMode?: boolean; + ctrlFleetMode?: boolean; + autoMode?: boolean; + ctrlAutoMode?: boolean; + extinguish?: boolean; + approachLock?: boolean; + protectRoute?: boolean; + autoRouteDisable?: boolean; + callon?: boolean; + yellowYellow?: boolean; + yellowGreen?: boolean; + blocked?: boolean; + lampFailure?: boolean; + id?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("redOpen" in data && data.redOpen != undefined) { + this.redOpen = data.redOpen; + } + if ("redFlash" in data && data.redFlash != undefined) { + this.redFlash = data.redFlash; + } + if ("greenOpen" in data && data.greenOpen != undefined) { + this.greenOpen = data.greenOpen; + } + if ("greenFlash" in data && data.greenFlash != undefined) { + this.greenFlash = data.greenFlash; + } + if ("yellowOpen" in data && data.yellowOpen != undefined) { + this.yellowOpen = data.yellowOpen; + } + if ("yellowFlash" in data && data.yellowFlash != undefined) { + this.yellowFlash = data.yellowFlash; + } + if ("whiteOpen" in data && data.whiteOpen != undefined) { + this.whiteOpen = data.whiteOpen; + } + if ("whiteFlash" in data && data.whiteFlash != undefined) { + this.whiteFlash = data.whiteFlash; + } + if ("blueOpen" in data && data.blueOpen != undefined) { + this.blueOpen = data.blueOpen; + } + if ("blueFlash" in data && data.blueFlash != undefined) { + this.blueFlash = data.blueFlash; + } + if ("fleetMode" in data && data.fleetMode != undefined) { + this.fleetMode = data.fleetMode; + } + if ("ctrlFleetMode" in data && data.ctrlFleetMode != undefined) { + this.ctrlFleetMode = data.ctrlFleetMode; + } + if ("autoMode" in data && data.autoMode != undefined) { + this.autoMode = data.autoMode; + } + if ("ctrlAutoMode" in data && data.ctrlAutoMode != undefined) { + this.ctrlAutoMode = data.ctrlAutoMode; + } + if ("extinguish" in data && data.extinguish != undefined) { + this.extinguish = data.extinguish; + } + if ("approachLock" in data && data.approachLock != undefined) { + this.approachLock = data.approachLock; + } + if ("protectRoute" in data && data.protectRoute != undefined) { + this.protectRoute = data.protectRoute; + } + if ("autoRouteDisable" in data && data.autoRouteDisable != undefined) { + this.autoRouteDisable = data.autoRouteDisable; + } + if ("callon" in data && data.callon != undefined) { + this.callon = data.callon; + } + if ("yellowYellow" in data && data.yellowYellow != undefined) { + this.yellowYellow = data.yellowYellow; + } + if ("yellowGreen" in data && data.yellowGreen != undefined) { + this.yellowGreen = data.yellowGreen; + } + if ("blocked" in data && data.blocked != undefined) { + this.blocked = data.blocked; + } + if ("lampFailure" in data && data.lampFailure != undefined) { + this.lampFailure = data.lampFailure; + } + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + } + } + get redOpen() { + return pb_1.Message.getFieldWithDefault(this, 1, false) as boolean; + } + set redOpen(value: boolean) { + pb_1.Message.setField(this, 1, value); + } + get redFlash() { + return pb_1.Message.getFieldWithDefault(this, 2, false) as boolean; + } + set redFlash(value: boolean) { + pb_1.Message.setField(this, 2, value); + } + get greenOpen() { + return pb_1.Message.getFieldWithDefault(this, 3, false) as boolean; + } + set greenOpen(value: boolean) { + pb_1.Message.setField(this, 3, value); + } + get greenFlash() { + return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean; + } + set greenFlash(value: boolean) { + pb_1.Message.setField(this, 4, value); + } + get yellowOpen() { + return pb_1.Message.getFieldWithDefault(this, 5, false) as boolean; + } + set yellowOpen(value: boolean) { + pb_1.Message.setField(this, 5, value); + } + get yellowFlash() { + return pb_1.Message.getFieldWithDefault(this, 6, false) as boolean; + } + set yellowFlash(value: boolean) { + pb_1.Message.setField(this, 6, value); + } + get whiteOpen() { + return pb_1.Message.getFieldWithDefault(this, 7, false) as boolean; + } + set whiteOpen(value: boolean) { + pb_1.Message.setField(this, 7, value); + } + get whiteFlash() { + return pb_1.Message.getFieldWithDefault(this, 8, false) as boolean; + } + set whiteFlash(value: boolean) { + pb_1.Message.setField(this, 8, value); + } + get blueOpen() { + return pb_1.Message.getFieldWithDefault(this, 9, false) as boolean; + } + set blueOpen(value: boolean) { + pb_1.Message.setField(this, 9, value); + } + get blueFlash() { + return pb_1.Message.getFieldWithDefault(this, 10, false) as boolean; + } + set blueFlash(value: boolean) { + pb_1.Message.setField(this, 10, value); + } + get fleetMode() { + return pb_1.Message.getFieldWithDefault(this, 11, false) as boolean; + } + set fleetMode(value: boolean) { + pb_1.Message.setField(this, 11, value); + } + get ctrlFleetMode() { + return pb_1.Message.getFieldWithDefault(this, 12, false) as boolean; + } + set ctrlFleetMode(value: boolean) { + pb_1.Message.setField(this, 12, value); + } + get autoMode() { + return pb_1.Message.getFieldWithDefault(this, 13, false) as boolean; + } + set autoMode(value: boolean) { + pb_1.Message.setField(this, 13, value); + } + get ctrlAutoMode() { + return pb_1.Message.getFieldWithDefault(this, 14, false) as boolean; + } + set ctrlAutoMode(value: boolean) { + pb_1.Message.setField(this, 14, value); + } + get extinguish() { + return pb_1.Message.getFieldWithDefault(this, 15, false) as boolean; + } + set extinguish(value: boolean) { + pb_1.Message.setField(this, 15, value); + } + get approachLock() { + return pb_1.Message.getFieldWithDefault(this, 16, false) as boolean; + } + set approachLock(value: boolean) { + pb_1.Message.setField(this, 16, value); + } + get protectRoute() { + return pb_1.Message.getFieldWithDefault(this, 17, false) as boolean; + } + set protectRoute(value: boolean) { + pb_1.Message.setField(this, 17, value); + } + get autoRouteDisable() { + return pb_1.Message.getFieldWithDefault(this, 18, false) as boolean; + } + set autoRouteDisable(value: boolean) { + pb_1.Message.setField(this, 18, value); + } + get callon() { + return pb_1.Message.getFieldWithDefault(this, 19, false) as boolean; + } + set callon(value: boolean) { + pb_1.Message.setField(this, 19, value); + } + get yellowYellow() { + return pb_1.Message.getFieldWithDefault(this, 20, false) as boolean; + } + set yellowYellow(value: boolean) { + pb_1.Message.setField(this, 20, value); + } + get yellowGreen() { + return pb_1.Message.getFieldWithDefault(this, 21, false) as boolean; + } + set yellowGreen(value: boolean) { + pb_1.Message.setField(this, 21, value); + } + get blocked() { + return pb_1.Message.getFieldWithDefault(this, 22, false) as boolean; + } + set blocked(value: boolean) { + pb_1.Message.setField(this, 22, value); + } + get lampFailure() { + return pb_1.Message.getFieldWithDefault(this, 23, false) as boolean; + } + set lampFailure(value: boolean) { + pb_1.Message.setField(this, 23, value); + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 24, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 24, value); + } + static fromObject(data: { + redOpen?: boolean; + redFlash?: boolean; + greenOpen?: boolean; + greenFlash?: boolean; + yellowOpen?: boolean; + yellowFlash?: boolean; + whiteOpen?: boolean; + whiteFlash?: boolean; + blueOpen?: boolean; + blueFlash?: boolean; + fleetMode?: boolean; + ctrlFleetMode?: boolean; + autoMode?: boolean; + ctrlAutoMode?: boolean; + extinguish?: boolean; + approachLock?: boolean; + protectRoute?: boolean; + autoRouteDisable?: boolean; + callon?: boolean; + yellowYellow?: boolean; + yellowGreen?: boolean; + blocked?: boolean; + lampFailure?: boolean; + id?: string; + }): Signal { + const message = new Signal({}); + if (data.redOpen != null) { + message.redOpen = data.redOpen; + } + if (data.redFlash != null) { + message.redFlash = data.redFlash; + } + if (data.greenOpen != null) { + message.greenOpen = data.greenOpen; + } + if (data.greenFlash != null) { + message.greenFlash = data.greenFlash; + } + if (data.yellowOpen != null) { + message.yellowOpen = data.yellowOpen; + } + if (data.yellowFlash != null) { + message.yellowFlash = data.yellowFlash; + } + if (data.whiteOpen != null) { + message.whiteOpen = data.whiteOpen; + } + if (data.whiteFlash != null) { + message.whiteFlash = data.whiteFlash; + } + if (data.blueOpen != null) { + message.blueOpen = data.blueOpen; + } + if (data.blueFlash != null) { + message.blueFlash = data.blueFlash; + } + if (data.fleetMode != null) { + message.fleetMode = data.fleetMode; + } + if (data.ctrlFleetMode != null) { + message.ctrlFleetMode = data.ctrlFleetMode; + } + if (data.autoMode != null) { + message.autoMode = data.autoMode; + } + if (data.ctrlAutoMode != null) { + message.ctrlAutoMode = data.ctrlAutoMode; + } + if (data.extinguish != null) { + message.extinguish = data.extinguish; + } + if (data.approachLock != null) { + message.approachLock = data.approachLock; + } + if (data.protectRoute != null) { + message.protectRoute = data.protectRoute; + } + if (data.autoRouteDisable != null) { + message.autoRouteDisable = data.autoRouteDisable; + } + if (data.callon != null) { + message.callon = data.callon; + } + if (data.yellowYellow != null) { + message.yellowYellow = data.yellowYellow; + } + if (data.yellowGreen != null) { + message.yellowGreen = data.yellowGreen; + } + if (data.blocked != null) { + message.blocked = data.blocked; + } + if (data.lampFailure != null) { + message.lampFailure = data.lampFailure; + } + if (data.id != null) { + message.id = data.id; + } + return message; + } + toObject() { + const data: { + redOpen?: boolean; + redFlash?: boolean; + greenOpen?: boolean; + greenFlash?: boolean; + yellowOpen?: boolean; + yellowFlash?: boolean; + whiteOpen?: boolean; + whiteFlash?: boolean; + blueOpen?: boolean; + blueFlash?: boolean; + fleetMode?: boolean; + ctrlFleetMode?: boolean; + autoMode?: boolean; + ctrlAutoMode?: boolean; + extinguish?: boolean; + approachLock?: boolean; + protectRoute?: boolean; + autoRouteDisable?: boolean; + callon?: boolean; + yellowYellow?: boolean; + yellowGreen?: boolean; + blocked?: boolean; + lampFailure?: boolean; + id?: string; + } = {}; + if (this.redOpen != null) { + data.redOpen = this.redOpen; + } + if (this.redFlash != null) { + data.redFlash = this.redFlash; + } + if (this.greenOpen != null) { + data.greenOpen = this.greenOpen; + } + if (this.greenFlash != null) { + data.greenFlash = this.greenFlash; + } + if (this.yellowOpen != null) { + data.yellowOpen = this.yellowOpen; + } + if (this.yellowFlash != null) { + data.yellowFlash = this.yellowFlash; + } + if (this.whiteOpen != null) { + data.whiteOpen = this.whiteOpen; + } + if (this.whiteFlash != null) { + data.whiteFlash = this.whiteFlash; + } + if (this.blueOpen != null) { + data.blueOpen = this.blueOpen; + } + if (this.blueFlash != null) { + data.blueFlash = this.blueFlash; + } + if (this.fleetMode != null) { + data.fleetMode = this.fleetMode; + } + if (this.ctrlFleetMode != null) { + data.ctrlFleetMode = this.ctrlFleetMode; + } + if (this.autoMode != null) { + data.autoMode = this.autoMode; + } + if (this.ctrlAutoMode != null) { + data.ctrlAutoMode = this.ctrlAutoMode; + } + if (this.extinguish != null) { + data.extinguish = this.extinguish; + } + if (this.approachLock != null) { + data.approachLock = this.approachLock; + } + if (this.protectRoute != null) { + data.protectRoute = this.protectRoute; + } + if (this.autoRouteDisable != null) { + data.autoRouteDisable = this.autoRouteDisable; + } + if (this.callon != null) { + data.callon = this.callon; + } + if (this.yellowYellow != null) { + data.yellowYellow = this.yellowYellow; + } + if (this.yellowGreen != null) { + data.yellowGreen = this.yellowGreen; + } + if (this.blocked != null) { + data.blocked = this.blocked; + } + if (this.lampFailure != null) { + data.lampFailure = this.lampFailure; + } + if (this.id != null) { + data.id = this.id; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.redOpen != false) + writer.writeBool(1, this.redOpen); + if (this.redFlash != false) + writer.writeBool(2, this.redFlash); + if (this.greenOpen != false) + writer.writeBool(3, this.greenOpen); + if (this.greenFlash != false) + writer.writeBool(4, this.greenFlash); + if (this.yellowOpen != false) + writer.writeBool(5, this.yellowOpen); + if (this.yellowFlash != false) + writer.writeBool(6, this.yellowFlash); + if (this.whiteOpen != false) + writer.writeBool(7, this.whiteOpen); + if (this.whiteFlash != false) + writer.writeBool(8, this.whiteFlash); + if (this.blueOpen != false) + writer.writeBool(9, this.blueOpen); + if (this.blueFlash != false) + writer.writeBool(10, this.blueFlash); + if (this.fleetMode != false) + writer.writeBool(11, this.fleetMode); + if (this.ctrlFleetMode != false) + writer.writeBool(12, this.ctrlFleetMode); + if (this.autoMode != false) + writer.writeBool(13, this.autoMode); + if (this.ctrlAutoMode != false) + writer.writeBool(14, this.ctrlAutoMode); + if (this.extinguish != false) + writer.writeBool(15, this.extinguish); + if (this.approachLock != false) + writer.writeBool(16, this.approachLock); + if (this.protectRoute != false) + writer.writeBool(17, this.protectRoute); + if (this.autoRouteDisable != false) + writer.writeBool(18, this.autoRouteDisable); + if (this.callon != false) + writer.writeBool(19, this.callon); + if (this.yellowYellow != false) + writer.writeBool(20, this.yellowYellow); + if (this.yellowGreen != false) + writer.writeBool(21, this.yellowGreen); + if (this.blocked != false) + writer.writeBool(22, this.blocked); + if (this.lampFailure != false) + writer.writeBool(23, this.lampFailure); + if (this.id.length) + writer.writeString(24, this.id); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Signal { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Signal(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.redOpen = reader.readBool(); + break; + case 2: + message.redFlash = reader.readBool(); + break; + case 3: + message.greenOpen = reader.readBool(); + break; + case 4: + message.greenFlash = reader.readBool(); + break; + case 5: + message.yellowOpen = reader.readBool(); + break; + case 6: + message.yellowFlash = reader.readBool(); + break; + case 7: + message.whiteOpen = reader.readBool(); + break; + case 8: + message.whiteFlash = reader.readBool(); + break; + case 9: + message.blueOpen = reader.readBool(); + break; + case 10: + message.blueFlash = reader.readBool(); + break; + case 11: + message.fleetMode = reader.readBool(); + break; + case 12: + message.ctrlFleetMode = reader.readBool(); + break; + case 13: + message.autoMode = reader.readBool(); + break; + case 14: + message.ctrlAutoMode = reader.readBool(); + break; + case 15: + message.extinguish = reader.readBool(); + break; + case 16: + message.approachLock = reader.readBool(); + break; + case 17: + message.protectRoute = reader.readBool(); + break; + case 18: + message.autoRouteDisable = reader.readBool(); + break; + case 19: + message.callon = reader.readBool(); + break; + case 20: + message.yellowYellow = reader.readBool(); + break; + case 21: + message.yellowGreen = reader.readBool(); + break; + case 22: + message.blocked = reader.readBool(); + break; + case 23: + message.lampFailure = reader.readBool(); + break; + case 24: + message.id = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Signal { + return Signal.deserialize(bytes); + } + } + export class Entry extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + dirLeft?: boolean; + dirRight?: boolean; + dirLocked?: boolean; + id?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("dirLeft" in data && data.dirLeft != undefined) { + this.dirLeft = data.dirLeft; + } + if ("dirRight" in data && data.dirRight != undefined) { + this.dirRight = data.dirRight; + } + if ("dirLocked" in data && data.dirLocked != undefined) { + this.dirLocked = data.dirLocked; + } + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + } + } + get dirLeft() { + return pb_1.Message.getFieldWithDefault(this, 1, false) as boolean; + } + set dirLeft(value: boolean) { + pb_1.Message.setField(this, 1, value); + } + get dirRight() { + return pb_1.Message.getFieldWithDefault(this, 2, false) as boolean; + } + set dirRight(value: boolean) { + pb_1.Message.setField(this, 2, value); + } + get dirLocked() { + return pb_1.Message.getFieldWithDefault(this, 3, false) as boolean; + } + set dirLocked(value: boolean) { + pb_1.Message.setField(this, 3, value); + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 4, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 4, value); + } + static fromObject(data: { + dirLeft?: boolean; + dirRight?: boolean; + dirLocked?: boolean; + id?: string; + }): Entry { + const message = new Entry({}); + if (data.dirLeft != null) { + message.dirLeft = data.dirLeft; + } + if (data.dirRight != null) { + message.dirRight = data.dirRight; + } + if (data.dirLocked != null) { + message.dirLocked = data.dirLocked; + } + if (data.id != null) { + message.id = data.id; + } + return message; + } + toObject() { + const data: { + dirLeft?: boolean; + dirRight?: boolean; + dirLocked?: boolean; + id?: string; + } = {}; + if (this.dirLeft != null) { + data.dirLeft = this.dirLeft; + } + if (this.dirRight != null) { + data.dirRight = this.dirRight; + } + if (this.dirLocked != null) { + data.dirLocked = this.dirLocked; + } + if (this.id != null) { + data.id = this.id; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.dirLeft != false) + writer.writeBool(1, this.dirLeft); + if (this.dirRight != false) + writer.writeBool(2, this.dirRight); + if (this.dirLocked != false) + writer.writeBool(3, this.dirLocked); + if (this.id.length) + writer.writeString(4, this.id); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Entry { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Entry(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.dirLeft = reader.readBool(); + break; + case 2: + message.dirRight = reader.readBool(); + break; + case 3: + message.dirLocked = reader.readBool(); + break; + case 4: + message.id = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Entry { + return Entry.deserialize(bytes); + } + } + export class Switch extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + ipSingleSwitchStusCiOccupied?: boolean; + ipSingleSwitchStusCbtcOccupied?: boolean; + ipSingleSwitchStusLocked?: boolean; + ipSingleSwitchStusFailLocked?: boolean; + ipSingleSwitchStusNormal?: boolean; + ipSingleSwitchStusReverse?: boolean; + ipSingleSwitchStusBlocked1?: boolean; + ipSingleSwitchStusJammed?: boolean; + ipSingleSwitchStusExpectLock?: boolean; + ipSingleSwitchStusExpectUnlock?: boolean; + ipSingleSwitchStusExpectNormal?: boolean; + ipSingleSwitchStusExpectReverse?: boolean; + ipSingleSwitchStusExpectBlock?: boolean; + ipSingleSwitchStusExpectUnblock?: boolean; + ipSingleSwitchStusInRoute?: boolean; + ipSingleSwitchStusManualMode?: boolean; + ipSingleSwitchStusCut?: boolean; + ipSingleSwitchStusAtcInvalid?: boolean; + ipSingleSwitchStusOverlap?: boolean; + ipSingleSwitchStusTsrCbtcMain?: boolean; + ipSingleSwitchStusTsrCbtcNormal?: boolean; + ipSingleSwitchStusTsrCbtcReverse?: boolean; + ipSingleSwitchStusTsrBmMain?: boolean; + ipSingleSwitchStusTsrBmNormal?: boolean; + ipSingleSwitchStusTsrBmReverse?: boolean; + ipSingleSwitchStusBlocked2?: boolean; + ipSingleSwitchStusLostIndication?: boolean; + id?: string; + speedLimit?: number; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("ipSingleSwitchStusCiOccupied" in data && data.ipSingleSwitchStusCiOccupied != undefined) { + this.ipSingleSwitchStusCiOccupied = data.ipSingleSwitchStusCiOccupied; + } + if ("ipSingleSwitchStusCbtcOccupied" in data && data.ipSingleSwitchStusCbtcOccupied != undefined) { + this.ipSingleSwitchStusCbtcOccupied = data.ipSingleSwitchStusCbtcOccupied; + } + if ("ipSingleSwitchStusLocked" in data && data.ipSingleSwitchStusLocked != undefined) { + this.ipSingleSwitchStusLocked = data.ipSingleSwitchStusLocked; + } + if ("ipSingleSwitchStusFailLocked" in data && data.ipSingleSwitchStusFailLocked != undefined) { + this.ipSingleSwitchStusFailLocked = data.ipSingleSwitchStusFailLocked; + } + if ("ipSingleSwitchStusNormal" in data && data.ipSingleSwitchStusNormal != undefined) { + this.ipSingleSwitchStusNormal = data.ipSingleSwitchStusNormal; + } + if ("ipSingleSwitchStusReverse" in data && data.ipSingleSwitchStusReverse != undefined) { + this.ipSingleSwitchStusReverse = data.ipSingleSwitchStusReverse; + } + if ("ipSingleSwitchStusBlocked1" in data && data.ipSingleSwitchStusBlocked1 != undefined) { + this.ipSingleSwitchStusBlocked1 = data.ipSingleSwitchStusBlocked1; + } + if ("ipSingleSwitchStusJammed" in data && data.ipSingleSwitchStusJammed != undefined) { + this.ipSingleSwitchStusJammed = data.ipSingleSwitchStusJammed; + } + if ("ipSingleSwitchStusExpectLock" in data && data.ipSingleSwitchStusExpectLock != undefined) { + this.ipSingleSwitchStusExpectLock = data.ipSingleSwitchStusExpectLock; + } + if ("ipSingleSwitchStusExpectUnlock" in data && data.ipSingleSwitchStusExpectUnlock != undefined) { + this.ipSingleSwitchStusExpectUnlock = data.ipSingleSwitchStusExpectUnlock; + } + if ("ipSingleSwitchStusExpectNormal" in data && data.ipSingleSwitchStusExpectNormal != undefined) { + this.ipSingleSwitchStusExpectNormal = data.ipSingleSwitchStusExpectNormal; + } + if ("ipSingleSwitchStusExpectReverse" in data && data.ipSingleSwitchStusExpectReverse != undefined) { + this.ipSingleSwitchStusExpectReverse = data.ipSingleSwitchStusExpectReverse; + } + if ("ipSingleSwitchStusExpectBlock" in data && data.ipSingleSwitchStusExpectBlock != undefined) { + this.ipSingleSwitchStusExpectBlock = data.ipSingleSwitchStusExpectBlock; + } + if ("ipSingleSwitchStusExpectUnblock" in data && data.ipSingleSwitchStusExpectUnblock != undefined) { + this.ipSingleSwitchStusExpectUnblock = data.ipSingleSwitchStusExpectUnblock; + } + if ("ipSingleSwitchStusInRoute" in data && data.ipSingleSwitchStusInRoute != undefined) { + this.ipSingleSwitchStusInRoute = data.ipSingleSwitchStusInRoute; + } + if ("ipSingleSwitchStusManualMode" in data && data.ipSingleSwitchStusManualMode != undefined) { + this.ipSingleSwitchStusManualMode = data.ipSingleSwitchStusManualMode; + } + if ("ipSingleSwitchStusCut" in data && data.ipSingleSwitchStusCut != undefined) { + this.ipSingleSwitchStusCut = data.ipSingleSwitchStusCut; + } + if ("ipSingleSwitchStusAtcInvalid" in data && data.ipSingleSwitchStusAtcInvalid != undefined) { + this.ipSingleSwitchStusAtcInvalid = data.ipSingleSwitchStusAtcInvalid; + } + if ("ipSingleSwitchStusOverlap" in data && data.ipSingleSwitchStusOverlap != undefined) { + this.ipSingleSwitchStusOverlap = data.ipSingleSwitchStusOverlap; + } + if ("ipSingleSwitchStusTsrCbtcMain" in data && data.ipSingleSwitchStusTsrCbtcMain != undefined) { + this.ipSingleSwitchStusTsrCbtcMain = data.ipSingleSwitchStusTsrCbtcMain; + } + if ("ipSingleSwitchStusTsrCbtcNormal" in data && data.ipSingleSwitchStusTsrCbtcNormal != undefined) { + this.ipSingleSwitchStusTsrCbtcNormal = data.ipSingleSwitchStusTsrCbtcNormal; + } + if ("ipSingleSwitchStusTsrCbtcReverse" in data && data.ipSingleSwitchStusTsrCbtcReverse != undefined) { + this.ipSingleSwitchStusTsrCbtcReverse = data.ipSingleSwitchStusTsrCbtcReverse; + } + if ("ipSingleSwitchStusTsrBmMain" in data && data.ipSingleSwitchStusTsrBmMain != undefined) { + this.ipSingleSwitchStusTsrBmMain = data.ipSingleSwitchStusTsrBmMain; + } + if ("ipSingleSwitchStusTsrBmNormal" in data && data.ipSingleSwitchStusTsrBmNormal != undefined) { + this.ipSingleSwitchStusTsrBmNormal = data.ipSingleSwitchStusTsrBmNormal; + } + if ("ipSingleSwitchStusTsrBmReverse" in data && data.ipSingleSwitchStusTsrBmReverse != undefined) { + this.ipSingleSwitchStusTsrBmReverse = data.ipSingleSwitchStusTsrBmReverse; + } + if ("ipSingleSwitchStusBlocked2" in data && data.ipSingleSwitchStusBlocked2 != undefined) { + this.ipSingleSwitchStusBlocked2 = data.ipSingleSwitchStusBlocked2; + } + if ("ipSingleSwitchStusLostIndication" in data && data.ipSingleSwitchStusLostIndication != undefined) { + this.ipSingleSwitchStusLostIndication = data.ipSingleSwitchStusLostIndication; + } + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + if ("speedLimit" in data && data.speedLimit != undefined) { + this.speedLimit = data.speedLimit; + } + } + } + get ipSingleSwitchStusCiOccupied() { + return pb_1.Message.getFieldWithDefault(this, 1, false) as boolean; + } + set ipSingleSwitchStusCiOccupied(value: boolean) { + pb_1.Message.setField(this, 1, value); + } + get ipSingleSwitchStusCbtcOccupied() { + return pb_1.Message.getFieldWithDefault(this, 2, false) as boolean; + } + set ipSingleSwitchStusCbtcOccupied(value: boolean) { + pb_1.Message.setField(this, 2, value); + } + get ipSingleSwitchStusLocked() { + return pb_1.Message.getFieldWithDefault(this, 3, false) as boolean; + } + set ipSingleSwitchStusLocked(value: boolean) { + pb_1.Message.setField(this, 3, value); + } + get ipSingleSwitchStusFailLocked() { + return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean; + } + set ipSingleSwitchStusFailLocked(value: boolean) { + pb_1.Message.setField(this, 4, value); + } + get ipSingleSwitchStusNormal() { + return pb_1.Message.getFieldWithDefault(this, 5, false) as boolean; + } + set ipSingleSwitchStusNormal(value: boolean) { + pb_1.Message.setField(this, 5, value); + } + get ipSingleSwitchStusReverse() { + return pb_1.Message.getFieldWithDefault(this, 6, false) as boolean; + } + set ipSingleSwitchStusReverse(value: boolean) { + pb_1.Message.setField(this, 6, value); + } + get ipSingleSwitchStusBlocked1() { + return pb_1.Message.getFieldWithDefault(this, 7, false) as boolean; + } + set ipSingleSwitchStusBlocked1(value: boolean) { + pb_1.Message.setField(this, 7, value); + } + get ipSingleSwitchStusJammed() { + return pb_1.Message.getFieldWithDefault(this, 8, false) as boolean; + } + set ipSingleSwitchStusJammed(value: boolean) { + pb_1.Message.setField(this, 8, value); + } + get ipSingleSwitchStusExpectLock() { + return pb_1.Message.getFieldWithDefault(this, 9, false) as boolean; + } + set ipSingleSwitchStusExpectLock(value: boolean) { + pb_1.Message.setField(this, 9, value); + } + get ipSingleSwitchStusExpectUnlock() { + return pb_1.Message.getFieldWithDefault(this, 10, false) as boolean; + } + set ipSingleSwitchStusExpectUnlock(value: boolean) { + pb_1.Message.setField(this, 10, value); + } + get ipSingleSwitchStusExpectNormal() { + return pb_1.Message.getFieldWithDefault(this, 11, false) as boolean; + } + set ipSingleSwitchStusExpectNormal(value: boolean) { + pb_1.Message.setField(this, 11, value); + } + get ipSingleSwitchStusExpectReverse() { + return pb_1.Message.getFieldWithDefault(this, 12, false) as boolean; + } + set ipSingleSwitchStusExpectReverse(value: boolean) { + pb_1.Message.setField(this, 12, value); + } + get ipSingleSwitchStusExpectBlock() { + return pb_1.Message.getFieldWithDefault(this, 13, false) as boolean; + } + set ipSingleSwitchStusExpectBlock(value: boolean) { + pb_1.Message.setField(this, 13, value); + } + get ipSingleSwitchStusExpectUnblock() { + return pb_1.Message.getFieldWithDefault(this, 14, false) as boolean; + } + set ipSingleSwitchStusExpectUnblock(value: boolean) { + pb_1.Message.setField(this, 14, value); + } + get ipSingleSwitchStusInRoute() { + return pb_1.Message.getFieldWithDefault(this, 15, false) as boolean; + } + set ipSingleSwitchStusInRoute(value: boolean) { + pb_1.Message.setField(this, 15, value); + } + get ipSingleSwitchStusManualMode() { + return pb_1.Message.getFieldWithDefault(this, 16, false) as boolean; + } + set ipSingleSwitchStusManualMode(value: boolean) { + pb_1.Message.setField(this, 16, value); + } + get ipSingleSwitchStusCut() { + return pb_1.Message.getFieldWithDefault(this, 17, false) as boolean; + } + set ipSingleSwitchStusCut(value: boolean) { + pb_1.Message.setField(this, 17, value); + } + get ipSingleSwitchStusAtcInvalid() { + return pb_1.Message.getFieldWithDefault(this, 18, false) as boolean; + } + set ipSingleSwitchStusAtcInvalid(value: boolean) { + pb_1.Message.setField(this, 18, value); + } + get ipSingleSwitchStusOverlap() { + return pb_1.Message.getFieldWithDefault(this, 19, false) as boolean; + } + set ipSingleSwitchStusOverlap(value: boolean) { + pb_1.Message.setField(this, 19, value); + } + get ipSingleSwitchStusTsrCbtcMain() { + return pb_1.Message.getFieldWithDefault(this, 20, false) as boolean; + } + set ipSingleSwitchStusTsrCbtcMain(value: boolean) { + pb_1.Message.setField(this, 20, value); + } + get ipSingleSwitchStusTsrCbtcNormal() { + return pb_1.Message.getFieldWithDefault(this, 21, false) as boolean; + } + set ipSingleSwitchStusTsrCbtcNormal(value: boolean) { + pb_1.Message.setField(this, 21, value); + } + get ipSingleSwitchStusTsrCbtcReverse() { + return pb_1.Message.getFieldWithDefault(this, 22, false) as boolean; + } + set ipSingleSwitchStusTsrCbtcReverse(value: boolean) { + pb_1.Message.setField(this, 22, value); + } + get ipSingleSwitchStusTsrBmMain() { + return pb_1.Message.getFieldWithDefault(this, 23, false) as boolean; + } + set ipSingleSwitchStusTsrBmMain(value: boolean) { + pb_1.Message.setField(this, 23, value); + } + get ipSingleSwitchStusTsrBmNormal() { + return pb_1.Message.getFieldWithDefault(this, 24, false) as boolean; + } + set ipSingleSwitchStusTsrBmNormal(value: boolean) { + pb_1.Message.setField(this, 24, value); + } + get ipSingleSwitchStusTsrBmReverse() { + return pb_1.Message.getFieldWithDefault(this, 25, false) as boolean; + } + set ipSingleSwitchStusTsrBmReverse(value: boolean) { + pb_1.Message.setField(this, 25, value); + } + get ipSingleSwitchStusBlocked2() { + return pb_1.Message.getFieldWithDefault(this, 26, false) as boolean; + } + set ipSingleSwitchStusBlocked2(value: boolean) { + pb_1.Message.setField(this, 26, value); + } + get ipSingleSwitchStusLostIndication() { + return pb_1.Message.getFieldWithDefault(this, 27, false) as boolean; + } + set ipSingleSwitchStusLostIndication(value: boolean) { + pb_1.Message.setField(this, 27, value); + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 28, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 28, value); + } + get speedLimit() { + return pb_1.Message.getFieldWithDefault(this, 29, 0) as number; + } + set speedLimit(value: number) { + pb_1.Message.setField(this, 29, value); + } + static fromObject(data: { + ipSingleSwitchStusCiOccupied?: boolean; + ipSingleSwitchStusCbtcOccupied?: boolean; + ipSingleSwitchStusLocked?: boolean; + ipSingleSwitchStusFailLocked?: boolean; + ipSingleSwitchStusNormal?: boolean; + ipSingleSwitchStusReverse?: boolean; + ipSingleSwitchStusBlocked1?: boolean; + ipSingleSwitchStusJammed?: boolean; + ipSingleSwitchStusExpectLock?: boolean; + ipSingleSwitchStusExpectUnlock?: boolean; + ipSingleSwitchStusExpectNormal?: boolean; + ipSingleSwitchStusExpectReverse?: boolean; + ipSingleSwitchStusExpectBlock?: boolean; + ipSingleSwitchStusExpectUnblock?: boolean; + ipSingleSwitchStusInRoute?: boolean; + ipSingleSwitchStusManualMode?: boolean; + ipSingleSwitchStusCut?: boolean; + ipSingleSwitchStusAtcInvalid?: boolean; + ipSingleSwitchStusOverlap?: boolean; + ipSingleSwitchStusTsrCbtcMain?: boolean; + ipSingleSwitchStusTsrCbtcNormal?: boolean; + ipSingleSwitchStusTsrCbtcReverse?: boolean; + ipSingleSwitchStusTsrBmMain?: boolean; + ipSingleSwitchStusTsrBmNormal?: boolean; + ipSingleSwitchStusTsrBmReverse?: boolean; + ipSingleSwitchStusBlocked2?: boolean; + ipSingleSwitchStusLostIndication?: boolean; + id?: string; + speedLimit?: number; + }): Switch { + const message = new Switch({}); + if (data.ipSingleSwitchStusCiOccupied != null) { + message.ipSingleSwitchStusCiOccupied = data.ipSingleSwitchStusCiOccupied; + } + if (data.ipSingleSwitchStusCbtcOccupied != null) { + message.ipSingleSwitchStusCbtcOccupied = data.ipSingleSwitchStusCbtcOccupied; + } + if (data.ipSingleSwitchStusLocked != null) { + message.ipSingleSwitchStusLocked = data.ipSingleSwitchStusLocked; + } + if (data.ipSingleSwitchStusFailLocked != null) { + message.ipSingleSwitchStusFailLocked = data.ipSingleSwitchStusFailLocked; + } + if (data.ipSingleSwitchStusNormal != null) { + message.ipSingleSwitchStusNormal = data.ipSingleSwitchStusNormal; + } + if (data.ipSingleSwitchStusReverse != null) { + message.ipSingleSwitchStusReverse = data.ipSingleSwitchStusReverse; + } + if (data.ipSingleSwitchStusBlocked1 != null) { + message.ipSingleSwitchStusBlocked1 = data.ipSingleSwitchStusBlocked1; + } + if (data.ipSingleSwitchStusJammed != null) { + message.ipSingleSwitchStusJammed = data.ipSingleSwitchStusJammed; + } + if (data.ipSingleSwitchStusExpectLock != null) { + message.ipSingleSwitchStusExpectLock = data.ipSingleSwitchStusExpectLock; + } + if (data.ipSingleSwitchStusExpectUnlock != null) { + message.ipSingleSwitchStusExpectUnlock = data.ipSingleSwitchStusExpectUnlock; + } + if (data.ipSingleSwitchStusExpectNormal != null) { + message.ipSingleSwitchStusExpectNormal = data.ipSingleSwitchStusExpectNormal; + } + if (data.ipSingleSwitchStusExpectReverse != null) { + message.ipSingleSwitchStusExpectReverse = data.ipSingleSwitchStusExpectReverse; + } + if (data.ipSingleSwitchStusExpectBlock != null) { + message.ipSingleSwitchStusExpectBlock = data.ipSingleSwitchStusExpectBlock; + } + if (data.ipSingleSwitchStusExpectUnblock != null) { + message.ipSingleSwitchStusExpectUnblock = data.ipSingleSwitchStusExpectUnblock; + } + if (data.ipSingleSwitchStusInRoute != null) { + message.ipSingleSwitchStusInRoute = data.ipSingleSwitchStusInRoute; + } + if (data.ipSingleSwitchStusManualMode != null) { + message.ipSingleSwitchStusManualMode = data.ipSingleSwitchStusManualMode; + } + if (data.ipSingleSwitchStusCut != null) { + message.ipSingleSwitchStusCut = data.ipSingleSwitchStusCut; + } + if (data.ipSingleSwitchStusAtcInvalid != null) { + message.ipSingleSwitchStusAtcInvalid = data.ipSingleSwitchStusAtcInvalid; + } + if (data.ipSingleSwitchStusOverlap != null) { + message.ipSingleSwitchStusOverlap = data.ipSingleSwitchStusOverlap; + } + if (data.ipSingleSwitchStusTsrCbtcMain != null) { + message.ipSingleSwitchStusTsrCbtcMain = data.ipSingleSwitchStusTsrCbtcMain; + } + if (data.ipSingleSwitchStusTsrCbtcNormal != null) { + message.ipSingleSwitchStusTsrCbtcNormal = data.ipSingleSwitchStusTsrCbtcNormal; + } + if (data.ipSingleSwitchStusTsrCbtcReverse != null) { + message.ipSingleSwitchStusTsrCbtcReverse = data.ipSingleSwitchStusTsrCbtcReverse; + } + if (data.ipSingleSwitchStusTsrBmMain != null) { + message.ipSingleSwitchStusTsrBmMain = data.ipSingleSwitchStusTsrBmMain; + } + if (data.ipSingleSwitchStusTsrBmNormal != null) { + message.ipSingleSwitchStusTsrBmNormal = data.ipSingleSwitchStusTsrBmNormal; + } + if (data.ipSingleSwitchStusTsrBmReverse != null) { + message.ipSingleSwitchStusTsrBmReverse = data.ipSingleSwitchStusTsrBmReverse; + } + if (data.ipSingleSwitchStusBlocked2 != null) { + message.ipSingleSwitchStusBlocked2 = data.ipSingleSwitchStusBlocked2; + } + if (data.ipSingleSwitchStusLostIndication != null) { + message.ipSingleSwitchStusLostIndication = data.ipSingleSwitchStusLostIndication; + } + if (data.id != null) { + message.id = data.id; + } + if (data.speedLimit != null) { + message.speedLimit = data.speedLimit; + } + return message; + } + toObject() { + const data: { + ipSingleSwitchStusCiOccupied?: boolean; + ipSingleSwitchStusCbtcOccupied?: boolean; + ipSingleSwitchStusLocked?: boolean; + ipSingleSwitchStusFailLocked?: boolean; + ipSingleSwitchStusNormal?: boolean; + ipSingleSwitchStusReverse?: boolean; + ipSingleSwitchStusBlocked1?: boolean; + ipSingleSwitchStusJammed?: boolean; + ipSingleSwitchStusExpectLock?: boolean; + ipSingleSwitchStusExpectUnlock?: boolean; + ipSingleSwitchStusExpectNormal?: boolean; + ipSingleSwitchStusExpectReverse?: boolean; + ipSingleSwitchStusExpectBlock?: boolean; + ipSingleSwitchStusExpectUnblock?: boolean; + ipSingleSwitchStusInRoute?: boolean; + ipSingleSwitchStusManualMode?: boolean; + ipSingleSwitchStusCut?: boolean; + ipSingleSwitchStusAtcInvalid?: boolean; + ipSingleSwitchStusOverlap?: boolean; + ipSingleSwitchStusTsrCbtcMain?: boolean; + ipSingleSwitchStusTsrCbtcNormal?: boolean; + ipSingleSwitchStusTsrCbtcReverse?: boolean; + ipSingleSwitchStusTsrBmMain?: boolean; + ipSingleSwitchStusTsrBmNormal?: boolean; + ipSingleSwitchStusTsrBmReverse?: boolean; + ipSingleSwitchStusBlocked2?: boolean; + ipSingleSwitchStusLostIndication?: boolean; + id?: string; + speedLimit?: number; + } = {}; + if (this.ipSingleSwitchStusCiOccupied != null) { + data.ipSingleSwitchStusCiOccupied = this.ipSingleSwitchStusCiOccupied; + } + if (this.ipSingleSwitchStusCbtcOccupied != null) { + data.ipSingleSwitchStusCbtcOccupied = this.ipSingleSwitchStusCbtcOccupied; + } + if (this.ipSingleSwitchStusLocked != null) { + data.ipSingleSwitchStusLocked = this.ipSingleSwitchStusLocked; + } + if (this.ipSingleSwitchStusFailLocked != null) { + data.ipSingleSwitchStusFailLocked = this.ipSingleSwitchStusFailLocked; + } + if (this.ipSingleSwitchStusNormal != null) { + data.ipSingleSwitchStusNormal = this.ipSingleSwitchStusNormal; + } + if (this.ipSingleSwitchStusReverse != null) { + data.ipSingleSwitchStusReverse = this.ipSingleSwitchStusReverse; + } + if (this.ipSingleSwitchStusBlocked1 != null) { + data.ipSingleSwitchStusBlocked1 = this.ipSingleSwitchStusBlocked1; + } + if (this.ipSingleSwitchStusJammed != null) { + data.ipSingleSwitchStusJammed = this.ipSingleSwitchStusJammed; + } + if (this.ipSingleSwitchStusExpectLock != null) { + data.ipSingleSwitchStusExpectLock = this.ipSingleSwitchStusExpectLock; + } + if (this.ipSingleSwitchStusExpectUnlock != null) { + data.ipSingleSwitchStusExpectUnlock = this.ipSingleSwitchStusExpectUnlock; + } + if (this.ipSingleSwitchStusExpectNormal != null) { + data.ipSingleSwitchStusExpectNormal = this.ipSingleSwitchStusExpectNormal; + } + if (this.ipSingleSwitchStusExpectReverse != null) { + data.ipSingleSwitchStusExpectReverse = this.ipSingleSwitchStusExpectReverse; + } + if (this.ipSingleSwitchStusExpectBlock != null) { + data.ipSingleSwitchStusExpectBlock = this.ipSingleSwitchStusExpectBlock; + } + if (this.ipSingleSwitchStusExpectUnblock != null) { + data.ipSingleSwitchStusExpectUnblock = this.ipSingleSwitchStusExpectUnblock; + } + if (this.ipSingleSwitchStusInRoute != null) { + data.ipSingleSwitchStusInRoute = this.ipSingleSwitchStusInRoute; + } + if (this.ipSingleSwitchStusManualMode != null) { + data.ipSingleSwitchStusManualMode = this.ipSingleSwitchStusManualMode; + } + if (this.ipSingleSwitchStusCut != null) { + data.ipSingleSwitchStusCut = this.ipSingleSwitchStusCut; + } + if (this.ipSingleSwitchStusAtcInvalid != null) { + data.ipSingleSwitchStusAtcInvalid = this.ipSingleSwitchStusAtcInvalid; + } + if (this.ipSingleSwitchStusOverlap != null) { + data.ipSingleSwitchStusOverlap = this.ipSingleSwitchStusOverlap; + } + if (this.ipSingleSwitchStusTsrCbtcMain != null) { + data.ipSingleSwitchStusTsrCbtcMain = this.ipSingleSwitchStusTsrCbtcMain; + } + if (this.ipSingleSwitchStusTsrCbtcNormal != null) { + data.ipSingleSwitchStusTsrCbtcNormal = this.ipSingleSwitchStusTsrCbtcNormal; + } + if (this.ipSingleSwitchStusTsrCbtcReverse != null) { + data.ipSingleSwitchStusTsrCbtcReverse = this.ipSingleSwitchStusTsrCbtcReverse; + } + if (this.ipSingleSwitchStusTsrBmMain != null) { + data.ipSingleSwitchStusTsrBmMain = this.ipSingleSwitchStusTsrBmMain; + } + if (this.ipSingleSwitchStusTsrBmNormal != null) { + data.ipSingleSwitchStusTsrBmNormal = this.ipSingleSwitchStusTsrBmNormal; + } + if (this.ipSingleSwitchStusTsrBmReverse != null) { + data.ipSingleSwitchStusTsrBmReverse = this.ipSingleSwitchStusTsrBmReverse; + } + if (this.ipSingleSwitchStusBlocked2 != null) { + data.ipSingleSwitchStusBlocked2 = this.ipSingleSwitchStusBlocked2; + } + if (this.ipSingleSwitchStusLostIndication != null) { + data.ipSingleSwitchStusLostIndication = this.ipSingleSwitchStusLostIndication; + } + if (this.id != null) { + data.id = this.id; + } + if (this.speedLimit != null) { + data.speedLimit = this.speedLimit; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.ipSingleSwitchStusCiOccupied != false) + writer.writeBool(1, this.ipSingleSwitchStusCiOccupied); + if (this.ipSingleSwitchStusCbtcOccupied != false) + writer.writeBool(2, this.ipSingleSwitchStusCbtcOccupied); + if (this.ipSingleSwitchStusLocked != false) + writer.writeBool(3, this.ipSingleSwitchStusLocked); + if (this.ipSingleSwitchStusFailLocked != false) + writer.writeBool(4, this.ipSingleSwitchStusFailLocked); + if (this.ipSingleSwitchStusNormal != false) + writer.writeBool(5, this.ipSingleSwitchStusNormal); + if (this.ipSingleSwitchStusReverse != false) + writer.writeBool(6, this.ipSingleSwitchStusReverse); + if (this.ipSingleSwitchStusBlocked1 != false) + writer.writeBool(7, this.ipSingleSwitchStusBlocked1); + if (this.ipSingleSwitchStusJammed != false) + writer.writeBool(8, this.ipSingleSwitchStusJammed); + if (this.ipSingleSwitchStusExpectLock != false) + writer.writeBool(9, this.ipSingleSwitchStusExpectLock); + if (this.ipSingleSwitchStusExpectUnlock != false) + writer.writeBool(10, this.ipSingleSwitchStusExpectUnlock); + if (this.ipSingleSwitchStusExpectNormal != false) + writer.writeBool(11, this.ipSingleSwitchStusExpectNormal); + if (this.ipSingleSwitchStusExpectReverse != false) + writer.writeBool(12, this.ipSingleSwitchStusExpectReverse); + if (this.ipSingleSwitchStusExpectBlock != false) + writer.writeBool(13, this.ipSingleSwitchStusExpectBlock); + if (this.ipSingleSwitchStusExpectUnblock != false) + writer.writeBool(14, this.ipSingleSwitchStusExpectUnblock); + if (this.ipSingleSwitchStusInRoute != false) + writer.writeBool(15, this.ipSingleSwitchStusInRoute); + if (this.ipSingleSwitchStusManualMode != false) + writer.writeBool(16, this.ipSingleSwitchStusManualMode); + if (this.ipSingleSwitchStusCut != false) + writer.writeBool(17, this.ipSingleSwitchStusCut); + if (this.ipSingleSwitchStusAtcInvalid != false) + writer.writeBool(18, this.ipSingleSwitchStusAtcInvalid); + if (this.ipSingleSwitchStusOverlap != false) + writer.writeBool(19, this.ipSingleSwitchStusOverlap); + if (this.ipSingleSwitchStusTsrCbtcMain != false) + writer.writeBool(20, this.ipSingleSwitchStusTsrCbtcMain); + if (this.ipSingleSwitchStusTsrCbtcNormal != false) + writer.writeBool(21, this.ipSingleSwitchStusTsrCbtcNormal); + if (this.ipSingleSwitchStusTsrCbtcReverse != false) + writer.writeBool(22, this.ipSingleSwitchStusTsrCbtcReverse); + if (this.ipSingleSwitchStusTsrBmMain != false) + writer.writeBool(23, this.ipSingleSwitchStusTsrBmMain); + if (this.ipSingleSwitchStusTsrBmNormal != false) + writer.writeBool(24, this.ipSingleSwitchStusTsrBmNormal); + if (this.ipSingleSwitchStusTsrBmReverse != false) + writer.writeBool(25, this.ipSingleSwitchStusTsrBmReverse); + if (this.ipSingleSwitchStusBlocked2 != false) + writer.writeBool(26, this.ipSingleSwitchStusBlocked2); + if (this.ipSingleSwitchStusLostIndication != false) + writer.writeBool(27, this.ipSingleSwitchStusLostIndication); + if (this.id.length) + writer.writeString(28, this.id); + if (this.speedLimit != 0) + writer.writeInt32(29, this.speedLimit); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Switch { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Switch(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.ipSingleSwitchStusCiOccupied = reader.readBool(); + break; + case 2: + message.ipSingleSwitchStusCbtcOccupied = reader.readBool(); + break; + case 3: + message.ipSingleSwitchStusLocked = reader.readBool(); + break; + case 4: + message.ipSingleSwitchStusFailLocked = reader.readBool(); + break; + case 5: + message.ipSingleSwitchStusNormal = reader.readBool(); + break; + case 6: + message.ipSingleSwitchStusReverse = reader.readBool(); + break; + case 7: + message.ipSingleSwitchStusBlocked1 = reader.readBool(); + break; + case 8: + message.ipSingleSwitchStusJammed = reader.readBool(); + break; + case 9: + message.ipSingleSwitchStusExpectLock = reader.readBool(); + break; + case 10: + message.ipSingleSwitchStusExpectUnlock = reader.readBool(); + break; + case 11: + message.ipSingleSwitchStusExpectNormal = reader.readBool(); + break; + case 12: + message.ipSingleSwitchStusExpectReverse = reader.readBool(); + break; + case 13: + message.ipSingleSwitchStusExpectBlock = reader.readBool(); + break; + case 14: + message.ipSingleSwitchStusExpectUnblock = reader.readBool(); + break; + case 15: + message.ipSingleSwitchStusInRoute = reader.readBool(); + break; + case 16: + message.ipSingleSwitchStusManualMode = reader.readBool(); + break; + case 17: + message.ipSingleSwitchStusCut = reader.readBool(); + break; + case 18: + message.ipSingleSwitchStusAtcInvalid = reader.readBool(); + break; + case 19: + message.ipSingleSwitchStusOverlap = reader.readBool(); + break; + case 20: + message.ipSingleSwitchStusTsrCbtcMain = reader.readBool(); + break; + case 21: + message.ipSingleSwitchStusTsrCbtcNormal = reader.readBool(); + break; + case 22: + message.ipSingleSwitchStusTsrCbtcReverse = reader.readBool(); + break; + case 23: + message.ipSingleSwitchStusTsrBmMain = reader.readBool(); + break; + case 24: + message.ipSingleSwitchStusTsrBmNormal = reader.readBool(); + break; + case 25: + message.ipSingleSwitchStusTsrBmReverse = reader.readBool(); + break; + case 26: + message.ipSingleSwitchStusBlocked2 = reader.readBool(); + break; + case 27: + message.ipSingleSwitchStusLostIndication = reader.readBool(); + break; + case 28: + message.id = reader.readString(); + break; + case 29: + message.speedLimit = reader.readInt32(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Switch { + return Switch.deserialize(bytes); + } + } + export class Track extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + ciOccupied?: boolean; + cbtcOccupied?: boolean; + locked?: boolean; + failLocked?: boolean; + expectLock?: boolean; + expectUnlock?: boolean; + inRoute?: boolean; + cut?: boolean; + atcInvalid?: boolean; + overlap?: boolean; + blocked?: boolean; + id?: string; + speedLimit?: number; + limitType?: Track.LimitType; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("ciOccupied" in data && data.ciOccupied != undefined) { + this.ciOccupied = data.ciOccupied; + } + if ("cbtcOccupied" in data && data.cbtcOccupied != undefined) { + this.cbtcOccupied = data.cbtcOccupied; + } + if ("locked" in data && data.locked != undefined) { + this.locked = data.locked; + } + if ("failLocked" in data && data.failLocked != undefined) { + this.failLocked = data.failLocked; + } + if ("expectLock" in data && data.expectLock != undefined) { + this.expectLock = data.expectLock; + } + if ("expectUnlock" in data && data.expectUnlock != undefined) { + this.expectUnlock = data.expectUnlock; + } + if ("inRoute" in data && data.inRoute != undefined) { + this.inRoute = data.inRoute; + } + if ("cut" in data && data.cut != undefined) { + this.cut = data.cut; + } + if ("atcInvalid" in data && data.atcInvalid != undefined) { + this.atcInvalid = data.atcInvalid; + } + if ("overlap" in data && data.overlap != undefined) { + this.overlap = data.overlap; + } + if ("blocked" in data && data.blocked != undefined) { + this.blocked = data.blocked; + } + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + if ("speedLimit" in data && data.speedLimit != undefined) { + this.speedLimit = data.speedLimit; + } + if ("limitType" in data && data.limitType != undefined) { + this.limitType = data.limitType; + } + } + } + get ciOccupied() { + return pb_1.Message.getFieldWithDefault(this, 1, false) as boolean; + } + set ciOccupied(value: boolean) { + pb_1.Message.setField(this, 1, value); + } + get cbtcOccupied() { + return pb_1.Message.getFieldWithDefault(this, 2, false) as boolean; + } + set cbtcOccupied(value: boolean) { + pb_1.Message.setField(this, 2, value); + } + get locked() { + return pb_1.Message.getFieldWithDefault(this, 3, false) as boolean; + } + set locked(value: boolean) { + pb_1.Message.setField(this, 3, value); + } + get failLocked() { + return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean; + } + set failLocked(value: boolean) { + pb_1.Message.setField(this, 4, value); + } + get expectLock() { + return pb_1.Message.getFieldWithDefault(this, 5, false) as boolean; + } + set expectLock(value: boolean) { + pb_1.Message.setField(this, 5, value); + } + get expectUnlock() { + return pb_1.Message.getFieldWithDefault(this, 6, false) as boolean; + } + set expectUnlock(value: boolean) { + pb_1.Message.setField(this, 6, value); + } + get inRoute() { + return pb_1.Message.getFieldWithDefault(this, 7, false) as boolean; + } + set inRoute(value: boolean) { + pb_1.Message.setField(this, 7, value); + } + get cut() { + return pb_1.Message.getFieldWithDefault(this, 8, false) as boolean; + } + set cut(value: boolean) { + pb_1.Message.setField(this, 8, value); + } + get atcInvalid() { + return pb_1.Message.getFieldWithDefault(this, 9, false) as boolean; + } + set atcInvalid(value: boolean) { + pb_1.Message.setField(this, 9, value); + } + get overlap() { + return pb_1.Message.getFieldWithDefault(this, 10, false) as boolean; + } + set overlap(value: boolean) { + pb_1.Message.setField(this, 10, value); + } + get blocked() { + return pb_1.Message.getFieldWithDefault(this, 11, false) as boolean; + } + set blocked(value: boolean) { + pb_1.Message.setField(this, 11, value); + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 12, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 12, value); + } + get speedLimit() { + return pb_1.Message.getFieldWithDefault(this, 13, 0) as number; + } + set speedLimit(value: number) { + pb_1.Message.setField(this, 13, value); + } + get limitType() { + return pb_1.Message.getFieldWithDefault(this, 14, Track.LimitType.Unknown) as Track.LimitType; + } + set limitType(value: Track.LimitType) { + pb_1.Message.setField(this, 14, value); + } + static fromObject(data: { + ciOccupied?: boolean; + cbtcOccupied?: boolean; + locked?: boolean; + failLocked?: boolean; + expectLock?: boolean; + expectUnlock?: boolean; + inRoute?: boolean; + cut?: boolean; + atcInvalid?: boolean; + overlap?: boolean; + blocked?: boolean; + id?: string; + speedLimit?: number; + limitType?: Track.LimitType; + }): Track { + const message = new Track({}); + if (data.ciOccupied != null) { + message.ciOccupied = data.ciOccupied; + } + if (data.cbtcOccupied != null) { + message.cbtcOccupied = data.cbtcOccupied; + } + if (data.locked != null) { + message.locked = data.locked; + } + if (data.failLocked != null) { + message.failLocked = data.failLocked; + } + if (data.expectLock != null) { + message.expectLock = data.expectLock; + } + if (data.expectUnlock != null) { + message.expectUnlock = data.expectUnlock; + } + if (data.inRoute != null) { + message.inRoute = data.inRoute; + } + if (data.cut != null) { + message.cut = data.cut; + } + if (data.atcInvalid != null) { + message.atcInvalid = data.atcInvalid; + } + if (data.overlap != null) { + message.overlap = data.overlap; + } + if (data.blocked != null) { + message.blocked = data.blocked; + } + if (data.id != null) { + message.id = data.id; + } + if (data.speedLimit != null) { + message.speedLimit = data.speedLimit; + } + if (data.limitType != null) { + message.limitType = data.limitType; + } + return message; + } + toObject() { + const data: { + ciOccupied?: boolean; + cbtcOccupied?: boolean; + locked?: boolean; + failLocked?: boolean; + expectLock?: boolean; + expectUnlock?: boolean; + inRoute?: boolean; + cut?: boolean; + atcInvalid?: boolean; + overlap?: boolean; + blocked?: boolean; + id?: string; + speedLimit?: number; + limitType?: Track.LimitType; + } = {}; + if (this.ciOccupied != null) { + data.ciOccupied = this.ciOccupied; + } + if (this.cbtcOccupied != null) { + data.cbtcOccupied = this.cbtcOccupied; + } + if (this.locked != null) { + data.locked = this.locked; + } + if (this.failLocked != null) { + data.failLocked = this.failLocked; + } + if (this.expectLock != null) { + data.expectLock = this.expectLock; + } + if (this.expectUnlock != null) { + data.expectUnlock = this.expectUnlock; + } + if (this.inRoute != null) { + data.inRoute = this.inRoute; + } + if (this.cut != null) { + data.cut = this.cut; + } + if (this.atcInvalid != null) { + data.atcInvalid = this.atcInvalid; + } + if (this.overlap != null) { + data.overlap = this.overlap; + } + if (this.blocked != null) { + data.blocked = this.blocked; + } + if (this.id != null) { + data.id = this.id; + } + if (this.speedLimit != null) { + data.speedLimit = this.speedLimit; + } + if (this.limitType != null) { + data.limitType = this.limitType; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.ciOccupied != false) + writer.writeBool(1, this.ciOccupied); + if (this.cbtcOccupied != false) + writer.writeBool(2, this.cbtcOccupied); + if (this.locked != false) + writer.writeBool(3, this.locked); + if (this.failLocked != false) + writer.writeBool(4, this.failLocked); + if (this.expectLock != false) + writer.writeBool(5, this.expectLock); + if (this.expectUnlock != false) + writer.writeBool(6, this.expectUnlock); + if (this.inRoute != false) + writer.writeBool(7, this.inRoute); + if (this.cut != false) + writer.writeBool(8, this.cut); + if (this.atcInvalid != false) + writer.writeBool(9, this.atcInvalid); + if (this.overlap != false) + writer.writeBool(10, this.overlap); + if (this.blocked != false) + writer.writeBool(11, this.blocked); + if (this.id.length) + writer.writeString(12, this.id); + if (this.speedLimit != 0) + writer.writeInt32(13, this.speedLimit); + if (this.limitType != Track.LimitType.Unknown) + writer.writeEnum(14, this.limitType); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Track { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Track(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.ciOccupied = reader.readBool(); + break; + case 2: + message.cbtcOccupied = reader.readBool(); + break; + case 3: + message.locked = reader.readBool(); + break; + case 4: + message.failLocked = reader.readBool(); + break; + case 5: + message.expectLock = reader.readBool(); + break; + case 6: + message.expectUnlock = reader.readBool(); + break; + case 7: + message.inRoute = reader.readBool(); + break; + case 8: + message.cut = reader.readBool(); + break; + case 9: + message.atcInvalid = reader.readBool(); + break; + case 10: + message.overlap = reader.readBool(); + break; + case 11: + message.blocked = reader.readBool(); + break; + case 12: + message.id = reader.readString(); + break; + case 13: + message.speedLimit = reader.readInt32(); + break; + case 14: + message.limitType = reader.readEnum(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Track { + return Track.deserialize(bytes); + } + } + export namespace Track { + export enum LimitType { + Unknown = 0, + Cbtc = 1, + Interlock = 2, + CbtcInterlock = 4 + } + } + export class Platform extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + emergstop?: boolean; + trainberth?: boolean; + close?: boolean; + upHold?: boolean; + downHold?: boolean; + upOccHold?: boolean; + downOccHold?: boolean; + psdOpen?: boolean; + psdCut?: boolean; + upSkipstop?: boolean; + downSkipstop?: boolean; + upTrainSkipstop?: boolean; + downTrainSkipstop?: boolean; + id?: string; + nextSectionRunTime?: number; + nextSectionRunLevel?: number; + stopTime?: number; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("emergstop" in data && data.emergstop != undefined) { + this.emergstop = data.emergstop; + } + if ("trainberth" in data && data.trainberth != undefined) { + this.trainberth = data.trainberth; + } + if ("close" in data && data.close != undefined) { + this.close = data.close; + } + if ("upHold" in data && data.upHold != undefined) { + this.upHold = data.upHold; + } + if ("downHold" in data && data.downHold != undefined) { + this.downHold = data.downHold; + } + if ("upOccHold" in data && data.upOccHold != undefined) { + this.upOccHold = data.upOccHold; + } + if ("downOccHold" in data && data.downOccHold != undefined) { + this.downOccHold = data.downOccHold; + } + if ("psdOpen" in data && data.psdOpen != undefined) { + this.psdOpen = data.psdOpen; + } + if ("psdCut" in data && data.psdCut != undefined) { + this.psdCut = data.psdCut; + } + if ("upSkipstop" in data && data.upSkipstop != undefined) { + this.upSkipstop = data.upSkipstop; + } + if ("downSkipstop" in data && data.downSkipstop != undefined) { + this.downSkipstop = data.downSkipstop; + } + if ("upTrainSkipstop" in data && data.upTrainSkipstop != undefined) { + this.upTrainSkipstop = data.upTrainSkipstop; + } + if ("downTrainSkipstop" in data && data.downTrainSkipstop != undefined) { + this.downTrainSkipstop = data.downTrainSkipstop; + } + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + if ("nextSectionRunTime" in data && data.nextSectionRunTime != undefined) { + this.nextSectionRunTime = data.nextSectionRunTime; + } + if ("nextSectionRunLevel" in data && data.nextSectionRunLevel != undefined) { + this.nextSectionRunLevel = data.nextSectionRunLevel; + } + if ("stopTime" in data && data.stopTime != undefined) { + this.stopTime = data.stopTime; + } + } + } + get emergstop() { + return pb_1.Message.getFieldWithDefault(this, 1, false) as boolean; + } + set emergstop(value: boolean) { + pb_1.Message.setField(this, 1, value); + } + get trainberth() { + return pb_1.Message.getFieldWithDefault(this, 2, false) as boolean; + } + set trainberth(value: boolean) { + pb_1.Message.setField(this, 2, value); + } + get close() { + return pb_1.Message.getFieldWithDefault(this, 3, false) as boolean; + } + set close(value: boolean) { + pb_1.Message.setField(this, 3, value); + } + get upHold() { + return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean; + } + set upHold(value: boolean) { + pb_1.Message.setField(this, 4, value); + } + get downHold() { + return pb_1.Message.getFieldWithDefault(this, 5, false) as boolean; + } + set downHold(value: boolean) { + pb_1.Message.setField(this, 5, value); + } + get upOccHold() { + return pb_1.Message.getFieldWithDefault(this, 6, false) as boolean; + } + set upOccHold(value: boolean) { + pb_1.Message.setField(this, 6, value); + } + get downOccHold() { + return pb_1.Message.getFieldWithDefault(this, 7, false) as boolean; + } + set downOccHold(value: boolean) { + pb_1.Message.setField(this, 7, value); + } + get psdOpen() { + return pb_1.Message.getFieldWithDefault(this, 8, false) as boolean; + } + set psdOpen(value: boolean) { + pb_1.Message.setField(this, 8, value); + } + get psdCut() { + return pb_1.Message.getFieldWithDefault(this, 9, false) as boolean; + } + set psdCut(value: boolean) { + pb_1.Message.setField(this, 9, value); + } + get upSkipstop() { + return pb_1.Message.getFieldWithDefault(this, 10, false) as boolean; + } + set upSkipstop(value: boolean) { + pb_1.Message.setField(this, 10, value); + } + get downSkipstop() { + return pb_1.Message.getFieldWithDefault(this, 11, false) as boolean; + } + set downSkipstop(value: boolean) { + pb_1.Message.setField(this, 11, value); + } + get upTrainSkipstop() { + return pb_1.Message.getFieldWithDefault(this, 12, false) as boolean; + } + set upTrainSkipstop(value: boolean) { + pb_1.Message.setField(this, 12, value); + } + get downTrainSkipstop() { + return pb_1.Message.getFieldWithDefault(this, 13, false) as boolean; + } + set downTrainSkipstop(value: boolean) { + pb_1.Message.setField(this, 13, value); + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 14, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 14, value); + } + get nextSectionRunTime() { + return pb_1.Message.getFieldWithDefault(this, 15, 0) as number; + } + set nextSectionRunTime(value: number) { + pb_1.Message.setField(this, 15, value); + } + get nextSectionRunLevel() { + return pb_1.Message.getFieldWithDefault(this, 16, 0) as number; + } + set nextSectionRunLevel(value: number) { + pb_1.Message.setField(this, 16, value); + } + get stopTime() { + return pb_1.Message.getFieldWithDefault(this, 17, 0) as number; + } + set stopTime(value: number) { + pb_1.Message.setField(this, 17, value); + } + static fromObject(data: { + emergstop?: boolean; + trainberth?: boolean; + close?: boolean; + upHold?: boolean; + downHold?: boolean; + upOccHold?: boolean; + downOccHold?: boolean; + psdOpen?: boolean; + psdCut?: boolean; + upSkipstop?: boolean; + downSkipstop?: boolean; + upTrainSkipstop?: boolean; + downTrainSkipstop?: boolean; + id?: string; + nextSectionRunTime?: number; + nextSectionRunLevel?: number; + stopTime?: number; + }): Platform { + const message = new Platform({}); + if (data.emergstop != null) { + message.emergstop = data.emergstop; + } + if (data.trainberth != null) { + message.trainberth = data.trainberth; + } + if (data.close != null) { + message.close = data.close; + } + if (data.upHold != null) { + message.upHold = data.upHold; + } + if (data.downHold != null) { + message.downHold = data.downHold; + } + if (data.upOccHold != null) { + message.upOccHold = data.upOccHold; + } + if (data.downOccHold != null) { + message.downOccHold = data.downOccHold; + } + if (data.psdOpen != null) { + message.psdOpen = data.psdOpen; + } + if (data.psdCut != null) { + message.psdCut = data.psdCut; + } + if (data.upSkipstop != null) { + message.upSkipstop = data.upSkipstop; + } + if (data.downSkipstop != null) { + message.downSkipstop = data.downSkipstop; + } + if (data.upTrainSkipstop != null) { + message.upTrainSkipstop = data.upTrainSkipstop; + } + if (data.downTrainSkipstop != null) { + message.downTrainSkipstop = data.downTrainSkipstop; + } + if (data.id != null) { + message.id = data.id; + } + if (data.nextSectionRunTime != null) { + message.nextSectionRunTime = data.nextSectionRunTime; + } + if (data.nextSectionRunLevel != null) { + message.nextSectionRunLevel = data.nextSectionRunLevel; + } + if (data.stopTime != null) { + message.stopTime = data.stopTime; + } + return message; + } + toObject() { + const data: { + emergstop?: boolean; + trainberth?: boolean; + close?: boolean; + upHold?: boolean; + downHold?: boolean; + upOccHold?: boolean; + downOccHold?: boolean; + psdOpen?: boolean; + psdCut?: boolean; + upSkipstop?: boolean; + downSkipstop?: boolean; + upTrainSkipstop?: boolean; + downTrainSkipstop?: boolean; + id?: string; + nextSectionRunTime?: number; + nextSectionRunLevel?: number; + stopTime?: number; + } = {}; + if (this.emergstop != null) { + data.emergstop = this.emergstop; + } + if (this.trainberth != null) { + data.trainberth = this.trainberth; + } + if (this.close != null) { + data.close = this.close; + } + if (this.upHold != null) { + data.upHold = this.upHold; + } + if (this.downHold != null) { + data.downHold = this.downHold; + } + if (this.upOccHold != null) { + data.upOccHold = this.upOccHold; + } + if (this.downOccHold != null) { + data.downOccHold = this.downOccHold; + } + if (this.psdOpen != null) { + data.psdOpen = this.psdOpen; + } + if (this.psdCut != null) { + data.psdCut = this.psdCut; + } + if (this.upSkipstop != null) { + data.upSkipstop = this.upSkipstop; + } + if (this.downSkipstop != null) { + data.downSkipstop = this.downSkipstop; + } + if (this.upTrainSkipstop != null) { + data.upTrainSkipstop = this.upTrainSkipstop; + } + if (this.downTrainSkipstop != null) { + data.downTrainSkipstop = this.downTrainSkipstop; + } + if (this.id != null) { + data.id = this.id; + } + if (this.nextSectionRunTime != null) { + data.nextSectionRunTime = this.nextSectionRunTime; + } + if (this.nextSectionRunLevel != null) { + data.nextSectionRunLevel = this.nextSectionRunLevel; + } + if (this.stopTime != null) { + data.stopTime = this.stopTime; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.emergstop != false) + writer.writeBool(1, this.emergstop); + if (this.trainberth != false) + writer.writeBool(2, this.trainberth); + if (this.close != false) + writer.writeBool(3, this.close); + if (this.upHold != false) + writer.writeBool(4, this.upHold); + if (this.downHold != false) + writer.writeBool(5, this.downHold); + if (this.upOccHold != false) + writer.writeBool(6, this.upOccHold); + if (this.downOccHold != false) + writer.writeBool(7, this.downOccHold); + if (this.psdOpen != false) + writer.writeBool(8, this.psdOpen); + if (this.psdCut != false) + writer.writeBool(9, this.psdCut); + if (this.upSkipstop != false) + writer.writeBool(10, this.upSkipstop); + if (this.downSkipstop != false) + writer.writeBool(11, this.downSkipstop); + if (this.upTrainSkipstop != false) + writer.writeBool(12, this.upTrainSkipstop); + if (this.downTrainSkipstop != false) + writer.writeBool(13, this.downTrainSkipstop); + if (this.id.length) + writer.writeString(14, this.id); + if (this.nextSectionRunTime != 0) + writer.writeInt32(15, this.nextSectionRunTime); + if (this.nextSectionRunLevel != 0) + writer.writeInt32(16, this.nextSectionRunLevel); + if (this.stopTime != 0) + writer.writeInt32(17, this.stopTime); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Platform { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Platform(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.emergstop = reader.readBool(); + break; + case 2: + message.trainberth = reader.readBool(); + break; + case 3: + message.close = reader.readBool(); + break; + case 4: + message.upHold = reader.readBool(); + break; + case 5: + message.downHold = reader.readBool(); + break; + case 6: + message.upOccHold = reader.readBool(); + break; + case 7: + message.downOccHold = reader.readBool(); + break; + case 8: + message.psdOpen = reader.readBool(); + break; + case 9: + message.psdCut = reader.readBool(); + break; + case 10: + message.upSkipstop = reader.readBool(); + break; + case 11: + message.downSkipstop = reader.readBool(); + break; + case 12: + message.upTrainSkipstop = reader.readBool(); + break; + case 13: + message.downTrainSkipstop = reader.readBool(); + break; + case 14: + message.id = reader.readString(); + break; + case 15: + message.nextSectionRunTime = reader.readInt32(); + break; + case 16: + message.nextSectionRunLevel = reader.readInt32(); + break; + case 17: + message.stopTime = reader.readInt32(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Platform { + return Platform.deserialize(bytes); + } + } + export class Scada extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + scadaOn?: boolean; + scadaSinglePower?: boolean; + scadaUnkown?: boolean; + id?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("scadaOn" in data && data.scadaOn != undefined) { + this.scadaOn = data.scadaOn; + } + if ("scadaSinglePower" in data && data.scadaSinglePower != undefined) { + this.scadaSinglePower = data.scadaSinglePower; + } + if ("scadaUnkown" in data && data.scadaUnkown != undefined) { + this.scadaUnkown = data.scadaUnkown; + } + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + } + } + get scadaOn() { + return pb_1.Message.getFieldWithDefault(this, 1, false) as boolean; + } + set scadaOn(value: boolean) { + pb_1.Message.setField(this, 1, value); + } + get scadaSinglePower() { + return pb_1.Message.getFieldWithDefault(this, 2, false) as boolean; + } + set scadaSinglePower(value: boolean) { + pb_1.Message.setField(this, 2, value); + } + get scadaUnkown() { + return pb_1.Message.getFieldWithDefault(this, 3, false) as boolean; + } + set scadaUnkown(value: boolean) { + pb_1.Message.setField(this, 3, value); + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 4, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 4, value); + } + static fromObject(data: { + scadaOn?: boolean; + scadaSinglePower?: boolean; + scadaUnkown?: boolean; + id?: string; + }): Scada { + const message = new Scada({}); + if (data.scadaOn != null) { + message.scadaOn = data.scadaOn; + } + if (data.scadaSinglePower != null) { + message.scadaSinglePower = data.scadaSinglePower; + } + if (data.scadaUnkown != null) { + message.scadaUnkown = data.scadaUnkown; + } + if (data.id != null) { + message.id = data.id; + } + return message; + } + toObject() { + const data: { + scadaOn?: boolean; + scadaSinglePower?: boolean; + scadaUnkown?: boolean; + id?: string; + } = {}; + if (this.scadaOn != null) { + data.scadaOn = this.scadaOn; + } + if (this.scadaSinglePower != null) { + data.scadaSinglePower = this.scadaSinglePower; + } + if (this.scadaUnkown != null) { + data.scadaUnkown = this.scadaUnkown; + } + if (this.id != null) { + data.id = this.id; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.scadaOn != false) + writer.writeBool(1, this.scadaOn); + if (this.scadaSinglePower != false) + writer.writeBool(2, this.scadaSinglePower); + if (this.scadaUnkown != false) + writer.writeBool(3, this.scadaUnkown); + if (this.id.length) + writer.writeString(4, this.id); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Scada { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Scada(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.scadaOn = reader.readBool(); + break; + case 2: + message.scadaSinglePower = reader.readBool(); + break; + case 3: + message.scadaUnkown = reader.readBool(); + break; + case 4: + message.id = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Scada { + return Scada.deserialize(bytes); + } + } + export class WaterProofDoor extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + doorClosed?: boolean; + doorExpectClose?: boolean; + doorAgreeClosed?: boolean; + doorClosing?: boolean; + doorOpenLock?: boolean; + id?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("doorClosed" in data && data.doorClosed != undefined) { + this.doorClosed = data.doorClosed; + } + if ("doorExpectClose" in data && data.doorExpectClose != undefined) { + this.doorExpectClose = data.doorExpectClose; + } + if ("doorAgreeClosed" in data && data.doorAgreeClosed != undefined) { + this.doorAgreeClosed = data.doorAgreeClosed; + } + if ("doorClosing" in data && data.doorClosing != undefined) { + this.doorClosing = data.doorClosing; + } + if ("doorOpenLock" in data && data.doorOpenLock != undefined) { + this.doorOpenLock = data.doorOpenLock; + } + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + } + } + get doorClosed() { + return pb_1.Message.getFieldWithDefault(this, 1, false) as boolean; + } + set doorClosed(value: boolean) { + pb_1.Message.setField(this, 1, value); + } + get doorExpectClose() { + return pb_1.Message.getFieldWithDefault(this, 2, false) as boolean; + } + set doorExpectClose(value: boolean) { + pb_1.Message.setField(this, 2, value); + } + get doorAgreeClosed() { + return pb_1.Message.getFieldWithDefault(this, 3, false) as boolean; + } + set doorAgreeClosed(value: boolean) { + pb_1.Message.setField(this, 3, value); + } + get doorClosing() { + return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean; + } + set doorClosing(value: boolean) { + pb_1.Message.setField(this, 4, value); + } + get doorOpenLock() { + return pb_1.Message.getFieldWithDefault(this, 5, false) as boolean; + } + set doorOpenLock(value: boolean) { + pb_1.Message.setField(this, 5, value); + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 6, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 6, value); + } + static fromObject(data: { + doorClosed?: boolean; + doorExpectClose?: boolean; + doorAgreeClosed?: boolean; + doorClosing?: boolean; + doorOpenLock?: boolean; + id?: string; + }): WaterProofDoor { + const message = new WaterProofDoor({}); + if (data.doorClosed != null) { + message.doorClosed = data.doorClosed; + } + if (data.doorExpectClose != null) { + message.doorExpectClose = data.doorExpectClose; + } + if (data.doorAgreeClosed != null) { + message.doorAgreeClosed = data.doorAgreeClosed; + } + if (data.doorClosing != null) { + message.doorClosing = data.doorClosing; + } + if (data.doorOpenLock != null) { + message.doorOpenLock = data.doorOpenLock; + } + if (data.id != null) { + message.id = data.id; + } + return message; + } + toObject() { + const data: { + doorClosed?: boolean; + doorExpectClose?: boolean; + doorAgreeClosed?: boolean; + doorClosing?: boolean; + doorOpenLock?: boolean; + id?: string; + } = {}; + if (this.doorClosed != null) { + data.doorClosed = this.doorClosed; + } + if (this.doorExpectClose != null) { + data.doorExpectClose = this.doorExpectClose; + } + if (this.doorAgreeClosed != null) { + data.doorAgreeClosed = this.doorAgreeClosed; + } + if (this.doorClosing != null) { + data.doorClosing = this.doorClosing; + } + if (this.doorOpenLock != null) { + data.doorOpenLock = this.doorOpenLock; + } + if (this.id != null) { + data.id = this.id; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.doorClosed != false) + writer.writeBool(1, this.doorClosed); + if (this.doorExpectClose != false) + writer.writeBool(2, this.doorExpectClose); + if (this.doorAgreeClosed != false) + writer.writeBool(3, this.doorAgreeClosed); + if (this.doorClosing != false) + writer.writeBool(4, this.doorClosing); + if (this.doorOpenLock != false) + writer.writeBool(5, this.doorOpenLock); + if (this.id.length) + writer.writeString(6, this.id); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): WaterProofDoor { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new WaterProofDoor(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.doorClosed = reader.readBool(); + break; + case 2: + message.doorExpectClose = reader.readBool(); + break; + case 3: + message.doorAgreeClosed = reader.readBool(); + break; + case 4: + message.doorClosing = reader.readBool(); + break; + case 5: + message.doorOpenLock = reader.readBool(); + break; + case 6: + message.id = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): WaterProofDoor { + return WaterProofDoor.deserialize(bytes); + } + } + export class WorkArea extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + ipStusWorkAreaEnable?: boolean; + id?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("ipStusWorkAreaEnable" in data && data.ipStusWorkAreaEnable != undefined) { + this.ipStusWorkAreaEnable = data.ipStusWorkAreaEnable; + } + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + } + } + get ipStusWorkAreaEnable() { + return pb_1.Message.getFieldWithDefault(this, 1, false) as boolean; + } + set ipStusWorkAreaEnable(value: boolean) { + pb_1.Message.setField(this, 1, value); + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 2, value); + } + static fromObject(data: { + ipStusWorkAreaEnable?: boolean; + id?: string; + }): WorkArea { + const message = new WorkArea({}); + if (data.ipStusWorkAreaEnable != null) { + message.ipStusWorkAreaEnable = data.ipStusWorkAreaEnable; + } + if (data.id != null) { + message.id = data.id; + } + return message; + } + toObject() { + const data: { + ipStusWorkAreaEnable?: boolean; + id?: string; + } = {}; + if (this.ipStusWorkAreaEnable != null) { + data.ipStusWorkAreaEnable = this.ipStusWorkAreaEnable; + } + if (this.id != null) { + data.id = this.id; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.ipStusWorkAreaEnable != false) + writer.writeBool(1, this.ipStusWorkAreaEnable); + if (this.id.length) + writer.writeString(2, this.id); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): WorkArea { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new WorkArea(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.ipStusWorkAreaEnable = reader.readBool(); + break; + case 2: + message.id = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): WorkArea { + return WorkArea.deserialize(bytes); + } + } + export class Gama extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + ipStusGamaDisable?: boolean; + id?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("ipStusGamaDisable" in data && data.ipStusGamaDisable != undefined) { + this.ipStusGamaDisable = data.ipStusGamaDisable; + } + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + } + } + get ipStusGamaDisable() { + return pb_1.Message.getFieldWithDefault(this, 1, false) as boolean; + } + set ipStusGamaDisable(value: boolean) { + pb_1.Message.setField(this, 1, value); + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 2, value); + } + static fromObject(data: { + ipStusGamaDisable?: boolean; + id?: string; + }): Gama { + const message = new Gama({}); + if (data.ipStusGamaDisable != null) { + message.ipStusGamaDisable = data.ipStusGamaDisable; + } + if (data.id != null) { + message.id = data.id; + } + return message; + } + toObject() { + const data: { + ipStusGamaDisable?: boolean; + id?: string; + } = {}; + if (this.ipStusGamaDisable != null) { + data.ipStusGamaDisable = this.ipStusGamaDisable; + } + if (this.id != null) { + data.id = this.id; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.ipStusGamaDisable != false) + writer.writeBool(1, this.ipStusGamaDisable); + if (this.id.length) + writer.writeString(2, this.id); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Gama { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Gama(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.ipStusGamaDisable = reader.readBool(); + break; + case 2: + message.id = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Gama { + return Gama.deserialize(bytes); + } + } + export class TrainMode extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + ipModeTrainTypeManual?: boolean; + ipModeTrainTypeHead?: boolean; + ipModeTrainTypeSpecial?: boolean; + ipModeTrainTypeSchedule?: boolean; + ipModeTrainTypeRoute?: boolean; + ipModeTrainTypeShuttle?: boolean; + ipModeTrainTypeLineup?: boolean; + ipModeTrainSchdEarly?: boolean; + ipModeTrainSchdLate?: boolean; + ipModeTrainSkipstop?: boolean; + ipModeTrainCbtcMode?: boolean; + ipModeTrainAtpCut?: boolean; + ipModeTrainBerthed?: boolean; + ipModeTrainStoped?: boolean; + ipModeTrainHolded?: boolean; + ipModeTrainItama?: boolean; + ipModeTrainDirUp?: boolean; + ipModeTrainDirDown?: boolean; + ipModeTrainDirHeadUp?: boolean; + ipModeTrainDirHeadDown?: boolean; + ipModeTrainDoorOpen?: boolean; + ipModeTrainRsAlarm?: boolean; + ipModeTrainDoorAlarm?: boolean; + ipModeTrainEbAlarm?: boolean; + ipModeTrainIntegrityAlarm?: boolean; + ipModeTrainDriveModeAm?: boolean; + ipModeTrainDriveModeCm?: boolean; + ipModeTrainDriveModeRmf?: boolean; + ipModeTrainDriveModeDto?: boolean; + ipModeTrainDriveModeAtb?: boolean; + ipModeTrainDriveBlockAm?: boolean; + ipModeTrainDriveBlockCm?: boolean; + ipModeTrainDriveModeRmr?: boolean; + ipModeTrainDriveModeWash?: boolean; + id?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("ipModeTrainTypeManual" in data && data.ipModeTrainTypeManual != undefined) { + this.ipModeTrainTypeManual = data.ipModeTrainTypeManual; + } + if ("ipModeTrainTypeHead" in data && data.ipModeTrainTypeHead != undefined) { + this.ipModeTrainTypeHead = data.ipModeTrainTypeHead; + } + if ("ipModeTrainTypeSpecial" in data && data.ipModeTrainTypeSpecial != undefined) { + this.ipModeTrainTypeSpecial = data.ipModeTrainTypeSpecial; + } + if ("ipModeTrainTypeSchedule" in data && data.ipModeTrainTypeSchedule != undefined) { + this.ipModeTrainTypeSchedule = data.ipModeTrainTypeSchedule; + } + if ("ipModeTrainTypeRoute" in data && data.ipModeTrainTypeRoute != undefined) { + this.ipModeTrainTypeRoute = data.ipModeTrainTypeRoute; + } + if ("ipModeTrainTypeShuttle" in data && data.ipModeTrainTypeShuttle != undefined) { + this.ipModeTrainTypeShuttle = data.ipModeTrainTypeShuttle; + } + if ("ipModeTrainTypeLineup" in data && data.ipModeTrainTypeLineup != undefined) { + this.ipModeTrainTypeLineup = data.ipModeTrainTypeLineup; + } + if ("ipModeTrainSchdEarly" in data && data.ipModeTrainSchdEarly != undefined) { + this.ipModeTrainSchdEarly = data.ipModeTrainSchdEarly; + } + if ("ipModeTrainSchdLate" in data && data.ipModeTrainSchdLate != undefined) { + this.ipModeTrainSchdLate = data.ipModeTrainSchdLate; + } + if ("ipModeTrainSkipstop" in data && data.ipModeTrainSkipstop != undefined) { + this.ipModeTrainSkipstop = data.ipModeTrainSkipstop; + } + if ("ipModeTrainCbtcMode" in data && data.ipModeTrainCbtcMode != undefined) { + this.ipModeTrainCbtcMode = data.ipModeTrainCbtcMode; + } + if ("ipModeTrainAtpCut" in data && data.ipModeTrainAtpCut != undefined) { + this.ipModeTrainAtpCut = data.ipModeTrainAtpCut; + } + if ("ipModeTrainBerthed" in data && data.ipModeTrainBerthed != undefined) { + this.ipModeTrainBerthed = data.ipModeTrainBerthed; + } + if ("ipModeTrainStoped" in data && data.ipModeTrainStoped != undefined) { + this.ipModeTrainStoped = data.ipModeTrainStoped; + } + if ("ipModeTrainHolded" in data && data.ipModeTrainHolded != undefined) { + this.ipModeTrainHolded = data.ipModeTrainHolded; + } + if ("ipModeTrainItama" in data && data.ipModeTrainItama != undefined) { + this.ipModeTrainItama = data.ipModeTrainItama; + } + if ("ipModeTrainDirUp" in data && data.ipModeTrainDirUp != undefined) { + this.ipModeTrainDirUp = data.ipModeTrainDirUp; + } + if ("ipModeTrainDirDown" in data && data.ipModeTrainDirDown != undefined) { + this.ipModeTrainDirDown = data.ipModeTrainDirDown; + } + if ("ipModeTrainDirHeadUp" in data && data.ipModeTrainDirHeadUp != undefined) { + this.ipModeTrainDirHeadUp = data.ipModeTrainDirHeadUp; + } + if ("ipModeTrainDirHeadDown" in data && data.ipModeTrainDirHeadDown != undefined) { + this.ipModeTrainDirHeadDown = data.ipModeTrainDirHeadDown; + } + if ("ipModeTrainDoorOpen" in data && data.ipModeTrainDoorOpen != undefined) { + this.ipModeTrainDoorOpen = data.ipModeTrainDoorOpen; + } + if ("ipModeTrainRsAlarm" in data && data.ipModeTrainRsAlarm != undefined) { + this.ipModeTrainRsAlarm = data.ipModeTrainRsAlarm; + } + if ("ipModeTrainDoorAlarm" in data && data.ipModeTrainDoorAlarm != undefined) { + this.ipModeTrainDoorAlarm = data.ipModeTrainDoorAlarm; + } + if ("ipModeTrainEbAlarm" in data && data.ipModeTrainEbAlarm != undefined) { + this.ipModeTrainEbAlarm = data.ipModeTrainEbAlarm; + } + if ("ipModeTrainIntegrityAlarm" in data && data.ipModeTrainIntegrityAlarm != undefined) { + this.ipModeTrainIntegrityAlarm = data.ipModeTrainIntegrityAlarm; + } + if ("ipModeTrainDriveModeAm" in data && data.ipModeTrainDriveModeAm != undefined) { + this.ipModeTrainDriveModeAm = data.ipModeTrainDriveModeAm; + } + if ("ipModeTrainDriveModeCm" in data && data.ipModeTrainDriveModeCm != undefined) { + this.ipModeTrainDriveModeCm = data.ipModeTrainDriveModeCm; + } + if ("ipModeTrainDriveModeRmf" in data && data.ipModeTrainDriveModeRmf != undefined) { + this.ipModeTrainDriveModeRmf = data.ipModeTrainDriveModeRmf; + } + if ("ipModeTrainDriveModeDto" in data && data.ipModeTrainDriveModeDto != undefined) { + this.ipModeTrainDriveModeDto = data.ipModeTrainDriveModeDto; + } + if ("ipModeTrainDriveModeAtb" in data && data.ipModeTrainDriveModeAtb != undefined) { + this.ipModeTrainDriveModeAtb = data.ipModeTrainDriveModeAtb; + } + if ("ipModeTrainDriveBlockAm" in data && data.ipModeTrainDriveBlockAm != undefined) { + this.ipModeTrainDriveBlockAm = data.ipModeTrainDriveBlockAm; + } + if ("ipModeTrainDriveBlockCm" in data && data.ipModeTrainDriveBlockCm != undefined) { + this.ipModeTrainDriveBlockCm = data.ipModeTrainDriveBlockCm; + } + if ("ipModeTrainDriveModeRmr" in data && data.ipModeTrainDriveModeRmr != undefined) { + this.ipModeTrainDriveModeRmr = data.ipModeTrainDriveModeRmr; + } + if ("ipModeTrainDriveModeWash" in data && data.ipModeTrainDriveModeWash != undefined) { + this.ipModeTrainDriveModeWash = data.ipModeTrainDriveModeWash; + } + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + } + } + get ipModeTrainTypeManual() { + return pb_1.Message.getFieldWithDefault(this, 1, false) as boolean; + } + set ipModeTrainTypeManual(value: boolean) { + pb_1.Message.setField(this, 1, value); + } + get ipModeTrainTypeHead() { + return pb_1.Message.getFieldWithDefault(this, 2, false) as boolean; + } + set ipModeTrainTypeHead(value: boolean) { + pb_1.Message.setField(this, 2, value); + } + get ipModeTrainTypeSpecial() { + return pb_1.Message.getFieldWithDefault(this, 3, false) as boolean; + } + set ipModeTrainTypeSpecial(value: boolean) { + pb_1.Message.setField(this, 3, value); + } + get ipModeTrainTypeSchedule() { + return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean; + } + set ipModeTrainTypeSchedule(value: boolean) { + pb_1.Message.setField(this, 4, value); + } + get ipModeTrainTypeRoute() { + return pb_1.Message.getFieldWithDefault(this, 5, false) as boolean; + } + set ipModeTrainTypeRoute(value: boolean) { + pb_1.Message.setField(this, 5, value); + } + get ipModeTrainTypeShuttle() { + return pb_1.Message.getFieldWithDefault(this, 6, false) as boolean; + } + set ipModeTrainTypeShuttle(value: boolean) { + pb_1.Message.setField(this, 6, value); + } + get ipModeTrainTypeLineup() { + return pb_1.Message.getFieldWithDefault(this, 7, false) as boolean; + } + set ipModeTrainTypeLineup(value: boolean) { + pb_1.Message.setField(this, 7, value); + } + get ipModeTrainSchdEarly() { + return pb_1.Message.getFieldWithDefault(this, 8, false) as boolean; + } + set ipModeTrainSchdEarly(value: boolean) { + pb_1.Message.setField(this, 8, value); + } + get ipModeTrainSchdLate() { + return pb_1.Message.getFieldWithDefault(this, 9, false) as boolean; + } + set ipModeTrainSchdLate(value: boolean) { + pb_1.Message.setField(this, 9, value); + } + get ipModeTrainSkipstop() { + return pb_1.Message.getFieldWithDefault(this, 10, false) as boolean; + } + set ipModeTrainSkipstop(value: boolean) { + pb_1.Message.setField(this, 10, value); + } + get ipModeTrainCbtcMode() { + return pb_1.Message.getFieldWithDefault(this, 11, false) as boolean; + } + set ipModeTrainCbtcMode(value: boolean) { + pb_1.Message.setField(this, 11, value); + } + get ipModeTrainAtpCut() { + return pb_1.Message.getFieldWithDefault(this, 12, false) as boolean; + } + set ipModeTrainAtpCut(value: boolean) { + pb_1.Message.setField(this, 12, value); + } + get ipModeTrainBerthed() { + return pb_1.Message.getFieldWithDefault(this, 13, false) as boolean; + } + set ipModeTrainBerthed(value: boolean) { + pb_1.Message.setField(this, 13, value); + } + get ipModeTrainStoped() { + return pb_1.Message.getFieldWithDefault(this, 14, false) as boolean; + } + set ipModeTrainStoped(value: boolean) { + pb_1.Message.setField(this, 14, value); + } + get ipModeTrainHolded() { + return pb_1.Message.getFieldWithDefault(this, 15, false) as boolean; + } + set ipModeTrainHolded(value: boolean) { + pb_1.Message.setField(this, 15, value); + } + get ipModeTrainItama() { + return pb_1.Message.getFieldWithDefault(this, 16, false) as boolean; + } + set ipModeTrainItama(value: boolean) { + pb_1.Message.setField(this, 16, value); + } + get ipModeTrainDirUp() { + return pb_1.Message.getFieldWithDefault(this, 17, false) as boolean; + } + set ipModeTrainDirUp(value: boolean) { + pb_1.Message.setField(this, 17, value); + } + get ipModeTrainDirDown() { + return pb_1.Message.getFieldWithDefault(this, 18, false) as boolean; + } + set ipModeTrainDirDown(value: boolean) { + pb_1.Message.setField(this, 18, value); + } + get ipModeTrainDirHeadUp() { + return pb_1.Message.getFieldWithDefault(this, 19, false) as boolean; + } + set ipModeTrainDirHeadUp(value: boolean) { + pb_1.Message.setField(this, 19, value); + } + get ipModeTrainDirHeadDown() { + return pb_1.Message.getFieldWithDefault(this, 20, false) as boolean; + } + set ipModeTrainDirHeadDown(value: boolean) { + pb_1.Message.setField(this, 20, value); + } + get ipModeTrainDoorOpen() { + return pb_1.Message.getFieldWithDefault(this, 21, false) as boolean; + } + set ipModeTrainDoorOpen(value: boolean) { + pb_1.Message.setField(this, 21, value); + } + get ipModeTrainRsAlarm() { + return pb_1.Message.getFieldWithDefault(this, 22, false) as boolean; + } + set ipModeTrainRsAlarm(value: boolean) { + pb_1.Message.setField(this, 22, value); + } + get ipModeTrainDoorAlarm() { + return pb_1.Message.getFieldWithDefault(this, 23, false) as boolean; + } + set ipModeTrainDoorAlarm(value: boolean) { + pb_1.Message.setField(this, 23, value); + } + get ipModeTrainEbAlarm() { + return pb_1.Message.getFieldWithDefault(this, 24, false) as boolean; + } + set ipModeTrainEbAlarm(value: boolean) { + pb_1.Message.setField(this, 24, value); + } + get ipModeTrainIntegrityAlarm() { + return pb_1.Message.getFieldWithDefault(this, 25, false) as boolean; + } + set ipModeTrainIntegrityAlarm(value: boolean) { + pb_1.Message.setField(this, 25, value); + } + get ipModeTrainDriveModeAm() { + return pb_1.Message.getFieldWithDefault(this, 26, false) as boolean; + } + set ipModeTrainDriveModeAm(value: boolean) { + pb_1.Message.setField(this, 26, value); + } + get ipModeTrainDriveModeCm() { + return pb_1.Message.getFieldWithDefault(this, 27, false) as boolean; + } + set ipModeTrainDriveModeCm(value: boolean) { + pb_1.Message.setField(this, 27, value); + } + get ipModeTrainDriveModeRmf() { + return pb_1.Message.getFieldWithDefault(this, 28, false) as boolean; + } + set ipModeTrainDriveModeRmf(value: boolean) { + pb_1.Message.setField(this, 28, value); + } + get ipModeTrainDriveModeDto() { + return pb_1.Message.getFieldWithDefault(this, 29, false) as boolean; + } + set ipModeTrainDriveModeDto(value: boolean) { + pb_1.Message.setField(this, 29, value); + } + get ipModeTrainDriveModeAtb() { + return pb_1.Message.getFieldWithDefault(this, 30, false) as boolean; + } + set ipModeTrainDriveModeAtb(value: boolean) { + pb_1.Message.setField(this, 30, value); + } + get ipModeTrainDriveBlockAm() { + return pb_1.Message.getFieldWithDefault(this, 31, false) as boolean; + } + set ipModeTrainDriveBlockAm(value: boolean) { + pb_1.Message.setField(this, 31, value); + } + get ipModeTrainDriveBlockCm() { + return pb_1.Message.getFieldWithDefault(this, 32, false) as boolean; + } + set ipModeTrainDriveBlockCm(value: boolean) { + pb_1.Message.setField(this, 32, value); + } + get ipModeTrainDriveModeRmr() { + return pb_1.Message.getFieldWithDefault(this, 33, false) as boolean; + } + set ipModeTrainDriveModeRmr(value: boolean) { + pb_1.Message.setField(this, 33, value); + } + get ipModeTrainDriveModeWash() { + return pb_1.Message.getFieldWithDefault(this, 34, false) as boolean; + } + set ipModeTrainDriveModeWash(value: boolean) { + pb_1.Message.setField(this, 34, value); + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 35, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 35, value); + } + static fromObject(data: { + ipModeTrainTypeManual?: boolean; + ipModeTrainTypeHead?: boolean; + ipModeTrainTypeSpecial?: boolean; + ipModeTrainTypeSchedule?: boolean; + ipModeTrainTypeRoute?: boolean; + ipModeTrainTypeShuttle?: boolean; + ipModeTrainTypeLineup?: boolean; + ipModeTrainSchdEarly?: boolean; + ipModeTrainSchdLate?: boolean; + ipModeTrainSkipstop?: boolean; + ipModeTrainCbtcMode?: boolean; + ipModeTrainAtpCut?: boolean; + ipModeTrainBerthed?: boolean; + ipModeTrainStoped?: boolean; + ipModeTrainHolded?: boolean; + ipModeTrainItama?: boolean; + ipModeTrainDirUp?: boolean; + ipModeTrainDirDown?: boolean; + ipModeTrainDirHeadUp?: boolean; + ipModeTrainDirHeadDown?: boolean; + ipModeTrainDoorOpen?: boolean; + ipModeTrainRsAlarm?: boolean; + ipModeTrainDoorAlarm?: boolean; + ipModeTrainEbAlarm?: boolean; + ipModeTrainIntegrityAlarm?: boolean; + ipModeTrainDriveModeAm?: boolean; + ipModeTrainDriveModeCm?: boolean; + ipModeTrainDriveModeRmf?: boolean; + ipModeTrainDriveModeDto?: boolean; + ipModeTrainDriveModeAtb?: boolean; + ipModeTrainDriveBlockAm?: boolean; + ipModeTrainDriveBlockCm?: boolean; + ipModeTrainDriveModeRmr?: boolean; + ipModeTrainDriveModeWash?: boolean; + id?: string; + }): TrainMode { + const message = new TrainMode({}); + if (data.ipModeTrainTypeManual != null) { + message.ipModeTrainTypeManual = data.ipModeTrainTypeManual; + } + if (data.ipModeTrainTypeHead != null) { + message.ipModeTrainTypeHead = data.ipModeTrainTypeHead; + } + if (data.ipModeTrainTypeSpecial != null) { + message.ipModeTrainTypeSpecial = data.ipModeTrainTypeSpecial; + } + if (data.ipModeTrainTypeSchedule != null) { + message.ipModeTrainTypeSchedule = data.ipModeTrainTypeSchedule; + } + if (data.ipModeTrainTypeRoute != null) { + message.ipModeTrainTypeRoute = data.ipModeTrainTypeRoute; + } + if (data.ipModeTrainTypeShuttle != null) { + message.ipModeTrainTypeShuttle = data.ipModeTrainTypeShuttle; + } + if (data.ipModeTrainTypeLineup != null) { + message.ipModeTrainTypeLineup = data.ipModeTrainTypeLineup; + } + if (data.ipModeTrainSchdEarly != null) { + message.ipModeTrainSchdEarly = data.ipModeTrainSchdEarly; + } + if (data.ipModeTrainSchdLate != null) { + message.ipModeTrainSchdLate = data.ipModeTrainSchdLate; + } + if (data.ipModeTrainSkipstop != null) { + message.ipModeTrainSkipstop = data.ipModeTrainSkipstop; + } + if (data.ipModeTrainCbtcMode != null) { + message.ipModeTrainCbtcMode = data.ipModeTrainCbtcMode; + } + if (data.ipModeTrainAtpCut != null) { + message.ipModeTrainAtpCut = data.ipModeTrainAtpCut; + } + if (data.ipModeTrainBerthed != null) { + message.ipModeTrainBerthed = data.ipModeTrainBerthed; + } + if (data.ipModeTrainStoped != null) { + message.ipModeTrainStoped = data.ipModeTrainStoped; + } + if (data.ipModeTrainHolded != null) { + message.ipModeTrainHolded = data.ipModeTrainHolded; + } + if (data.ipModeTrainItama != null) { + message.ipModeTrainItama = data.ipModeTrainItama; + } + if (data.ipModeTrainDirUp != null) { + message.ipModeTrainDirUp = data.ipModeTrainDirUp; + } + if (data.ipModeTrainDirDown != null) { + message.ipModeTrainDirDown = data.ipModeTrainDirDown; + } + if (data.ipModeTrainDirHeadUp != null) { + message.ipModeTrainDirHeadUp = data.ipModeTrainDirHeadUp; + } + if (data.ipModeTrainDirHeadDown != null) { + message.ipModeTrainDirHeadDown = data.ipModeTrainDirHeadDown; + } + if (data.ipModeTrainDoorOpen != null) { + message.ipModeTrainDoorOpen = data.ipModeTrainDoorOpen; + } + if (data.ipModeTrainRsAlarm != null) { + message.ipModeTrainRsAlarm = data.ipModeTrainRsAlarm; + } + if (data.ipModeTrainDoorAlarm != null) { + message.ipModeTrainDoorAlarm = data.ipModeTrainDoorAlarm; + } + if (data.ipModeTrainEbAlarm != null) { + message.ipModeTrainEbAlarm = data.ipModeTrainEbAlarm; + } + if (data.ipModeTrainIntegrityAlarm != null) { + message.ipModeTrainIntegrityAlarm = data.ipModeTrainIntegrityAlarm; + } + if (data.ipModeTrainDriveModeAm != null) { + message.ipModeTrainDriveModeAm = data.ipModeTrainDriveModeAm; + } + if (data.ipModeTrainDriveModeCm != null) { + message.ipModeTrainDriveModeCm = data.ipModeTrainDriveModeCm; + } + if (data.ipModeTrainDriveModeRmf != null) { + message.ipModeTrainDriveModeRmf = data.ipModeTrainDriveModeRmf; + } + if (data.ipModeTrainDriveModeDto != null) { + message.ipModeTrainDriveModeDto = data.ipModeTrainDriveModeDto; + } + if (data.ipModeTrainDriveModeAtb != null) { + message.ipModeTrainDriveModeAtb = data.ipModeTrainDriveModeAtb; + } + if (data.ipModeTrainDriveBlockAm != null) { + message.ipModeTrainDriveBlockAm = data.ipModeTrainDriveBlockAm; + } + if (data.ipModeTrainDriveBlockCm != null) { + message.ipModeTrainDriveBlockCm = data.ipModeTrainDriveBlockCm; + } + if (data.ipModeTrainDriveModeRmr != null) { + message.ipModeTrainDriveModeRmr = data.ipModeTrainDriveModeRmr; + } + if (data.ipModeTrainDriveModeWash != null) { + message.ipModeTrainDriveModeWash = data.ipModeTrainDriveModeWash; + } + if (data.id != null) { + message.id = data.id; + } + return message; + } + toObject() { + const data: { + ipModeTrainTypeManual?: boolean; + ipModeTrainTypeHead?: boolean; + ipModeTrainTypeSpecial?: boolean; + ipModeTrainTypeSchedule?: boolean; + ipModeTrainTypeRoute?: boolean; + ipModeTrainTypeShuttle?: boolean; + ipModeTrainTypeLineup?: boolean; + ipModeTrainSchdEarly?: boolean; + ipModeTrainSchdLate?: boolean; + ipModeTrainSkipstop?: boolean; + ipModeTrainCbtcMode?: boolean; + ipModeTrainAtpCut?: boolean; + ipModeTrainBerthed?: boolean; + ipModeTrainStoped?: boolean; + ipModeTrainHolded?: boolean; + ipModeTrainItama?: boolean; + ipModeTrainDirUp?: boolean; + ipModeTrainDirDown?: boolean; + ipModeTrainDirHeadUp?: boolean; + ipModeTrainDirHeadDown?: boolean; + ipModeTrainDoorOpen?: boolean; + ipModeTrainRsAlarm?: boolean; + ipModeTrainDoorAlarm?: boolean; + ipModeTrainEbAlarm?: boolean; + ipModeTrainIntegrityAlarm?: boolean; + ipModeTrainDriveModeAm?: boolean; + ipModeTrainDriveModeCm?: boolean; + ipModeTrainDriveModeRmf?: boolean; + ipModeTrainDriveModeDto?: boolean; + ipModeTrainDriveModeAtb?: boolean; + ipModeTrainDriveBlockAm?: boolean; + ipModeTrainDriveBlockCm?: boolean; + ipModeTrainDriveModeRmr?: boolean; + ipModeTrainDriveModeWash?: boolean; + id?: string; + } = {}; + if (this.ipModeTrainTypeManual != null) { + data.ipModeTrainTypeManual = this.ipModeTrainTypeManual; + } + if (this.ipModeTrainTypeHead != null) { + data.ipModeTrainTypeHead = this.ipModeTrainTypeHead; + } + if (this.ipModeTrainTypeSpecial != null) { + data.ipModeTrainTypeSpecial = this.ipModeTrainTypeSpecial; + } + if (this.ipModeTrainTypeSchedule != null) { + data.ipModeTrainTypeSchedule = this.ipModeTrainTypeSchedule; + } + if (this.ipModeTrainTypeRoute != null) { + data.ipModeTrainTypeRoute = this.ipModeTrainTypeRoute; + } + if (this.ipModeTrainTypeShuttle != null) { + data.ipModeTrainTypeShuttle = this.ipModeTrainTypeShuttle; + } + if (this.ipModeTrainTypeLineup != null) { + data.ipModeTrainTypeLineup = this.ipModeTrainTypeLineup; + } + if (this.ipModeTrainSchdEarly != null) { + data.ipModeTrainSchdEarly = this.ipModeTrainSchdEarly; + } + if (this.ipModeTrainSchdLate != null) { + data.ipModeTrainSchdLate = this.ipModeTrainSchdLate; + } + if (this.ipModeTrainSkipstop != null) { + data.ipModeTrainSkipstop = this.ipModeTrainSkipstop; + } + if (this.ipModeTrainCbtcMode != null) { + data.ipModeTrainCbtcMode = this.ipModeTrainCbtcMode; + } + if (this.ipModeTrainAtpCut != null) { + data.ipModeTrainAtpCut = this.ipModeTrainAtpCut; + } + if (this.ipModeTrainBerthed != null) { + data.ipModeTrainBerthed = this.ipModeTrainBerthed; + } + if (this.ipModeTrainStoped != null) { + data.ipModeTrainStoped = this.ipModeTrainStoped; + } + if (this.ipModeTrainHolded != null) { + data.ipModeTrainHolded = this.ipModeTrainHolded; + } + if (this.ipModeTrainItama != null) { + data.ipModeTrainItama = this.ipModeTrainItama; + } + if (this.ipModeTrainDirUp != null) { + data.ipModeTrainDirUp = this.ipModeTrainDirUp; + } + if (this.ipModeTrainDirDown != null) { + data.ipModeTrainDirDown = this.ipModeTrainDirDown; + } + if (this.ipModeTrainDirHeadUp != null) { + data.ipModeTrainDirHeadUp = this.ipModeTrainDirHeadUp; + } + if (this.ipModeTrainDirHeadDown != null) { + data.ipModeTrainDirHeadDown = this.ipModeTrainDirHeadDown; + } + if (this.ipModeTrainDoorOpen != null) { + data.ipModeTrainDoorOpen = this.ipModeTrainDoorOpen; + } + if (this.ipModeTrainRsAlarm != null) { + data.ipModeTrainRsAlarm = this.ipModeTrainRsAlarm; + } + if (this.ipModeTrainDoorAlarm != null) { + data.ipModeTrainDoorAlarm = this.ipModeTrainDoorAlarm; + } + if (this.ipModeTrainEbAlarm != null) { + data.ipModeTrainEbAlarm = this.ipModeTrainEbAlarm; + } + if (this.ipModeTrainIntegrityAlarm != null) { + data.ipModeTrainIntegrityAlarm = this.ipModeTrainIntegrityAlarm; + } + if (this.ipModeTrainDriveModeAm != null) { + data.ipModeTrainDriveModeAm = this.ipModeTrainDriveModeAm; + } + if (this.ipModeTrainDriveModeCm != null) { + data.ipModeTrainDriveModeCm = this.ipModeTrainDriveModeCm; + } + if (this.ipModeTrainDriveModeRmf != null) { + data.ipModeTrainDriveModeRmf = this.ipModeTrainDriveModeRmf; + } + if (this.ipModeTrainDriveModeDto != null) { + data.ipModeTrainDriveModeDto = this.ipModeTrainDriveModeDto; + } + if (this.ipModeTrainDriveModeAtb != null) { + data.ipModeTrainDriveModeAtb = this.ipModeTrainDriveModeAtb; + } + if (this.ipModeTrainDriveBlockAm != null) { + data.ipModeTrainDriveBlockAm = this.ipModeTrainDriveBlockAm; + } + if (this.ipModeTrainDriveBlockCm != null) { + data.ipModeTrainDriveBlockCm = this.ipModeTrainDriveBlockCm; + } + if (this.ipModeTrainDriveModeRmr != null) { + data.ipModeTrainDriveModeRmr = this.ipModeTrainDriveModeRmr; + } + if (this.ipModeTrainDriveModeWash != null) { + data.ipModeTrainDriveModeWash = this.ipModeTrainDriveModeWash; + } + if (this.id != null) { + data.id = this.id; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.ipModeTrainTypeManual != false) + writer.writeBool(1, this.ipModeTrainTypeManual); + if (this.ipModeTrainTypeHead != false) + writer.writeBool(2, this.ipModeTrainTypeHead); + if (this.ipModeTrainTypeSpecial != false) + writer.writeBool(3, this.ipModeTrainTypeSpecial); + if (this.ipModeTrainTypeSchedule != false) + writer.writeBool(4, this.ipModeTrainTypeSchedule); + if (this.ipModeTrainTypeRoute != false) + writer.writeBool(5, this.ipModeTrainTypeRoute); + if (this.ipModeTrainTypeShuttle != false) + writer.writeBool(6, this.ipModeTrainTypeShuttle); + if (this.ipModeTrainTypeLineup != false) + writer.writeBool(7, this.ipModeTrainTypeLineup); + if (this.ipModeTrainSchdEarly != false) + writer.writeBool(8, this.ipModeTrainSchdEarly); + if (this.ipModeTrainSchdLate != false) + writer.writeBool(9, this.ipModeTrainSchdLate); + if (this.ipModeTrainSkipstop != false) + writer.writeBool(10, this.ipModeTrainSkipstop); + if (this.ipModeTrainCbtcMode != false) + writer.writeBool(11, this.ipModeTrainCbtcMode); + if (this.ipModeTrainAtpCut != false) + writer.writeBool(12, this.ipModeTrainAtpCut); + if (this.ipModeTrainBerthed != false) + writer.writeBool(13, this.ipModeTrainBerthed); + if (this.ipModeTrainStoped != false) + writer.writeBool(14, this.ipModeTrainStoped); + if (this.ipModeTrainHolded != false) + writer.writeBool(15, this.ipModeTrainHolded); + if (this.ipModeTrainItama != false) + writer.writeBool(16, this.ipModeTrainItama); + if (this.ipModeTrainDirUp != false) + writer.writeBool(17, this.ipModeTrainDirUp); + if (this.ipModeTrainDirDown != false) + writer.writeBool(18, this.ipModeTrainDirDown); + if (this.ipModeTrainDirHeadUp != false) + writer.writeBool(19, this.ipModeTrainDirHeadUp); + if (this.ipModeTrainDirHeadDown != false) + writer.writeBool(20, this.ipModeTrainDirHeadDown); + if (this.ipModeTrainDoorOpen != false) + writer.writeBool(21, this.ipModeTrainDoorOpen); + if (this.ipModeTrainRsAlarm != false) + writer.writeBool(22, this.ipModeTrainRsAlarm); + if (this.ipModeTrainDoorAlarm != false) + writer.writeBool(23, this.ipModeTrainDoorAlarm); + if (this.ipModeTrainEbAlarm != false) + writer.writeBool(24, this.ipModeTrainEbAlarm); + if (this.ipModeTrainIntegrityAlarm != false) + writer.writeBool(25, this.ipModeTrainIntegrityAlarm); + if (this.ipModeTrainDriveModeAm != false) + writer.writeBool(26, this.ipModeTrainDriveModeAm); + if (this.ipModeTrainDriveModeCm != false) + writer.writeBool(27, this.ipModeTrainDriveModeCm); + if (this.ipModeTrainDriveModeRmf != false) + writer.writeBool(28, this.ipModeTrainDriveModeRmf); + if (this.ipModeTrainDriveModeDto != false) + writer.writeBool(29, this.ipModeTrainDriveModeDto); + if (this.ipModeTrainDriveModeAtb != false) + writer.writeBool(30, this.ipModeTrainDriveModeAtb); + if (this.ipModeTrainDriveBlockAm != false) + writer.writeBool(31, this.ipModeTrainDriveBlockAm); + if (this.ipModeTrainDriveBlockCm != false) + writer.writeBool(32, this.ipModeTrainDriveBlockCm); + if (this.ipModeTrainDriveModeRmr != false) + writer.writeBool(33, this.ipModeTrainDriveModeRmr); + if (this.ipModeTrainDriveModeWash != false) + writer.writeBool(34, this.ipModeTrainDriveModeWash); + if (this.id.length) + writer.writeString(35, this.id); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): TrainMode { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new TrainMode(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.ipModeTrainTypeManual = reader.readBool(); + break; + case 2: + message.ipModeTrainTypeHead = reader.readBool(); + break; + case 3: + message.ipModeTrainTypeSpecial = reader.readBool(); + break; + case 4: + message.ipModeTrainTypeSchedule = reader.readBool(); + break; + case 5: + message.ipModeTrainTypeRoute = reader.readBool(); + break; + case 6: + message.ipModeTrainTypeShuttle = reader.readBool(); + break; + case 7: + message.ipModeTrainTypeLineup = reader.readBool(); + break; + case 8: + message.ipModeTrainSchdEarly = reader.readBool(); + break; + case 9: + message.ipModeTrainSchdLate = reader.readBool(); + break; + case 10: + message.ipModeTrainSkipstop = reader.readBool(); + break; + case 11: + message.ipModeTrainCbtcMode = reader.readBool(); + break; + case 12: + message.ipModeTrainAtpCut = reader.readBool(); + break; + case 13: + message.ipModeTrainBerthed = reader.readBool(); + break; + case 14: + message.ipModeTrainStoped = reader.readBool(); + break; + case 15: + message.ipModeTrainHolded = reader.readBool(); + break; + case 16: + message.ipModeTrainItama = reader.readBool(); + break; + case 17: + message.ipModeTrainDirUp = reader.readBool(); + break; + case 18: + message.ipModeTrainDirDown = reader.readBool(); + break; + case 19: + message.ipModeTrainDirHeadUp = reader.readBool(); + break; + case 20: + message.ipModeTrainDirHeadDown = reader.readBool(); + break; + case 21: + message.ipModeTrainDoorOpen = reader.readBool(); + break; + case 22: + message.ipModeTrainRsAlarm = reader.readBool(); + break; + case 23: + message.ipModeTrainDoorAlarm = reader.readBool(); + break; + case 24: + message.ipModeTrainEbAlarm = reader.readBool(); + break; + case 25: + message.ipModeTrainIntegrityAlarm = reader.readBool(); + break; + case 26: + message.ipModeTrainDriveModeAm = reader.readBool(); + break; + case 27: + message.ipModeTrainDriveModeCm = reader.readBool(); + break; + case 28: + message.ipModeTrainDriveModeRmf = reader.readBool(); + break; + case 29: + message.ipModeTrainDriveModeDto = reader.readBool(); + break; + case 30: + message.ipModeTrainDriveModeAtb = reader.readBool(); + break; + case 31: + message.ipModeTrainDriveBlockAm = reader.readBool(); + break; + case 32: + message.ipModeTrainDriveBlockCm = reader.readBool(); + break; + case 33: + message.ipModeTrainDriveModeRmr = reader.readBool(); + break; + case 34: + message.ipModeTrainDriveModeWash = reader.readBool(); + break; + case 35: + message.id = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): TrainMode { + return TrainMode.deserialize(bytes); + } + } + export class OccNccFepNetwork extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + id?: string; + active?: boolean; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + if ("active" in data && data.active != undefined) { + this.active = data.active; + } + } + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 1, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 1, value); + } + get active() { + return pb_1.Message.getFieldWithDefault(this, 2, false) as boolean; + } + set active(value: boolean) { + pb_1.Message.setField(this, 2, value); + } + static fromObject(data: { + id?: string; + active?: boolean; + }): OccNccFepNetwork { + const message = new OccNccFepNetwork({}); + if (data.id != null) { + message.id = data.id; + } + if (data.active != null) { + message.active = data.active; + } + return message; + } + toObject() { + const data: { + id?: string; + active?: boolean; + } = {}; + if (this.id != null) { + data.id = this.id; + } + if (this.active != null) { + data.active = this.active; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.id.length) + writer.writeString(1, this.id); + if (this.active != false) + writer.writeBool(2, this.active); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): OccNccFepNetwork { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new OccNccFepNetwork(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.id = reader.readString(); + break; + case 2: + message.active = reader.readBool(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): OccNccFepNetwork { + return OccNccFepNetwork.deserialize(bytes); + } + } +} diff --git a/src/protos/section_status.ts b/src/protos/section_status.ts new file mode 100644 index 0000000..8a6a587 --- /dev/null +++ b/src/protos/section_status.ts @@ -0,0 +1,219 @@ +/** + * Generated by the protoc-gen-ts. DO NOT EDIT! + * compiler version: 4.23.1 + * source: section_status.proto + * git: https://github.com/thesayyn/protoc-gen-ts */ +import * as pb_1 from "google-protobuf"; +export namespace state { + export class Section extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + code?: string; + leftSection?: Section; + rightSection?: Section; + axleCounter?: boolean; + logicList?: Section[]; + leftKilometerCode?: string; + rightKilometerCode?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [5], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("leftSection" in data && data.leftSection != undefined) { + this.leftSection = data.leftSection; + } + if ("rightSection" in data && data.rightSection != undefined) { + this.rightSection = data.rightSection; + } + if ("axleCounter" in data && data.axleCounter != undefined) { + this.axleCounter = data.axleCounter; + } + if ("logicList" in data && data.logicList != undefined) { + this.logicList = data.logicList; + } + if ("leftKilometerCode" in data && data.leftKilometerCode != undefined) { + this.leftKilometerCode = data.leftKilometerCode; + } + if ("rightKilometerCode" in data && data.rightKilometerCode != undefined) { + this.rightKilometerCode = data.rightKilometerCode; + } + } + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 1, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 1, value); + } + get leftSection() { + return pb_1.Message.getWrapperField(this, Section, 2) as Section; + } + set leftSection(value: Section) { + pb_1.Message.setWrapperField(this, 2, value); + } + get has_leftSection() { + return pb_1.Message.getField(this, 2) != null; + } + get rightSection() { + return pb_1.Message.getWrapperField(this, Section, 3) as Section; + } + set rightSection(value: Section) { + pb_1.Message.setWrapperField(this, 3, value); + } + get has_rightSection() { + return pb_1.Message.getField(this, 3) != null; + } + get axleCounter() { + return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean; + } + set axleCounter(value: boolean) { + pb_1.Message.setField(this, 4, value); + } + get logicList() { + return pb_1.Message.getRepeatedWrapperField(this, Section, 5) as Section[]; + } + set logicList(value: Section[]) { + pb_1.Message.setRepeatedWrapperField(this, 5, value); + } + get leftKilometerCode() { + return pb_1.Message.getFieldWithDefault(this, 6, "") as string; + } + set leftKilometerCode(value: string) { + pb_1.Message.setField(this, 6, value); + } + get rightKilometerCode() { + return pb_1.Message.getFieldWithDefault(this, 7, "") as string; + } + set rightKilometerCode(value: string) { + pb_1.Message.setField(this, 7, value); + } + static fromObject(data: { + code?: string; + leftSection?: ReturnType; + rightSection?: ReturnType; + axleCounter?: boolean; + logicList?: ReturnType[]; + leftKilometerCode?: string; + rightKilometerCode?: string; + }): Section { + const message = new Section({}); + if (data.code != null) { + message.code = data.code; + } + if (data.leftSection != null) { + message.leftSection = Section.fromObject(data.leftSection); + } + if (data.rightSection != null) { + message.rightSection = Section.fromObject(data.rightSection); + } + if (data.axleCounter != null) { + message.axleCounter = data.axleCounter; + } + if (data.logicList != null) { + message.logicList = data.logicList.map(item => Section.fromObject(item)); + } + if (data.leftKilometerCode != null) { + message.leftKilometerCode = data.leftKilometerCode; + } + if (data.rightKilometerCode != null) { + message.rightKilometerCode = data.rightKilometerCode; + } + return message; + } + toObject() { + const data: { + code?: string; + leftSection?: ReturnType; + rightSection?: ReturnType; + axleCounter?: boolean; + logicList?: ReturnType[]; + leftKilometerCode?: string; + rightKilometerCode?: string; + } = {}; + if (this.code != null) { + data.code = this.code; + } + if (this.leftSection != null) { + data.leftSection = this.leftSection.toObject(); + } + if (this.rightSection != null) { + data.rightSection = this.rightSection.toObject(); + } + if (this.axleCounter != null) { + data.axleCounter = this.axleCounter; + } + if (this.logicList != null) { + data.logicList = this.logicList.map((item: Section) => item.toObject()); + } + if (this.leftKilometerCode != null) { + data.leftKilometerCode = this.leftKilometerCode; + } + if (this.rightKilometerCode != null) { + data.rightKilometerCode = this.rightKilometerCode; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.code.length) + writer.writeString(1, this.code); + if (this.has_leftSection) + writer.writeMessage(2, this.leftSection, () => this.leftSection.serialize(writer)); + if (this.has_rightSection) + writer.writeMessage(3, this.rightSection, () => this.rightSection.serialize(writer)); + if (this.axleCounter != false) + writer.writeBool(4, this.axleCounter); + if (this.logicList.length) + writer.writeRepeatedMessage(5, this.logicList, (item: Section) => item.serialize(writer)); + if (this.leftKilometerCode.length) + writer.writeString(6, this.leftKilometerCode); + if (this.rightKilometerCode.length) + writer.writeString(7, this.rightKilometerCode); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Section { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Section(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.code = reader.readString(); + break; + case 2: + reader.readMessage(message.leftSection, () => message.leftSection = Section.deserialize(reader)); + break; + case 3: + reader.readMessage(message.rightSection, () => message.rightSection = Section.deserialize(reader)); + break; + case 4: + message.axleCounter = reader.readBool(); + break; + case 5: + reader.readMessage(message.logicList, () => pb_1.Message.addToRepeatedWrapperField(message, 5, Section.deserialize(reader), Section)); + break; + case 6: + message.leftKilometerCode = reader.readString(); + break; + case 7: + message.rightKilometerCode = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Section { + return Section.deserialize(bytes); + } + } +} diff --git a/src/protos/stationLayoutGraphics.ts b/src/protos/stationLayoutGraphics.ts new file mode 100644 index 0000000..5beab30 --- /dev/null +++ b/src/protos/stationLayoutGraphics.ts @@ -0,0 +1,4126 @@ +/** + * Generated by the protoc-gen-ts. DO NOT EDIT! + * compiler version: 4.23.1 + * source: stationLayoutGraphics.proto + * git: https://github.com/thesayyn/protoc-gen-ts */ +import * as pb_1 from "google-protobuf"; +export namespace graphicData { + export class RtssGraphicStorage extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + canvas?: Canvas; + links?: Link[]; + iscsFans?: IscsFan[]; + Platforms?: Platform[]; + stations?: Station[]; + rects?: Rect[]; + train?: Train[]; + signals?: Signal[]; + turnouts?: Turnout[]; + section?: Section[]; + stationLines?: StationLine[]; + runLines?: RunLine[]; + trainLines?: TrainLine[]; + pathLines?: PathLine[]; + polygons?: Polygon[]; + trainWindows?: TrainWindow[]; + axleCountings?: AxleCounting[]; + separators?: Separator[]; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("canvas" in data && data.canvas != undefined) { + this.canvas = data.canvas; + } + if ("links" in data && data.links != undefined) { + this.links = data.links; + } + if ("iscsFans" in data && data.iscsFans != undefined) { + this.iscsFans = data.iscsFans; + } + if ("Platforms" in data && data.Platforms != undefined) { + this.Platforms = data.Platforms; + } + if ("stations" in data && data.stations != undefined) { + this.stations = data.stations; + } + if ("rects" in data && data.rects != undefined) { + this.rects = data.rects; + } + if ("train" in data && data.train != undefined) { + this.train = data.train; + } + if ("signals" in data && data.signals != undefined) { + this.signals = data.signals; + } + if ("turnouts" in data && data.turnouts != undefined) { + this.turnouts = data.turnouts; + } + if ("section" in data && data.section != undefined) { + this.section = data.section; + } + if ("stationLines" in data && data.stationLines != undefined) { + this.stationLines = data.stationLines; + } + if ("runLines" in data && data.runLines != undefined) { + this.runLines = data.runLines; + } + if ("trainLines" in data && data.trainLines != undefined) { + this.trainLines = data.trainLines; + } + if ("pathLines" in data && data.pathLines != undefined) { + this.pathLines = data.pathLines; + } + if ("polygons" in data && data.polygons != undefined) { + this.polygons = data.polygons; + } + if ("trainWindows" in data && data.trainWindows != undefined) { + this.trainWindows = data.trainWindows; + } + if ("axleCountings" in data && data.axleCountings != undefined) { + this.axleCountings = data.axleCountings; + } + if ("separators" in data && data.separators != undefined) { + this.separators = data.separators; + } + } + } + get canvas() { + return pb_1.Message.getWrapperField(this, Canvas, 1) as Canvas; + } + set canvas(value: Canvas) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_canvas() { + return pb_1.Message.getField(this, 1) != null; + } + get links() { + return pb_1.Message.getRepeatedWrapperField(this, Link, 2) as Link[]; + } + set links(value: Link[]) { + pb_1.Message.setRepeatedWrapperField(this, 2, value); + } + get iscsFans() { + return pb_1.Message.getRepeatedWrapperField(this, IscsFan, 3) as IscsFan[]; + } + set iscsFans(value: IscsFan[]) { + pb_1.Message.setRepeatedWrapperField(this, 3, value); + } + get Platforms() { + return pb_1.Message.getRepeatedWrapperField(this, Platform, 4) as Platform[]; + } + set Platforms(value: Platform[]) { + pb_1.Message.setRepeatedWrapperField(this, 4, value); + } + get stations() { + return pb_1.Message.getRepeatedWrapperField(this, Station, 5) as Station[]; + } + set stations(value: Station[]) { + pb_1.Message.setRepeatedWrapperField(this, 5, value); + } + get rects() { + return pb_1.Message.getRepeatedWrapperField(this, Rect, 6) as Rect[]; + } + set rects(value: Rect[]) { + pb_1.Message.setRepeatedWrapperField(this, 6, value); + } + get train() { + return pb_1.Message.getRepeatedWrapperField(this, Train, 7) as Train[]; + } + set train(value: Train[]) { + pb_1.Message.setRepeatedWrapperField(this, 7, value); + } + get signals() { + return pb_1.Message.getRepeatedWrapperField(this, Signal, 8) as Signal[]; + } + set signals(value: Signal[]) { + pb_1.Message.setRepeatedWrapperField(this, 8, value); + } + get turnouts() { + return pb_1.Message.getRepeatedWrapperField(this, Turnout, 9) as Turnout[]; + } + set turnouts(value: Turnout[]) { + pb_1.Message.setRepeatedWrapperField(this, 9, value); + } + get section() { + return pb_1.Message.getRepeatedWrapperField(this, Section, 10) as Section[]; + } + set section(value: Section[]) { + pb_1.Message.setRepeatedWrapperField(this, 10, value); + } + get stationLines() { + return pb_1.Message.getRepeatedWrapperField(this, StationLine, 11) as StationLine[]; + } + set stationLines(value: StationLine[]) { + pb_1.Message.setRepeatedWrapperField(this, 11, value); + } + get runLines() { + return pb_1.Message.getRepeatedWrapperField(this, RunLine, 12) as RunLine[]; + } + set runLines(value: RunLine[]) { + pb_1.Message.setRepeatedWrapperField(this, 12, value); + } + get trainLines() { + return pb_1.Message.getRepeatedWrapperField(this, TrainLine, 13) as TrainLine[]; + } + set trainLines(value: TrainLine[]) { + pb_1.Message.setRepeatedWrapperField(this, 13, value); + } + get pathLines() { + return pb_1.Message.getRepeatedWrapperField(this, PathLine, 14) as PathLine[]; + } + set pathLines(value: PathLine[]) { + pb_1.Message.setRepeatedWrapperField(this, 14, value); + } + get polygons() { + return pb_1.Message.getRepeatedWrapperField(this, Polygon, 15) as Polygon[]; + } + set polygons(value: Polygon[]) { + pb_1.Message.setRepeatedWrapperField(this, 15, value); + } + get trainWindows() { + return pb_1.Message.getRepeatedWrapperField(this, TrainWindow, 16) as TrainWindow[]; + } + set trainWindows(value: TrainWindow[]) { + pb_1.Message.setRepeatedWrapperField(this, 16, value); + } + get axleCountings() { + return pb_1.Message.getRepeatedWrapperField(this, AxleCounting, 17) as AxleCounting[]; + } + set axleCountings(value: AxleCounting[]) { + pb_1.Message.setRepeatedWrapperField(this, 17, value); + } + get separators() { + return pb_1.Message.getRepeatedWrapperField(this, Separator, 18) as Separator[]; + } + set separators(value: Separator[]) { + pb_1.Message.setRepeatedWrapperField(this, 18, value); + } + static fromObject(data: { + canvas?: ReturnType; + links?: ReturnType[]; + iscsFans?: ReturnType[]; + Platforms?: ReturnType[]; + stations?: ReturnType[]; + rects?: ReturnType[]; + train?: ReturnType[]; + signals?: ReturnType[]; + turnouts?: ReturnType[]; + section?: ReturnType[]; + stationLines?: ReturnType[]; + runLines?: ReturnType[]; + trainLines?: ReturnType[]; + pathLines?: ReturnType[]; + polygons?: ReturnType[]; + trainWindows?: ReturnType[]; + axleCountings?: ReturnType[]; + separators?: ReturnType[]; + }): RtssGraphicStorage { + const message = new RtssGraphicStorage({}); + if (data.canvas != null) { + message.canvas = Canvas.fromObject(data.canvas); + } + if (data.links != null) { + message.links = data.links.map(item => Link.fromObject(item)); + } + if (data.iscsFans != null) { + message.iscsFans = data.iscsFans.map(item => IscsFan.fromObject(item)); + } + if (data.Platforms != null) { + message.Platforms = data.Platforms.map(item => Platform.fromObject(item)); + } + if (data.stations != null) { + message.stations = data.stations.map(item => Station.fromObject(item)); + } + if (data.rects != null) { + message.rects = data.rects.map(item => Rect.fromObject(item)); + } + if (data.train != null) { + message.train = data.train.map(item => Train.fromObject(item)); + } + if (data.signals != null) { + message.signals = data.signals.map(item => Signal.fromObject(item)); + } + if (data.turnouts != null) { + message.turnouts = data.turnouts.map(item => Turnout.fromObject(item)); + } + if (data.section != null) { + message.section = data.section.map(item => Section.fromObject(item)); + } + if (data.stationLines != null) { + message.stationLines = data.stationLines.map(item => StationLine.fromObject(item)); + } + if (data.runLines != null) { + message.runLines = data.runLines.map(item => RunLine.fromObject(item)); + } + if (data.trainLines != null) { + message.trainLines = data.trainLines.map(item => TrainLine.fromObject(item)); + } + if (data.pathLines != null) { + message.pathLines = data.pathLines.map(item => PathLine.fromObject(item)); + } + if (data.polygons != null) { + message.polygons = data.polygons.map(item => Polygon.fromObject(item)); + } + if (data.trainWindows != null) { + message.trainWindows = data.trainWindows.map(item => TrainWindow.fromObject(item)); + } + if (data.axleCountings != null) { + message.axleCountings = data.axleCountings.map(item => AxleCounting.fromObject(item)); + } + if (data.separators != null) { + message.separators = data.separators.map(item => Separator.fromObject(item)); + } + return message; + } + toObject() { + const data: { + canvas?: ReturnType; + links?: ReturnType[]; + iscsFans?: ReturnType[]; + Platforms?: ReturnType[]; + stations?: ReturnType[]; + rects?: ReturnType[]; + train?: ReturnType[]; + signals?: ReturnType[]; + turnouts?: ReturnType[]; + section?: ReturnType[]; + stationLines?: ReturnType[]; + runLines?: ReturnType[]; + trainLines?: ReturnType[]; + pathLines?: ReturnType[]; + polygons?: ReturnType[]; + trainWindows?: ReturnType[]; + axleCountings?: ReturnType[]; + separators?: ReturnType[]; + } = {}; + if (this.canvas != null) { + data.canvas = this.canvas.toObject(); + } + if (this.links != null) { + data.links = this.links.map((item: Link) => item.toObject()); + } + if (this.iscsFans != null) { + data.iscsFans = this.iscsFans.map((item: IscsFan) => item.toObject()); + } + if (this.Platforms != null) { + data.Platforms = this.Platforms.map((item: Platform) => item.toObject()); + } + if (this.stations != null) { + data.stations = this.stations.map((item: Station) => item.toObject()); + } + if (this.rects != null) { + data.rects = this.rects.map((item: Rect) => item.toObject()); + } + if (this.train != null) { + data.train = this.train.map((item: Train) => item.toObject()); + } + if (this.signals != null) { + data.signals = this.signals.map((item: Signal) => item.toObject()); + } + if (this.turnouts != null) { + data.turnouts = this.turnouts.map((item: Turnout) => item.toObject()); + } + if (this.section != null) { + data.section = this.section.map((item: Section) => item.toObject()); + } + if (this.stationLines != null) { + data.stationLines = this.stationLines.map((item: StationLine) => item.toObject()); + } + if (this.runLines != null) { + data.runLines = this.runLines.map((item: RunLine) => item.toObject()); + } + if (this.trainLines != null) { + data.trainLines = this.trainLines.map((item: TrainLine) => item.toObject()); + } + if (this.pathLines != null) { + data.pathLines = this.pathLines.map((item: PathLine) => item.toObject()); + } + if (this.polygons != null) { + data.polygons = this.polygons.map((item: Polygon) => item.toObject()); + } + if (this.trainWindows != null) { + data.trainWindows = this.trainWindows.map((item: TrainWindow) => item.toObject()); + } + if (this.axleCountings != null) { + data.axleCountings = this.axleCountings.map((item: AxleCounting) => item.toObject()); + } + if (this.separators != null) { + data.separators = this.separators.map((item: Separator) => item.toObject()); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_canvas) + writer.writeMessage(1, this.canvas, () => this.canvas.serialize(writer)); + if (this.links.length) + writer.writeRepeatedMessage(2, this.links, (item: Link) => item.serialize(writer)); + if (this.iscsFans.length) + writer.writeRepeatedMessage(3, this.iscsFans, (item: IscsFan) => item.serialize(writer)); + if (this.Platforms.length) + writer.writeRepeatedMessage(4, this.Platforms, (item: Platform) => item.serialize(writer)); + if (this.stations.length) + writer.writeRepeatedMessage(5, this.stations, (item: Station) => item.serialize(writer)); + if (this.rects.length) + writer.writeRepeatedMessage(6, this.rects, (item: Rect) => item.serialize(writer)); + if (this.train.length) + writer.writeRepeatedMessage(7, this.train, (item: Train) => item.serialize(writer)); + if (this.signals.length) + writer.writeRepeatedMessage(8, this.signals, (item: Signal) => item.serialize(writer)); + if (this.turnouts.length) + writer.writeRepeatedMessage(9, this.turnouts, (item: Turnout) => item.serialize(writer)); + if (this.section.length) + writer.writeRepeatedMessage(10, this.section, (item: Section) => item.serialize(writer)); + if (this.stationLines.length) + writer.writeRepeatedMessage(11, this.stationLines, (item: StationLine) => item.serialize(writer)); + if (this.runLines.length) + writer.writeRepeatedMessage(12, this.runLines, (item: RunLine) => item.serialize(writer)); + if (this.trainLines.length) + writer.writeRepeatedMessage(13, this.trainLines, (item: TrainLine) => item.serialize(writer)); + if (this.pathLines.length) + writer.writeRepeatedMessage(14, this.pathLines, (item: PathLine) => item.serialize(writer)); + if (this.polygons.length) + writer.writeRepeatedMessage(15, this.polygons, (item: Polygon) => item.serialize(writer)); + if (this.trainWindows.length) + writer.writeRepeatedMessage(16, this.trainWindows, (item: TrainWindow) => item.serialize(writer)); + if (this.axleCountings.length) + writer.writeRepeatedMessage(17, this.axleCountings, (item: AxleCounting) => item.serialize(writer)); + if (this.separators.length) + writer.writeRepeatedMessage(18, this.separators, (item: Separator) => item.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): RtssGraphicStorage { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new RtssGraphicStorage(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.canvas, () => message.canvas = Canvas.deserialize(reader)); + break; + case 2: + reader.readMessage(message.links, () => pb_1.Message.addToRepeatedWrapperField(message, 2, Link.deserialize(reader), Link)); + break; + case 3: + reader.readMessage(message.iscsFans, () => pb_1.Message.addToRepeatedWrapperField(message, 3, IscsFan.deserialize(reader), IscsFan)); + break; + case 4: + reader.readMessage(message.Platforms, () => pb_1.Message.addToRepeatedWrapperField(message, 4, Platform.deserialize(reader), Platform)); + break; + case 5: + reader.readMessage(message.stations, () => pb_1.Message.addToRepeatedWrapperField(message, 5, Station.deserialize(reader), Station)); + break; + case 6: + reader.readMessage(message.rects, () => pb_1.Message.addToRepeatedWrapperField(message, 6, Rect.deserialize(reader), Rect)); + break; + case 7: + reader.readMessage(message.train, () => pb_1.Message.addToRepeatedWrapperField(message, 7, Train.deserialize(reader), Train)); + break; + case 8: + reader.readMessage(message.signals, () => pb_1.Message.addToRepeatedWrapperField(message, 8, Signal.deserialize(reader), Signal)); + break; + case 9: + reader.readMessage(message.turnouts, () => pb_1.Message.addToRepeatedWrapperField(message, 9, Turnout.deserialize(reader), Turnout)); + break; + case 10: + reader.readMessage(message.section, () => pb_1.Message.addToRepeatedWrapperField(message, 10, Section.deserialize(reader), Section)); + break; + case 11: + reader.readMessage(message.stationLines, () => pb_1.Message.addToRepeatedWrapperField(message, 11, StationLine.deserialize(reader), StationLine)); + break; + case 12: + reader.readMessage(message.runLines, () => pb_1.Message.addToRepeatedWrapperField(message, 12, RunLine.deserialize(reader), RunLine)); + break; + case 13: + reader.readMessage(message.trainLines, () => pb_1.Message.addToRepeatedWrapperField(message, 13, TrainLine.deserialize(reader), TrainLine)); + break; + case 14: + reader.readMessage(message.pathLines, () => pb_1.Message.addToRepeatedWrapperField(message, 14, PathLine.deserialize(reader), PathLine)); + break; + case 15: + reader.readMessage(message.polygons, () => pb_1.Message.addToRepeatedWrapperField(message, 15, Polygon.deserialize(reader), Polygon)); + break; + case 16: + reader.readMessage(message.trainWindows, () => pb_1.Message.addToRepeatedWrapperField(message, 16, TrainWindow.deserialize(reader), TrainWindow)); + break; + case 17: + reader.readMessage(message.axleCountings, () => pb_1.Message.addToRepeatedWrapperField(message, 17, AxleCounting.deserialize(reader), AxleCounting)); + break; + case 18: + reader.readMessage(message.separators, () => pb_1.Message.addToRepeatedWrapperField(message, 18, Separator.deserialize(reader), Separator)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): RtssGraphicStorage { + return RtssGraphicStorage.deserialize(bytes); + } + } + export class Canvas extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + width?: number; + height?: number; + backgroundColor?: string; + viewportTransform?: Transform; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("width" in data && data.width != undefined) { + this.width = data.width; + } + if ("height" in data && data.height != undefined) { + this.height = data.height; + } + if ("backgroundColor" in data && data.backgroundColor != undefined) { + this.backgroundColor = data.backgroundColor; + } + if ("viewportTransform" in data && data.viewportTransform != undefined) { + this.viewportTransform = data.viewportTransform; + } + } + } + get width() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set width(value: number) { + pb_1.Message.setField(this, 1, value); + } + get height() { + return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; + } + set height(value: number) { + pb_1.Message.setField(this, 2, value); + } + get backgroundColor() { + return pb_1.Message.getFieldWithDefault(this, 3, "") as string; + } + set backgroundColor(value: string) { + pb_1.Message.setField(this, 3, value); + } + get viewportTransform() { + return pb_1.Message.getWrapperField(this, Transform, 4) as Transform; + } + set viewportTransform(value: Transform) { + pb_1.Message.setWrapperField(this, 4, value); + } + get has_viewportTransform() { + return pb_1.Message.getField(this, 4) != null; + } + static fromObject(data: { + width?: number; + height?: number; + backgroundColor?: string; + viewportTransform?: ReturnType; + }): Canvas { + const message = new Canvas({}); + if (data.width != null) { + message.width = data.width; + } + if (data.height != null) { + message.height = data.height; + } + if (data.backgroundColor != null) { + message.backgroundColor = data.backgroundColor; + } + if (data.viewportTransform != null) { + message.viewportTransform = Transform.fromObject(data.viewportTransform); + } + return message; + } + toObject() { + const data: { + width?: number; + height?: number; + backgroundColor?: string; + viewportTransform?: ReturnType; + } = {}; + if (this.width != null) { + data.width = this.width; + } + if (this.height != null) { + data.height = this.height; + } + if (this.backgroundColor != null) { + data.backgroundColor = this.backgroundColor; + } + if (this.viewportTransform != null) { + data.viewportTransform = this.viewportTransform.toObject(); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.width != 0) + writer.writeInt32(1, this.width); + if (this.height != 0) + writer.writeInt32(2, this.height); + if (this.backgroundColor.length) + writer.writeString(3, this.backgroundColor); + if (this.has_viewportTransform) + writer.writeMessage(4, this.viewportTransform, () => this.viewportTransform.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Canvas { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Canvas(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.width = reader.readInt32(); + break; + case 2: + message.height = reader.readInt32(); + break; + case 3: + message.backgroundColor = reader.readString(); + break; + case 4: + reader.readMessage(message.viewportTransform, () => message.viewportTransform = Transform.deserialize(reader)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Canvas { + return Canvas.deserialize(bytes); + } + } + export class Point extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + x?: number; + y?: number; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("x" in data && data.x != undefined) { + this.x = data.x; + } + if ("y" in data && data.y != undefined) { + this.y = data.y; + } + } + } + get x() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set x(value: number) { + pb_1.Message.setField(this, 1, value); + } + get y() { + return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; + } + set y(value: number) { + pb_1.Message.setField(this, 2, value); + } + static fromObject(data: { + x?: number; + y?: number; + }): Point { + const message = new Point({}); + if (data.x != null) { + message.x = data.x; + } + if (data.y != null) { + message.y = data.y; + } + return message; + } + toObject() { + const data: { + x?: number; + y?: number; + } = {}; + if (this.x != null) { + data.x = this.x; + } + if (this.y != null) { + data.y = this.y; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.x != 0) + writer.writeFloat(1, this.x); + if (this.y != 0) + writer.writeFloat(2, this.y); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Point { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Point(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.x = reader.readFloat(); + break; + case 2: + message.y = reader.readFloat(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Point { + return Point.deserialize(bytes); + } + } + export class Transform extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + position?: Point; + scale?: Point; + rotation?: number; + skew?: Point; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("position" in data && data.position != undefined) { + this.position = data.position; + } + if ("scale" in data && data.scale != undefined) { + this.scale = data.scale; + } + if ("rotation" in data && data.rotation != undefined) { + this.rotation = data.rotation; + } + if ("skew" in data && data.skew != undefined) { + this.skew = data.skew; + } + } + } + get position() { + return pb_1.Message.getWrapperField(this, Point, 1) as Point; + } + set position(value: Point) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_position() { + return pb_1.Message.getField(this, 1) != null; + } + get scale() { + return pb_1.Message.getWrapperField(this, Point, 2) as Point; + } + set scale(value: Point) { + pb_1.Message.setWrapperField(this, 2, value); + } + get has_scale() { + return pb_1.Message.getField(this, 2) != null; + } + get rotation() { + return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; + } + set rotation(value: number) { + pb_1.Message.setField(this, 3, value); + } + get skew() { + return pb_1.Message.getWrapperField(this, Point, 4) as Point; + } + set skew(value: Point) { + pb_1.Message.setWrapperField(this, 4, value); + } + get has_skew() { + return pb_1.Message.getField(this, 4) != null; + } + static fromObject(data: { + position?: ReturnType; + scale?: ReturnType; + rotation?: number; + skew?: ReturnType; + }): Transform { + const message = new Transform({}); + if (data.position != null) { + message.position = Point.fromObject(data.position); + } + if (data.scale != null) { + message.scale = Point.fromObject(data.scale); + } + if (data.rotation != null) { + message.rotation = data.rotation; + } + if (data.skew != null) { + message.skew = Point.fromObject(data.skew); + } + return message; + } + toObject() { + const data: { + position?: ReturnType; + scale?: ReturnType; + rotation?: number; + skew?: ReturnType; + } = {}; + if (this.position != null) { + data.position = this.position.toObject(); + } + if (this.scale != null) { + data.scale = this.scale.toObject(); + } + if (this.rotation != null) { + data.rotation = this.rotation; + } + if (this.skew != null) { + data.skew = this.skew.toObject(); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_position) + writer.writeMessage(1, this.position, () => this.position.serialize(writer)); + if (this.has_scale) + writer.writeMessage(2, this.scale, () => this.scale.serialize(writer)); + if (this.rotation != 0) + writer.writeFloat(3, this.rotation); + if (this.has_skew) + writer.writeMessage(4, this.skew, () => this.skew.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Transform { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Transform(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.position, () => message.position = Point.deserialize(reader)); + break; + case 2: + reader.readMessage(message.scale, () => message.scale = Point.deserialize(reader)); + break; + case 3: + message.rotation = reader.readFloat(); + break; + case 4: + reader.readMessage(message.skew, () => message.skew = Point.deserialize(reader)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Transform { + return Transform.deserialize(bytes); + } + } + export class ChildTransform extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + name?: string; + transform?: Transform; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("name" in data && data.name != undefined) { + this.name = data.name; + } + if ("transform" in data && data.transform != undefined) { + this.transform = data.transform; + } + } + } + get name() { + return pb_1.Message.getFieldWithDefault(this, 1, "") as string; + } + set name(value: string) { + pb_1.Message.setField(this, 1, value); + } + get transform() { + return pb_1.Message.getWrapperField(this, Transform, 2) as Transform; + } + set transform(value: Transform) { + pb_1.Message.setWrapperField(this, 2, value); + } + get has_transform() { + return pb_1.Message.getField(this, 2) != null; + } + static fromObject(data: { + name?: string; + transform?: ReturnType; + }): ChildTransform { + const message = new ChildTransform({}); + if (data.name != null) { + message.name = data.name; + } + if (data.transform != null) { + message.transform = Transform.fromObject(data.transform); + } + return message; + } + toObject() { + const data: { + name?: string; + transform?: ReturnType; + } = {}; + if (this.name != null) { + data.name = this.name; + } + if (this.transform != null) { + data.transform = this.transform.toObject(); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.name.length) + writer.writeString(1, this.name); + if (this.has_transform) + writer.writeMessage(2, this.transform, () => this.transform.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): ChildTransform { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new ChildTransform(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.name = reader.readString(); + break; + case 2: + reader.readMessage(message.transform, () => message.transform = Transform.deserialize(reader)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): ChildTransform { + return ChildTransform.deserialize(bytes); + } + } + export class CommonInfo extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + id?: string; + graphicType?: string; + transform?: Transform; + childTransforms?: ChildTransform[]; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [4], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + if ("graphicType" in data && data.graphicType != undefined) { + this.graphicType = data.graphicType; + } + if ("transform" in data && data.transform != undefined) { + this.transform = data.transform; + } + if ("childTransforms" in data && data.childTransforms != undefined) { + this.childTransforms = data.childTransforms; + } + } + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 1, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 1, value); + } + get graphicType() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set graphicType(value: string) { + pb_1.Message.setField(this, 2, value); + } + get transform() { + return pb_1.Message.getWrapperField(this, Transform, 3) as Transform; + } + set transform(value: Transform) { + pb_1.Message.setWrapperField(this, 3, value); + } + get has_transform() { + return pb_1.Message.getField(this, 3) != null; + } + get childTransforms() { + return pb_1.Message.getRepeatedWrapperField(this, ChildTransform, 4) as ChildTransform[]; + } + set childTransforms(value: ChildTransform[]) { + pb_1.Message.setRepeatedWrapperField(this, 4, value); + } + static fromObject(data: { + id?: string; + graphicType?: string; + transform?: ReturnType; + childTransforms?: ReturnType[]; + }): CommonInfo { + const message = new CommonInfo({}); + if (data.id != null) { + message.id = data.id; + } + if (data.graphicType != null) { + message.graphicType = data.graphicType; + } + if (data.transform != null) { + message.transform = Transform.fromObject(data.transform); + } + if (data.childTransforms != null) { + message.childTransforms = data.childTransforms.map(item => ChildTransform.fromObject(item)); + } + return message; + } + toObject() { + const data: { + id?: string; + graphicType?: string; + transform?: ReturnType; + childTransforms?: ReturnType[]; + } = {}; + if (this.id != null) { + data.id = this.id; + } + if (this.graphicType != null) { + data.graphicType = this.graphicType; + } + if (this.transform != null) { + data.transform = this.transform.toObject(); + } + if (this.childTransforms != null) { + data.childTransforms = this.childTransforms.map((item: ChildTransform) => item.toObject()); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.id.length) + writer.writeString(1, this.id); + if (this.graphicType.length) + writer.writeString(2, this.graphicType); + if (this.has_transform) + writer.writeMessage(3, this.transform, () => this.transform.serialize(writer)); + if (this.childTransforms.length) + writer.writeRepeatedMessage(4, this.childTransforms, (item: ChildTransform) => item.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): CommonInfo { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new CommonInfo(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.id = reader.readString(); + break; + case 2: + message.graphicType = reader.readString(); + break; + case 3: + reader.readMessage(message.transform, () => message.transform = Transform.deserialize(reader)); + break; + case 4: + reader.readMessage(message.childTransforms, () => pb_1.Message.addToRepeatedWrapperField(message, 4, ChildTransform.deserialize(reader), ChildTransform)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): CommonInfo { + return CommonInfo.deserialize(bytes); + } + } + export class Link extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + curve?: boolean; + segmentsCount?: number; + lineWidth?: number; + lineColor?: string; + points?: Point[]; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [7], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("curve" in data && data.curve != undefined) { + this.curve = data.curve; + } + if ("segmentsCount" in data && data.segmentsCount != undefined) { + this.segmentsCount = data.segmentsCount; + } + if ("lineWidth" in data && data.lineWidth != undefined) { + this.lineWidth = data.lineWidth; + } + if ("lineColor" in data && data.lineColor != undefined) { + this.lineColor = data.lineColor; + } + if ("points" in data && data.points != undefined) { + this.points = data.points; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get curve() { + return pb_1.Message.getFieldWithDefault(this, 3, false) as boolean; + } + set curve(value: boolean) { + pb_1.Message.setField(this, 3, value); + } + get segmentsCount() { + return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; + } + set segmentsCount(value: number) { + pb_1.Message.setField(this, 4, value); + } + get lineWidth() { + return pb_1.Message.getFieldWithDefault(this, 5, 0) as number; + } + set lineWidth(value: number) { + pb_1.Message.setField(this, 5, value); + } + get lineColor() { + return pb_1.Message.getFieldWithDefault(this, 6, "") as string; + } + set lineColor(value: string) { + pb_1.Message.setField(this, 6, value); + } + get points() { + return pb_1.Message.getRepeatedWrapperField(this, Point, 7) as Point[]; + } + set points(value: Point[]) { + pb_1.Message.setRepeatedWrapperField(this, 7, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + curve?: boolean; + segmentsCount?: number; + lineWidth?: number; + lineColor?: string; + points?: ReturnType[]; + }): Link { + const message = new Link({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.curve != null) { + message.curve = data.curve; + } + if (data.segmentsCount != null) { + message.segmentsCount = data.segmentsCount; + } + if (data.lineWidth != null) { + message.lineWidth = data.lineWidth; + } + if (data.lineColor != null) { + message.lineColor = data.lineColor; + } + if (data.points != null) { + message.points = data.points.map(item => Point.fromObject(item)); + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + curve?: boolean; + segmentsCount?: number; + lineWidth?: number; + lineColor?: string; + points?: ReturnType[]; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.curve != null) { + data.curve = this.curve; + } + if (this.segmentsCount != null) { + data.segmentsCount = this.segmentsCount; + } + if (this.lineWidth != null) { + data.lineWidth = this.lineWidth; + } + if (this.lineColor != null) { + data.lineColor = this.lineColor; + } + if (this.points != null) { + data.points = this.points.map((item: Point) => item.toObject()); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.curve != false) + writer.writeBool(3, this.curve); + if (this.segmentsCount != 0) + writer.writeInt32(4, this.segmentsCount); + if (this.lineWidth != 0) + writer.writeInt32(5, this.lineWidth); + if (this.lineColor.length) + writer.writeString(6, this.lineColor); + if (this.points.length) + writer.writeRepeatedMessage(7, this.points, (item: Point) => item.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Link { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Link(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + message.curve = reader.readBool(); + break; + case 4: + message.segmentsCount = reader.readInt32(); + break; + case 5: + message.lineWidth = reader.readInt32(); + break; + case 6: + message.lineColor = reader.readString(); + break; + case 7: + reader.readMessage(message.points, () => pb_1.Message.addToRepeatedWrapperField(message, 7, Point.deserialize(reader), Point)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Link { + return Link.deserialize(bytes); + } + } + export class Rect extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + lineWidth?: number; + lineColor?: string; + width?: number; + height?: number; + radius?: number; + point?: Point; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("lineWidth" in data && data.lineWidth != undefined) { + this.lineWidth = data.lineWidth; + } + if ("lineColor" in data && data.lineColor != undefined) { + this.lineColor = data.lineColor; + } + if ("width" in data && data.width != undefined) { + this.width = data.width; + } + if ("height" in data && data.height != undefined) { + this.height = data.height; + } + if ("radius" in data && data.radius != undefined) { + this.radius = data.radius; + } + if ("point" in data && data.point != undefined) { + this.point = data.point; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get lineWidth() { + return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; + } + set lineWidth(value: number) { + pb_1.Message.setField(this, 3, value); + } + get lineColor() { + return pb_1.Message.getFieldWithDefault(this, 4, "") as string; + } + set lineColor(value: string) { + pb_1.Message.setField(this, 4, value); + } + get width() { + return pb_1.Message.getFieldWithDefault(this, 5, 0) as number; + } + set width(value: number) { + pb_1.Message.setField(this, 5, value); + } + get height() { + return pb_1.Message.getFieldWithDefault(this, 6, 0) as number; + } + set height(value: number) { + pb_1.Message.setField(this, 6, value); + } + get radius() { + return pb_1.Message.getFieldWithDefault(this, 7, 0) as number; + } + set radius(value: number) { + pb_1.Message.setField(this, 7, value); + } + get point() { + return pb_1.Message.getWrapperField(this, Point, 8) as Point; + } + set point(value: Point) { + pb_1.Message.setWrapperField(this, 8, value); + } + get has_point() { + return pb_1.Message.getField(this, 8) != null; + } + static fromObject(data: { + common?: ReturnType; + code?: string; + lineWidth?: number; + lineColor?: string; + width?: number; + height?: number; + radius?: number; + point?: ReturnType; + }): Rect { + const message = new Rect({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.lineWidth != null) { + message.lineWidth = data.lineWidth; + } + if (data.lineColor != null) { + message.lineColor = data.lineColor; + } + if (data.width != null) { + message.width = data.width; + } + if (data.height != null) { + message.height = data.height; + } + if (data.radius != null) { + message.radius = data.radius; + } + if (data.point != null) { + message.point = Point.fromObject(data.point); + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + lineWidth?: number; + lineColor?: string; + width?: number; + height?: number; + radius?: number; + point?: ReturnType; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.lineWidth != null) { + data.lineWidth = this.lineWidth; + } + if (this.lineColor != null) { + data.lineColor = this.lineColor; + } + if (this.width != null) { + data.width = this.width; + } + if (this.height != null) { + data.height = this.height; + } + if (this.radius != null) { + data.radius = this.radius; + } + if (this.point != null) { + data.point = this.point.toObject(); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.lineWidth != 0) + writer.writeInt32(3, this.lineWidth); + if (this.lineColor.length) + writer.writeString(4, this.lineColor); + if (this.width != 0) + writer.writeFloat(5, this.width); + if (this.height != 0) + writer.writeFloat(6, this.height); + if (this.radius != 0) + writer.writeInt32(7, this.radius); + if (this.has_point) + writer.writeMessage(8, this.point, () => this.point.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Rect { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Rect(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + message.lineWidth = reader.readInt32(); + break; + case 4: + message.lineColor = reader.readString(); + break; + case 5: + message.width = reader.readFloat(); + break; + case 6: + message.height = reader.readFloat(); + break; + case 7: + message.radius = reader.readInt32(); + break; + case 8: + reader.readMessage(message.point, () => message.point = Point.deserialize(reader)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Rect { + return Rect.deserialize(bytes); + } + } + export class Polygon extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + lineWidth?: number; + lineColor?: string; + points?: Point[]; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [5], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("lineWidth" in data && data.lineWidth != undefined) { + this.lineWidth = data.lineWidth; + } + if ("lineColor" in data && data.lineColor != undefined) { + this.lineColor = data.lineColor; + } + if ("points" in data && data.points != undefined) { + this.points = data.points; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get lineWidth() { + return pb_1.Message.getFieldWithDefault(this, 3, 0) as number; + } + set lineWidth(value: number) { + pb_1.Message.setField(this, 3, value); + } + get lineColor() { + return pb_1.Message.getFieldWithDefault(this, 4, "") as string; + } + set lineColor(value: string) { + pb_1.Message.setField(this, 4, value); + } + get points() { + return pb_1.Message.getRepeatedWrapperField(this, Point, 5) as Point[]; + } + set points(value: Point[]) { + pb_1.Message.setRepeatedWrapperField(this, 5, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + lineWidth?: number; + lineColor?: string; + points?: ReturnType[]; + }): Polygon { + const message = new Polygon({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.lineWidth != null) { + message.lineWidth = data.lineWidth; + } + if (data.lineColor != null) { + message.lineColor = data.lineColor; + } + if (data.points != null) { + message.points = data.points.map(item => Point.fromObject(item)); + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + lineWidth?: number; + lineColor?: string; + points?: ReturnType[]; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.lineWidth != null) { + data.lineWidth = this.lineWidth; + } + if (this.lineColor != null) { + data.lineColor = this.lineColor; + } + if (this.points != null) { + data.points = this.points.map((item: Point) => item.toObject()); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.lineWidth != 0) + writer.writeInt32(3, this.lineWidth); + if (this.lineColor.length) + writer.writeString(4, this.lineColor); + if (this.points.length) + writer.writeRepeatedMessage(5, this.points, (item: Point) => item.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Polygon { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Polygon(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + message.lineWidth = reader.readInt32(); + break; + case 4: + message.lineColor = reader.readString(); + break; + case 5: + reader.readMessage(message.points, () => pb_1.Message.addToRepeatedWrapperField(message, 5, Point.deserialize(reader), Point)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Polygon { + return Polygon.deserialize(bytes); + } + } + export class Platform extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + hasdoor?: boolean; + direction?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("hasdoor" in data && data.hasdoor != undefined) { + this.hasdoor = data.hasdoor; + } + if ("direction" in data && data.direction != undefined) { + this.direction = data.direction; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get hasdoor() { + return pb_1.Message.getFieldWithDefault(this, 3, false) as boolean; + } + set hasdoor(value: boolean) { + pb_1.Message.setField(this, 3, value); + } + get direction() { + return pb_1.Message.getFieldWithDefault(this, 4, "") as string; + } + set direction(value: string) { + pb_1.Message.setField(this, 4, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + hasdoor?: boolean; + direction?: string; + }): Platform { + const message = new Platform({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.hasdoor != null) { + message.hasdoor = data.hasdoor; + } + if (data.direction != null) { + message.direction = data.direction; + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + hasdoor?: boolean; + direction?: string; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.hasdoor != null) { + data.hasdoor = this.hasdoor; + } + if (this.direction != null) { + data.direction = this.direction; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.hasdoor != false) + writer.writeBool(3, this.hasdoor); + if (this.direction.length) + writer.writeString(4, this.direction); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Platform { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Platform(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + message.hasdoor = reader.readBool(); + break; + case 4: + message.direction = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Platform { + return Platform.deserialize(bytes); + } + } + export class Station extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + hasControl?: boolean; + concentrationStations?: boolean; + kilometerSystem?: KilometerSystem; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("hasControl" in data && data.hasControl != undefined) { + this.hasControl = data.hasControl; + } + if ("concentrationStations" in data && data.concentrationStations != undefined) { + this.concentrationStations = data.concentrationStations; + } + if ("kilometerSystem" in data && data.kilometerSystem != undefined) { + this.kilometerSystem = data.kilometerSystem; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get hasControl() { + return pb_1.Message.getFieldWithDefault(this, 3, false) as boolean; + } + set hasControl(value: boolean) { + pb_1.Message.setField(this, 3, value); + } + get concentrationStations() { + return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean; + } + set concentrationStations(value: boolean) { + pb_1.Message.setField(this, 4, value); + } + get kilometerSystem() { + return pb_1.Message.getWrapperField(this, KilometerSystem, 6) as KilometerSystem; + } + set kilometerSystem(value: KilometerSystem) { + pb_1.Message.setWrapperField(this, 6, value); + } + get has_kilometerSystem() { + return pb_1.Message.getField(this, 6) != null; + } + static fromObject(data: { + common?: ReturnType; + code?: string; + hasControl?: boolean; + concentrationStations?: boolean; + kilometerSystem?: ReturnType; + }): Station { + const message = new Station({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.hasControl != null) { + message.hasControl = data.hasControl; + } + if (data.concentrationStations != null) { + message.concentrationStations = data.concentrationStations; + } + if (data.kilometerSystem != null) { + message.kilometerSystem = KilometerSystem.fromObject(data.kilometerSystem); + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + hasControl?: boolean; + concentrationStations?: boolean; + kilometerSystem?: ReturnType; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.hasControl != null) { + data.hasControl = this.hasControl; + } + if (this.concentrationStations != null) { + data.concentrationStations = this.concentrationStations; + } + if (this.kilometerSystem != null) { + data.kilometerSystem = this.kilometerSystem.toObject(); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.hasControl != false) + writer.writeBool(3, this.hasControl); + if (this.concentrationStations != false) + writer.writeBool(4, this.concentrationStations); + if (this.has_kilometerSystem) + writer.writeMessage(6, this.kilometerSystem, () => this.kilometerSystem.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Station { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Station(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + message.hasControl = reader.readBool(); + break; + case 4: + message.concentrationStations = reader.readBool(); + break; + case 6: + reader.readMessage(message.kilometerSystem, () => message.kilometerSystem = KilometerSystem.deserialize(reader)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Station { + return Station.deserialize(bytes); + } + } + export class StationLine extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + hasTransfer?: boolean; + hideName?: boolean; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("hasTransfer" in data && data.hasTransfer != undefined) { + this.hasTransfer = data.hasTransfer; + } + if ("hideName" in data && data.hideName != undefined) { + this.hideName = data.hideName; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get hasTransfer() { + return pb_1.Message.getFieldWithDefault(this, 3, false) as boolean; + } + set hasTransfer(value: boolean) { + pb_1.Message.setField(this, 3, value); + } + get hideName() { + return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean; + } + set hideName(value: boolean) { + pb_1.Message.setField(this, 4, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + hasTransfer?: boolean; + hideName?: boolean; + }): StationLine { + const message = new StationLine({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.hasTransfer != null) { + message.hasTransfer = data.hasTransfer; + } + if (data.hideName != null) { + message.hideName = data.hideName; + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + hasTransfer?: boolean; + hideName?: boolean; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.hasTransfer != null) { + data.hasTransfer = this.hasTransfer; + } + if (this.hideName != null) { + data.hideName = this.hideName; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.hasTransfer != false) + writer.writeBool(3, this.hasTransfer); + if (this.hideName != false) + writer.writeBool(4, this.hideName); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): StationLine { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new StationLine(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + message.hasTransfer = reader.readBool(); + break; + case 4: + message.hideName = reader.readBool(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): StationLine { + return StationLine.deserialize(bytes); + } + } + export class TrainWindow extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + sectionId?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("sectionId" in data && data.sectionId != undefined) { + this.sectionId = data.sectionId; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get sectionId() { + return pb_1.Message.getFieldWithDefault(this, 3, "") as string; + } + set sectionId(value: string) { + pb_1.Message.setField(this, 3, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + sectionId?: string; + }): TrainWindow { + const message = new TrainWindow({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.sectionId != null) { + message.sectionId = data.sectionId; + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + sectionId?: string; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.sectionId != null) { + data.sectionId = this.sectionId; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.sectionId.length) + writer.writeString(3, this.sectionId); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): TrainWindow { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new TrainWindow(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + message.sectionId = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): TrainWindow { + return TrainWindow.deserialize(bytes); + } + } + export class AxleCounting extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + kilometerSystem?: KilometerSystem; + axleCountingRef?: RelatedRef[]; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [4], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("kilometerSystem" in data && data.kilometerSystem != undefined) { + this.kilometerSystem = data.kilometerSystem; + } + if ("axleCountingRef" in data && data.axleCountingRef != undefined) { + this.axleCountingRef = data.axleCountingRef; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get kilometerSystem() { + return pb_1.Message.getWrapperField(this, KilometerSystem, 3) as KilometerSystem; + } + set kilometerSystem(value: KilometerSystem) { + pb_1.Message.setWrapperField(this, 3, value); + } + get has_kilometerSystem() { + return pb_1.Message.getField(this, 3) != null; + } + get axleCountingRef() { + return pb_1.Message.getRepeatedWrapperField(this, RelatedRef, 4) as RelatedRef[]; + } + set axleCountingRef(value: RelatedRef[]) { + pb_1.Message.setRepeatedWrapperField(this, 4, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + kilometerSystem?: ReturnType; + axleCountingRef?: ReturnType[]; + }): AxleCounting { + const message = new AxleCounting({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.kilometerSystem != null) { + message.kilometerSystem = KilometerSystem.fromObject(data.kilometerSystem); + } + if (data.axleCountingRef != null) { + message.axleCountingRef = data.axleCountingRef.map(item => RelatedRef.fromObject(item)); + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + kilometerSystem?: ReturnType; + axleCountingRef?: ReturnType[]; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.kilometerSystem != null) { + data.kilometerSystem = this.kilometerSystem.toObject(); + } + if (this.axleCountingRef != null) { + data.axleCountingRef = this.axleCountingRef.map((item: RelatedRef) => item.toObject()); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.has_kilometerSystem) + writer.writeMessage(3, this.kilometerSystem, () => this.kilometerSystem.serialize(writer)); + if (this.axleCountingRef.length) + writer.writeRepeatedMessage(4, this.axleCountingRef, (item: RelatedRef) => item.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): AxleCounting { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new AxleCounting(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + reader.readMessage(message.kilometerSystem, () => message.kilometerSystem = KilometerSystem.deserialize(reader)); + break; + case 4: + reader.readMessage(message.axleCountingRef, () => pb_1.Message.addToRepeatedWrapperField(message, 4, RelatedRef.deserialize(reader), RelatedRef)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): AxleCounting { + return AxleCounting.deserialize(bytes); + } + } + export class Train extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + }): Train { + const message = new Train({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Train { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Train(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Train { + return Train.deserialize(bytes); + } + } + export class TrainLine extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + }): TrainLine { + const message = new TrainLine({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): TrainLine { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new TrainLine(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): TrainLine { + return TrainLine.deserialize(bytes); + } + } + export class IscsFan extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + }): IscsFan { + const message = new IscsFan({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): IscsFan { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new IscsFan(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): IscsFan { + return IscsFan.deserialize(bytes); + } + } + export class Turnout extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + pointA?: Point[]; + pointB?: Point[]; + pointC?: Point[]; + paRef?: RelatedRef; + pbRef?: RelatedRef; + pcRef?: RelatedRef; + kilometerSystem?: KilometerSystem[]; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [6, 7, 8, 13], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("pointA" in data && data.pointA != undefined) { + this.pointA = data.pointA; + } + if ("pointB" in data && data.pointB != undefined) { + this.pointB = data.pointB; + } + if ("pointC" in data && data.pointC != undefined) { + this.pointC = data.pointC; + } + if ("paRef" in data && data.paRef != undefined) { + this.paRef = data.paRef; + } + if ("pbRef" in data && data.pbRef != undefined) { + this.pbRef = data.pbRef; + } + if ("pcRef" in data && data.pcRef != undefined) { + this.pcRef = data.pcRef; + } + if ("kilometerSystem" in data && data.kilometerSystem != undefined) { + this.kilometerSystem = data.kilometerSystem; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get pointA() { + return pb_1.Message.getRepeatedWrapperField(this, Point, 6) as Point[]; + } + set pointA(value: Point[]) { + pb_1.Message.setRepeatedWrapperField(this, 6, value); + } + get pointB() { + return pb_1.Message.getRepeatedWrapperField(this, Point, 7) as Point[]; + } + set pointB(value: Point[]) { + pb_1.Message.setRepeatedWrapperField(this, 7, value); + } + get pointC() { + return pb_1.Message.getRepeatedWrapperField(this, Point, 8) as Point[]; + } + set pointC(value: Point[]) { + pb_1.Message.setRepeatedWrapperField(this, 8, value); + } + get paRef() { + return pb_1.Message.getWrapperField(this, RelatedRef, 9) as RelatedRef; + } + set paRef(value: RelatedRef) { + pb_1.Message.setWrapperField(this, 9, value); + } + get has_paRef() { + return pb_1.Message.getField(this, 9) != null; + } + get pbRef() { + return pb_1.Message.getWrapperField(this, RelatedRef, 10) as RelatedRef; + } + set pbRef(value: RelatedRef) { + pb_1.Message.setWrapperField(this, 10, value); + } + get has_pbRef() { + return pb_1.Message.getField(this, 10) != null; + } + get pcRef() { + return pb_1.Message.getWrapperField(this, RelatedRef, 11) as RelatedRef; + } + set pcRef(value: RelatedRef) { + pb_1.Message.setWrapperField(this, 11, value); + } + get has_pcRef() { + return pb_1.Message.getField(this, 11) != null; + } + get kilometerSystem() { + return pb_1.Message.getRepeatedWrapperField(this, KilometerSystem, 13) as KilometerSystem[]; + } + set kilometerSystem(value: KilometerSystem[]) { + pb_1.Message.setRepeatedWrapperField(this, 13, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + pointA?: ReturnType[]; + pointB?: ReturnType[]; + pointC?: ReturnType[]; + paRef?: ReturnType; + pbRef?: ReturnType; + pcRef?: ReturnType; + kilometerSystem?: ReturnType[]; + }): Turnout { + const message = new Turnout({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.pointA != null) { + message.pointA = data.pointA.map(item => Point.fromObject(item)); + } + if (data.pointB != null) { + message.pointB = data.pointB.map(item => Point.fromObject(item)); + } + if (data.pointC != null) { + message.pointC = data.pointC.map(item => Point.fromObject(item)); + } + if (data.paRef != null) { + message.paRef = RelatedRef.fromObject(data.paRef); + } + if (data.pbRef != null) { + message.pbRef = RelatedRef.fromObject(data.pbRef); + } + if (data.pcRef != null) { + message.pcRef = RelatedRef.fromObject(data.pcRef); + } + if (data.kilometerSystem != null) { + message.kilometerSystem = data.kilometerSystem.map(item => KilometerSystem.fromObject(item)); + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + pointA?: ReturnType[]; + pointB?: ReturnType[]; + pointC?: ReturnType[]; + paRef?: ReturnType; + pbRef?: ReturnType; + pcRef?: ReturnType; + kilometerSystem?: ReturnType[]; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.pointA != null) { + data.pointA = this.pointA.map((item: Point) => item.toObject()); + } + if (this.pointB != null) { + data.pointB = this.pointB.map((item: Point) => item.toObject()); + } + if (this.pointC != null) { + data.pointC = this.pointC.map((item: Point) => item.toObject()); + } + if (this.paRef != null) { + data.paRef = this.paRef.toObject(); + } + if (this.pbRef != null) { + data.pbRef = this.pbRef.toObject(); + } + if (this.pcRef != null) { + data.pcRef = this.pcRef.toObject(); + } + if (this.kilometerSystem != null) { + data.kilometerSystem = this.kilometerSystem.map((item: KilometerSystem) => item.toObject()); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.pointA.length) + writer.writeRepeatedMessage(6, this.pointA, (item: Point) => item.serialize(writer)); + if (this.pointB.length) + writer.writeRepeatedMessage(7, this.pointB, (item: Point) => item.serialize(writer)); + if (this.pointC.length) + writer.writeRepeatedMessage(8, this.pointC, (item: Point) => item.serialize(writer)); + if (this.has_paRef) + writer.writeMessage(9, this.paRef, () => this.paRef.serialize(writer)); + if (this.has_pbRef) + writer.writeMessage(10, this.pbRef, () => this.pbRef.serialize(writer)); + if (this.has_pcRef) + writer.writeMessage(11, this.pcRef, () => this.pcRef.serialize(writer)); + if (this.kilometerSystem.length) + writer.writeRepeatedMessage(13, this.kilometerSystem, (item: KilometerSystem) => item.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Turnout { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Turnout(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 6: + reader.readMessage(message.pointA, () => pb_1.Message.addToRepeatedWrapperField(message, 6, Point.deserialize(reader), Point)); + break; + case 7: + reader.readMessage(message.pointB, () => pb_1.Message.addToRepeatedWrapperField(message, 7, Point.deserialize(reader), Point)); + break; + case 8: + reader.readMessage(message.pointC, () => pb_1.Message.addToRepeatedWrapperField(message, 8, Point.deserialize(reader), Point)); + break; + case 9: + reader.readMessage(message.paRef, () => message.paRef = RelatedRef.deserialize(reader)); + break; + case 10: + reader.readMessage(message.pbRef, () => message.pbRef = RelatedRef.deserialize(reader)); + break; + case 11: + reader.readMessage(message.pcRef, () => message.pcRef = RelatedRef.deserialize(reader)); + break; + case 13: + reader.readMessage(message.kilometerSystem, () => pb_1.Message.addToRepeatedWrapperField(message, 13, KilometerSystem.deserialize(reader), KilometerSystem)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Turnout { + return Turnout.deserialize(bytes); + } + } + export class KilometerSystem extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + kilometer?: number; + coordinateSystem?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("kilometer" in data && data.kilometer != undefined) { + this.kilometer = data.kilometer; + } + if ("coordinateSystem" in data && data.coordinateSystem != undefined) { + this.coordinateSystem = data.coordinateSystem; + } + } + } + get kilometer() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set kilometer(value: number) { + pb_1.Message.setField(this, 1, value); + } + get coordinateSystem() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set coordinateSystem(value: string) { + pb_1.Message.setField(this, 2, value); + } + static fromObject(data: { + kilometer?: number; + coordinateSystem?: string; + }): KilometerSystem { + const message = new KilometerSystem({}); + if (data.kilometer != null) { + message.kilometer = data.kilometer; + } + if (data.coordinateSystem != null) { + message.coordinateSystem = data.coordinateSystem; + } + return message; + } + toObject() { + const data: { + kilometer?: number; + coordinateSystem?: string; + } = {}; + if (this.kilometer != null) { + data.kilometer = this.kilometer; + } + if (this.coordinateSystem != null) { + data.coordinateSystem = this.coordinateSystem; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.kilometer != 0) + writer.writeInt64(1, this.kilometer); + if (this.coordinateSystem.length) + writer.writeString(2, this.coordinateSystem); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): KilometerSystem { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new KilometerSystem(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.kilometer = reader.readInt64(); + break; + case 2: + message.coordinateSystem = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): KilometerSystem { + return KilometerSystem.deserialize(bytes); + } + } + export class Signal extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + mirror?: boolean; + kilometerSystem?: KilometerSystem; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("mirror" in data && data.mirror != undefined) { + this.mirror = data.mirror; + } + if ("kilometerSystem" in data && data.kilometerSystem != undefined) { + this.kilometerSystem = data.kilometerSystem; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get mirror() { + return pb_1.Message.getFieldWithDefault(this, 3, false) as boolean; + } + set mirror(value: boolean) { + pb_1.Message.setField(this, 3, value); + } + get kilometerSystem() { + return pb_1.Message.getWrapperField(this, KilometerSystem, 6) as KilometerSystem; + } + set kilometerSystem(value: KilometerSystem) { + pb_1.Message.setWrapperField(this, 6, value); + } + get has_kilometerSystem() { + return pb_1.Message.getField(this, 6) != null; + } + static fromObject(data: { + common?: ReturnType; + code?: string; + mirror?: boolean; + kilometerSystem?: ReturnType; + }): Signal { + const message = new Signal({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.mirror != null) { + message.mirror = data.mirror; + } + if (data.kilometerSystem != null) { + message.kilometerSystem = KilometerSystem.fromObject(data.kilometerSystem); + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + mirror?: boolean; + kilometerSystem?: ReturnType; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.mirror != null) { + data.mirror = this.mirror; + } + if (this.kilometerSystem != null) { + data.kilometerSystem = this.kilometerSystem.toObject(); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.mirror != false) + writer.writeBool(3, this.mirror); + if (this.has_kilometerSystem) + writer.writeMessage(6, this.kilometerSystem, () => this.kilometerSystem.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Signal { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Signal(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + message.mirror = reader.readBool(); + break; + case 6: + reader.readMessage(message.kilometerSystem, () => message.kilometerSystem = KilometerSystem.deserialize(reader)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Signal { + return Signal.deserialize(bytes); + } + } + export class RunLine extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + points?: Point[]; + nameColor?: string; + nameBgColor?: string; + containSta?: string[]; + linkPathLines?: string[]; + lineId?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [3, 8, 9], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("points" in data && data.points != undefined) { + this.points = data.points; + } + if ("nameColor" in data && data.nameColor != undefined) { + this.nameColor = data.nameColor; + } + if ("nameBgColor" in data && data.nameBgColor != undefined) { + this.nameBgColor = data.nameBgColor; + } + if ("containSta" in data && data.containSta != undefined) { + this.containSta = data.containSta; + } + if ("linkPathLines" in data && data.linkPathLines != undefined) { + this.linkPathLines = data.linkPathLines; + } + if ("lineId" in data && data.lineId != undefined) { + this.lineId = data.lineId; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get points() { + return pb_1.Message.getRepeatedWrapperField(this, Point, 3) as Point[]; + } + set points(value: Point[]) { + pb_1.Message.setRepeatedWrapperField(this, 3, value); + } + get nameColor() { + return pb_1.Message.getFieldWithDefault(this, 4, "") as string; + } + set nameColor(value: string) { + pb_1.Message.setField(this, 4, value); + } + get nameBgColor() { + return pb_1.Message.getFieldWithDefault(this, 5, "") as string; + } + set nameBgColor(value: string) { + pb_1.Message.setField(this, 5, value); + } + get containSta() { + return pb_1.Message.getFieldWithDefault(this, 8, []) as string[]; + } + set containSta(value: string[]) { + pb_1.Message.setField(this, 8, value); + } + get linkPathLines() { + return pb_1.Message.getFieldWithDefault(this, 9, []) as string[]; + } + set linkPathLines(value: string[]) { + pb_1.Message.setField(this, 9, value); + } + get lineId() { + return pb_1.Message.getFieldWithDefault(this, 10, "") as string; + } + set lineId(value: string) { + pb_1.Message.setField(this, 10, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + points?: ReturnType[]; + nameColor?: string; + nameBgColor?: string; + containSta?: string[]; + linkPathLines?: string[]; + lineId?: string; + }): RunLine { + const message = new RunLine({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.points != null) { + message.points = data.points.map(item => Point.fromObject(item)); + } + if (data.nameColor != null) { + message.nameColor = data.nameColor; + } + if (data.nameBgColor != null) { + message.nameBgColor = data.nameBgColor; + } + if (data.containSta != null) { + message.containSta = data.containSta; + } + if (data.linkPathLines != null) { + message.linkPathLines = data.linkPathLines; + } + if (data.lineId != null) { + message.lineId = data.lineId; + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + points?: ReturnType[]; + nameColor?: string; + nameBgColor?: string; + containSta?: string[]; + linkPathLines?: string[]; + lineId?: string; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.points != null) { + data.points = this.points.map((item: Point) => item.toObject()); + } + if (this.nameColor != null) { + data.nameColor = this.nameColor; + } + if (this.nameBgColor != null) { + data.nameBgColor = this.nameBgColor; + } + if (this.containSta != null) { + data.containSta = this.containSta; + } + if (this.linkPathLines != null) { + data.linkPathLines = this.linkPathLines; + } + if (this.lineId != null) { + data.lineId = this.lineId; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.points.length) + writer.writeRepeatedMessage(3, this.points, (item: Point) => item.serialize(writer)); + if (this.nameColor.length) + writer.writeString(4, this.nameColor); + if (this.nameBgColor.length) + writer.writeString(5, this.nameBgColor); + if (this.containSta.length) + writer.writeRepeatedString(8, this.containSta); + if (this.linkPathLines.length) + writer.writeRepeatedString(9, this.linkPathLines); + if (this.lineId.length) + writer.writeString(10, this.lineId); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): RunLine { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new RunLine(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + reader.readMessage(message.points, () => pb_1.Message.addToRepeatedWrapperField(message, 3, Point.deserialize(reader), Point)); + break; + case 4: + message.nameColor = reader.readString(); + break; + case 5: + message.nameBgColor = reader.readString(); + break; + case 8: + pb_1.Message.addToRepeatedField(message, 8, reader.readString()); + break; + case 9: + pb_1.Message.addToRepeatedField(message, 9, reader.readString()); + break; + case 10: + message.lineId = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): RunLine { + return RunLine.deserialize(bytes); + } + } + export class Section extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + points?: Point[]; + paRef?: RelatedRef; + pbRef?: RelatedRef; + sectionType?: Section.SectionType; + children?: string[]; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [3, 7], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("points" in data && data.points != undefined) { + this.points = data.points; + } + if ("paRef" in data && data.paRef != undefined) { + this.paRef = data.paRef; + } + if ("pbRef" in data && data.pbRef != undefined) { + this.pbRef = data.pbRef; + } + if ("sectionType" in data && data.sectionType != undefined) { + this.sectionType = data.sectionType; + } + if ("children" in data && data.children != undefined) { + this.children = data.children; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get points() { + return pb_1.Message.getRepeatedWrapperField(this, Point, 3) as Point[]; + } + set points(value: Point[]) { + pb_1.Message.setRepeatedWrapperField(this, 3, value); + } + get paRef() { + return pb_1.Message.getWrapperField(this, RelatedRef, 4) as RelatedRef; + } + set paRef(value: RelatedRef) { + pb_1.Message.setWrapperField(this, 4, value); + } + get has_paRef() { + return pb_1.Message.getField(this, 4) != null; + } + get pbRef() { + return pb_1.Message.getWrapperField(this, RelatedRef, 5) as RelatedRef; + } + set pbRef(value: RelatedRef) { + pb_1.Message.setWrapperField(this, 5, value); + } + get has_pbRef() { + return pb_1.Message.getField(this, 5) != null; + } + get sectionType() { + return pb_1.Message.getFieldWithDefault(this, 6, Section.SectionType.Physical) as Section.SectionType; + } + set sectionType(value: Section.SectionType) { + pb_1.Message.setField(this, 6, value); + } + get children() { + return pb_1.Message.getFieldWithDefault(this, 7, []) as string[]; + } + set children(value: string[]) { + pb_1.Message.setField(this, 7, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + points?: ReturnType[]; + paRef?: ReturnType; + pbRef?: ReturnType; + sectionType?: Section.SectionType; + children?: string[]; + }): Section { + const message = new Section({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.points != null) { + message.points = data.points.map(item => Point.fromObject(item)); + } + if (data.paRef != null) { + message.paRef = RelatedRef.fromObject(data.paRef); + } + if (data.pbRef != null) { + message.pbRef = RelatedRef.fromObject(data.pbRef); + } + if (data.sectionType != null) { + message.sectionType = data.sectionType; + } + if (data.children != null) { + message.children = data.children; + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + points?: ReturnType[]; + paRef?: ReturnType; + pbRef?: ReturnType; + sectionType?: Section.SectionType; + children?: string[]; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.points != null) { + data.points = this.points.map((item: Point) => item.toObject()); + } + if (this.paRef != null) { + data.paRef = this.paRef.toObject(); + } + if (this.pbRef != null) { + data.pbRef = this.pbRef.toObject(); + } + if (this.sectionType != null) { + data.sectionType = this.sectionType; + } + if (this.children != null) { + data.children = this.children; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.points.length) + writer.writeRepeatedMessage(3, this.points, (item: Point) => item.serialize(writer)); + if (this.has_paRef) + writer.writeMessage(4, this.paRef, () => this.paRef.serialize(writer)); + if (this.has_pbRef) + writer.writeMessage(5, this.pbRef, () => this.pbRef.serialize(writer)); + if (this.sectionType != Section.SectionType.Physical) + writer.writeEnum(6, this.sectionType); + if (this.children.length) + writer.writeRepeatedString(7, this.children); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Section { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Section(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + reader.readMessage(message.points, () => pb_1.Message.addToRepeatedWrapperField(message, 3, Point.deserialize(reader), Point)); + break; + case 4: + reader.readMessage(message.paRef, () => message.paRef = RelatedRef.deserialize(reader)); + break; + case 5: + reader.readMessage(message.pbRef, () => message.pbRef = RelatedRef.deserialize(reader)); + break; + case 6: + message.sectionType = reader.readEnum(); + break; + case 7: + pb_1.Message.addToRepeatedField(message, 7, reader.readString()); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Section { + return Section.deserialize(bytes); + } + } + export namespace Section { + export enum SectionType { + Physical = 0, + Logic = 1, + TurnoutPhysical = 2 + } + } + export class KilometerPoint extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + point?: Point; + kilometer?: number; + stName?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("point" in data && data.point != undefined) { + this.point = data.point; + } + if ("kilometer" in data && data.kilometer != undefined) { + this.kilometer = data.kilometer; + } + if ("stName" in data && data.stName != undefined) { + this.stName = data.stName; + } + } + } + get point() { + return pb_1.Message.getWrapperField(this, Point, 1) as Point; + } + set point(value: Point) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_point() { + return pb_1.Message.getField(this, 1) != null; + } + get kilometer() { + return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; + } + set kilometer(value: number) { + pb_1.Message.setField(this, 2, value); + } + get stName() { + return pb_1.Message.getFieldWithDefault(this, 3, "") as string; + } + set stName(value: string) { + pb_1.Message.setField(this, 3, value); + } + static fromObject(data: { + point?: ReturnType; + kilometer?: number; + stName?: string; + }): KilometerPoint { + const message = new KilometerPoint({}); + if (data.point != null) { + message.point = Point.fromObject(data.point); + } + if (data.kilometer != null) { + message.kilometer = data.kilometer; + } + if (data.stName != null) { + message.stName = data.stName; + } + return message; + } + toObject() { + const data: { + point?: ReturnType; + kilometer?: number; + stName?: string; + } = {}; + if (this.point != null) { + data.point = this.point.toObject(); + } + if (this.kilometer != null) { + data.kilometer = this.kilometer; + } + if (this.stName != null) { + data.stName = this.stName; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_point) + writer.writeMessage(1, this.point, () => this.point.serialize(writer)); + if (this.kilometer != 0) + writer.writeInt64(2, this.kilometer); + if (this.stName.length) + writer.writeString(3, this.stName); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): KilometerPoint { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new KilometerPoint(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.point, () => message.point = Point.deserialize(reader)); + break; + case 2: + message.kilometer = reader.readInt64(); + break; + case 3: + message.stName = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): KilometerPoint { + return KilometerPoint.deserialize(bytes); + } + } + export class PathLine extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + points?: Point[]; + isUp?: boolean; + kilometerPoints?: KilometerPoint[]; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [3, 5], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("points" in data && data.points != undefined) { + this.points = data.points; + } + if ("isUp" in data && data.isUp != undefined) { + this.isUp = data.isUp; + } + if ("kilometerPoints" in data && data.kilometerPoints != undefined) { + this.kilometerPoints = data.kilometerPoints; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get points() { + return pb_1.Message.getRepeatedWrapperField(this, Point, 3) as Point[]; + } + set points(value: Point[]) { + pb_1.Message.setRepeatedWrapperField(this, 3, value); + } + get isUp() { + return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean; + } + set isUp(value: boolean) { + pb_1.Message.setField(this, 4, value); + } + get kilometerPoints() { + return pb_1.Message.getRepeatedWrapperField(this, KilometerPoint, 5) as KilometerPoint[]; + } + set kilometerPoints(value: KilometerPoint[]) { + pb_1.Message.setRepeatedWrapperField(this, 5, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + points?: ReturnType[]; + isUp?: boolean; + kilometerPoints?: ReturnType[]; + }): PathLine { + const message = new PathLine({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.points != null) { + message.points = data.points.map(item => Point.fromObject(item)); + } + if (data.isUp != null) { + message.isUp = data.isUp; + } + if (data.kilometerPoints != null) { + message.kilometerPoints = data.kilometerPoints.map(item => KilometerPoint.fromObject(item)); + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + points?: ReturnType[]; + isUp?: boolean; + kilometerPoints?: ReturnType[]; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.points != null) { + data.points = this.points.map((item: Point) => item.toObject()); + } + if (this.isUp != null) { + data.isUp = this.isUp; + } + if (this.kilometerPoints != null) { + data.kilometerPoints = this.kilometerPoints.map((item: KilometerPoint) => item.toObject()); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.points.length) + writer.writeRepeatedMessage(3, this.points, (item: Point) => item.serialize(writer)); + if (this.isUp != false) + writer.writeBool(4, this.isUp); + if (this.kilometerPoints.length) + writer.writeRepeatedMessage(5, this.kilometerPoints, (item: KilometerPoint) => item.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): PathLine { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new PathLine(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + reader.readMessage(message.points, () => pb_1.Message.addToRepeatedWrapperField(message, 3, Point.deserialize(reader), Point)); + break; + case 4: + message.isUp = reader.readBool(); + break; + case 5: + reader.readMessage(message.kilometerPoints, () => pb_1.Message.addToRepeatedWrapperField(message, 5, KilometerPoint.deserialize(reader), KilometerPoint)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): PathLine { + return PathLine.deserialize(bytes); + } + } + export class RelatedRef extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + deviceType?: RelatedRef.DeviceType; + id?: string; + devicePort?: RelatedRef.DevicePort; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("deviceType" in data && data.deviceType != undefined) { + this.deviceType = data.deviceType; + } + if ("id" in data && data.id != undefined) { + this.id = data.id; + } + if ("devicePort" in data && data.devicePort != undefined) { + this.devicePort = data.devicePort; + } + } + } + get deviceType() { + return pb_1.Message.getFieldWithDefault(this, 1, RelatedRef.DeviceType.Section) as RelatedRef.DeviceType; + } + set deviceType(value: RelatedRef.DeviceType) { + pb_1.Message.setField(this, 1, value); + } + get id() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set id(value: string) { + pb_1.Message.setField(this, 2, value); + } + get devicePort() { + return pb_1.Message.getFieldWithDefault(this, 3, RelatedRef.DevicePort.A) as RelatedRef.DevicePort; + } + set devicePort(value: RelatedRef.DevicePort) { + pb_1.Message.setField(this, 3, value); + } + static fromObject(data: { + deviceType?: RelatedRef.DeviceType; + id?: string; + devicePort?: RelatedRef.DevicePort; + }): RelatedRef { + const message = new RelatedRef({}); + if (data.deviceType != null) { + message.deviceType = data.deviceType; + } + if (data.id != null) { + message.id = data.id; + } + if (data.devicePort != null) { + message.devicePort = data.devicePort; + } + return message; + } + toObject() { + const data: { + deviceType?: RelatedRef.DeviceType; + id?: string; + devicePort?: RelatedRef.DevicePort; + } = {}; + if (this.deviceType != null) { + data.deviceType = this.deviceType; + } + if (this.id != null) { + data.id = this.id; + } + if (this.devicePort != null) { + data.devicePort = this.devicePort; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.deviceType != RelatedRef.DeviceType.Section) + writer.writeEnum(1, this.deviceType); + if (this.id.length) + writer.writeString(2, this.id); + if (this.devicePort != RelatedRef.DevicePort.A) + writer.writeEnum(3, this.devicePort); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): RelatedRef { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new RelatedRef(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.deviceType = reader.readEnum(); + break; + case 2: + message.id = reader.readString(); + break; + case 3: + message.devicePort = reader.readEnum(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): RelatedRef { + return RelatedRef.deserialize(bytes); + } + } + export namespace RelatedRef { + export enum DeviceType { + Section = 0, + Turnout = 1, + TrainWindow = 2, + AxleCounting = 3 + } + export enum DevicePort { + A = 0, + B = 1, + C = 2 + } + } + export class Separator extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + common?: CommonInfo; + code?: string; + separatorType?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("common" in data && data.common != undefined) { + this.common = data.common; + } + if ("code" in data && data.code != undefined) { + this.code = data.code; + } + if ("separatorType" in data && data.separatorType != undefined) { + this.separatorType = data.separatorType; + } + } + } + get common() { + return pb_1.Message.getWrapperField(this, CommonInfo, 1) as CommonInfo; + } + set common(value: CommonInfo) { + pb_1.Message.setWrapperField(this, 1, value); + } + get has_common() { + return pb_1.Message.getField(this, 1) != null; + } + get code() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set code(value: string) { + pb_1.Message.setField(this, 2, value); + } + get separatorType() { + return pb_1.Message.getFieldWithDefault(this, 3, "") as string; + } + set separatorType(value: string) { + pb_1.Message.setField(this, 3, value); + } + static fromObject(data: { + common?: ReturnType; + code?: string; + separatorType?: string; + }): Separator { + const message = new Separator({}); + if (data.common != null) { + message.common = CommonInfo.fromObject(data.common); + } + if (data.code != null) { + message.code = data.code; + } + if (data.separatorType != null) { + message.separatorType = data.separatorType; + } + return message; + } + toObject() { + const data: { + common?: ReturnType; + code?: string; + separatorType?: string; + } = {}; + if (this.common != null) { + data.common = this.common.toObject(); + } + if (this.code != null) { + data.code = this.code; + } + if (this.separatorType != null) { + data.separatorType = this.separatorType; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.has_common) + writer.writeMessage(1, this.common, () => this.common.serialize(writer)); + if (this.code.length) + writer.writeString(2, this.code); + if (this.separatorType.length) + writer.writeString(3, this.separatorType); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): Separator { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new Separator(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.common, () => message.common = CommonInfo.deserialize(reader)); + break; + case 2: + message.code = reader.readString(); + break; + case 3: + message.separatorType = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): Separator { + return Separator.deserialize(bytes); + } + } +} diff --git a/src/protos/train.ts b/src/protos/train.ts new file mode 100644 index 0000000..7d30ec9 --- /dev/null +++ b/src/protos/train.ts @@ -0,0 +1,1512 @@ +/** + * Generated by the protoc-gen-ts. DO NOT EDIT! + * compiler version: 4.23.1 + * source: train.proto + * git: https://github.com/thesayyn/protoc-gen-ts */ +import * as dependency_1 from "./device_status"; +import * as pb_1 from "google-protobuf"; +export namespace train { + export class TrainInfo extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + lineId?: number; + rtuId?: number; + window?: NccWindow; + devType?: dependency_1.state.DeviceType; + devName?: string; + trainIndex?: string; + groupId?: string; + trainId?: string; + globalId?: string; + destinationId?: number; + rollingStock?: number; + driverId?: string; + otpTime?: number; + mode?: dependency_1.state.TrainMode; + arriveTime?: number; + departTime?: number; + speed?: number; + type?: boolean; + routeId?: number; + rate?: number; + remove?: TrainRemove; + block?: TrainBlock; + record?: TrainRecord; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("lineId" in data && data.lineId != undefined) { + this.lineId = data.lineId; + } + if ("rtuId" in data && data.rtuId != undefined) { + this.rtuId = data.rtuId; + } + if ("window" in data && data.window != undefined) { + this.window = data.window; + } + if ("devType" in data && data.devType != undefined) { + this.devType = data.devType; + } + if ("devName" in data && data.devName != undefined) { + this.devName = data.devName; + } + if ("trainIndex" in data && data.trainIndex != undefined) { + this.trainIndex = data.trainIndex; + } + if ("groupId" in data && data.groupId != undefined) { + this.groupId = data.groupId; + } + if ("trainId" in data && data.trainId != undefined) { + this.trainId = data.trainId; + } + if ("globalId" in data && data.globalId != undefined) { + this.globalId = data.globalId; + } + if ("destinationId" in data && data.destinationId != undefined) { + this.destinationId = data.destinationId; + } + if ("rollingStock" in data && data.rollingStock != undefined) { + this.rollingStock = data.rollingStock; + } + if ("driverId" in data && data.driverId != undefined) { + this.driverId = data.driverId; + } + if ("otpTime" in data && data.otpTime != undefined) { + this.otpTime = data.otpTime; + } + if ("mode" in data && data.mode != undefined) { + this.mode = data.mode; + } + if ("arriveTime" in data && data.arriveTime != undefined) { + this.arriveTime = data.arriveTime; + } + if ("departTime" in data && data.departTime != undefined) { + this.departTime = data.departTime; + } + if ("speed" in data && data.speed != undefined) { + this.speed = data.speed; + } + if ("type" in data && data.type != undefined) { + this.type = data.type; + } + if ("routeId" in data && data.routeId != undefined) { + this.routeId = data.routeId; + } + if ("rate" in data && data.rate != undefined) { + this.rate = data.rate; + } + if ("remove" in data && data.remove != undefined) { + this.remove = data.remove; + } + if ("block" in data && data.block != undefined) { + this.block = data.block; + } + if ("record" in data && data.record != undefined) { + this.record = data.record; + } + } + } + get lineId() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set lineId(value: number) { + pb_1.Message.setField(this, 1, value); + } + get rtuId() { + return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; + } + set rtuId(value: number) { + pb_1.Message.setField(this, 2, value); + } + get window() { + return pb_1.Message.getWrapperField(this, NccWindow, 3) as NccWindow; + } + set window(value: NccWindow) { + pb_1.Message.setWrapperField(this, 3, value); + } + get has_window() { + return pb_1.Message.getField(this, 3) != null; + } + get devType() { + return pb_1.Message.getFieldWithDefault(this, 4, dependency_1.state.DeviceType.UNKNOW) as dependency_1.state.DeviceType; + } + set devType(value: dependency_1.state.DeviceType) { + pb_1.Message.setField(this, 4, value); + } + get devName() { + return pb_1.Message.getFieldWithDefault(this, 5, "") as string; + } + set devName(value: string) { + pb_1.Message.setField(this, 5, value); + } + get trainIndex() { + return pb_1.Message.getFieldWithDefault(this, 6, "") as string; + } + set trainIndex(value: string) { + pb_1.Message.setField(this, 6, value); + } + get groupId() { + return pb_1.Message.getFieldWithDefault(this, 7, "") as string; + } + set groupId(value: string) { + pb_1.Message.setField(this, 7, value); + } + get trainId() { + return pb_1.Message.getFieldWithDefault(this, 8, "") as string; + } + set trainId(value: string) { + pb_1.Message.setField(this, 8, value); + } + get globalId() { + return pb_1.Message.getFieldWithDefault(this, 9, "") as string; + } + set globalId(value: string) { + pb_1.Message.setField(this, 9, value); + } + get destinationId() { + return pb_1.Message.getFieldWithDefault(this, 10, 0) as number; + } + set destinationId(value: number) { + pb_1.Message.setField(this, 10, value); + } + get rollingStock() { + return pb_1.Message.getFieldWithDefault(this, 11, 0) as number; + } + set rollingStock(value: number) { + pb_1.Message.setField(this, 11, value); + } + get driverId() { + return pb_1.Message.getFieldWithDefault(this, 12, "") as string; + } + set driverId(value: string) { + pb_1.Message.setField(this, 12, value); + } + get otpTime() { + return pb_1.Message.getFieldWithDefault(this, 13, 0) as number; + } + set otpTime(value: number) { + pb_1.Message.setField(this, 13, value); + } + get mode() { + return pb_1.Message.getWrapperField(this, dependency_1.state.TrainMode, 14) as dependency_1.state.TrainMode; + } + set mode(value: dependency_1.state.TrainMode) { + pb_1.Message.setWrapperField(this, 14, value); + } + get has_mode() { + return pb_1.Message.getField(this, 14) != null; + } + get arriveTime() { + return pb_1.Message.getFieldWithDefault(this, 15, 0) as number; + } + set arriveTime(value: number) { + pb_1.Message.setField(this, 15, value); + } + get departTime() { + return pb_1.Message.getFieldWithDefault(this, 16, 0) as number; + } + set departTime(value: number) { + pb_1.Message.setField(this, 16, value); + } + get speed() { + return pb_1.Message.getFieldWithDefault(this, 17, 0) as number; + } + set speed(value: number) { + pb_1.Message.setField(this, 17, value); + } + get type() { + return pb_1.Message.getFieldWithDefault(this, 18, false) as boolean; + } + set type(value: boolean) { + pb_1.Message.setField(this, 18, value); + } + get routeId() { + return pb_1.Message.getFieldWithDefault(this, 19, 0) as number; + } + set routeId(value: number) { + pb_1.Message.setField(this, 19, value); + } + get rate() { + return pb_1.Message.getFieldWithDefault(this, 20, 0) as number; + } + set rate(value: number) { + pb_1.Message.setField(this, 20, value); + } + get remove() { + return pb_1.Message.getWrapperField(this, TrainRemove, 21) as TrainRemove; + } + set remove(value: TrainRemove) { + pb_1.Message.setWrapperField(this, 21, value); + } + get has_remove() { + return pb_1.Message.getField(this, 21) != null; + } + get block() { + return pb_1.Message.getWrapperField(this, TrainBlock, 22) as TrainBlock; + } + set block(value: TrainBlock) { + pb_1.Message.setWrapperField(this, 22, value); + } + get has_block() { + return pb_1.Message.getField(this, 22) != null; + } + get record() { + return pb_1.Message.getWrapperField(this, TrainRecord, 23) as TrainRecord; + } + set record(value: TrainRecord) { + pb_1.Message.setWrapperField(this, 23, value); + } + get has_record() { + return pb_1.Message.getField(this, 23) != null; + } + static fromObject(data: { + lineId?: number; + rtuId?: number; + window?: ReturnType; + devType?: dependency_1.state.DeviceType; + devName?: string; + trainIndex?: string; + groupId?: string; + trainId?: string; + globalId?: string; + destinationId?: number; + rollingStock?: number; + driverId?: string; + otpTime?: number; + mode?: ReturnType; + arriveTime?: number; + departTime?: number; + speed?: number; + type?: boolean; + routeId?: number; + rate?: number; + remove?: ReturnType; + block?: ReturnType; + record?: ReturnType; + }): TrainInfo { + const message = new TrainInfo({}); + if (data.lineId != null) { + message.lineId = data.lineId; + } + if (data.rtuId != null) { + message.rtuId = data.rtuId; + } + if (data.window != null) { + message.window = NccWindow.fromObject(data.window); + } + if (data.devType != null) { + message.devType = data.devType; + } + if (data.devName != null) { + message.devName = data.devName; + } + if (data.trainIndex != null) { + message.trainIndex = data.trainIndex; + } + if (data.groupId != null) { + message.groupId = data.groupId; + } + if (data.trainId != null) { + message.trainId = data.trainId; + } + if (data.globalId != null) { + message.globalId = data.globalId; + } + if (data.destinationId != null) { + message.destinationId = data.destinationId; + } + if (data.rollingStock != null) { + message.rollingStock = data.rollingStock; + } + if (data.driverId != null) { + message.driverId = data.driverId; + } + if (data.otpTime != null) { + message.otpTime = data.otpTime; + } + if (data.mode != null) { + message.mode = dependency_1.state.TrainMode.fromObject(data.mode); + } + if (data.arriveTime != null) { + message.arriveTime = data.arriveTime; + } + if (data.departTime != null) { + message.departTime = data.departTime; + } + if (data.speed != null) { + message.speed = data.speed; + } + if (data.type != null) { + message.type = data.type; + } + if (data.routeId != null) { + message.routeId = data.routeId; + } + if (data.rate != null) { + message.rate = data.rate; + } + if (data.remove != null) { + message.remove = TrainRemove.fromObject(data.remove); + } + if (data.block != null) { + message.block = TrainBlock.fromObject(data.block); + } + if (data.record != null) { + message.record = TrainRecord.fromObject(data.record); + } + return message; + } + toObject() { + const data: { + lineId?: number; + rtuId?: number; + window?: ReturnType; + devType?: dependency_1.state.DeviceType; + devName?: string; + trainIndex?: string; + groupId?: string; + trainId?: string; + globalId?: string; + destinationId?: number; + rollingStock?: number; + driverId?: string; + otpTime?: number; + mode?: ReturnType; + arriveTime?: number; + departTime?: number; + speed?: number; + type?: boolean; + routeId?: number; + rate?: number; + remove?: ReturnType; + block?: ReturnType; + record?: ReturnType; + } = {}; + if (this.lineId != null) { + data.lineId = this.lineId; + } + if (this.rtuId != null) { + data.rtuId = this.rtuId; + } + if (this.window != null) { + data.window = this.window.toObject(); + } + if (this.devType != null) { + data.devType = this.devType; + } + if (this.devName != null) { + data.devName = this.devName; + } + if (this.trainIndex != null) { + data.trainIndex = this.trainIndex; + } + if (this.groupId != null) { + data.groupId = this.groupId; + } + if (this.trainId != null) { + data.trainId = this.trainId; + } + if (this.globalId != null) { + data.globalId = this.globalId; + } + if (this.destinationId != null) { + data.destinationId = this.destinationId; + } + if (this.rollingStock != null) { + data.rollingStock = this.rollingStock; + } + if (this.driverId != null) { + data.driverId = this.driverId; + } + if (this.otpTime != null) { + data.otpTime = this.otpTime; + } + if (this.mode != null) { + data.mode = this.mode.toObject(); + } + if (this.arriveTime != null) { + data.arriveTime = this.arriveTime; + } + if (this.departTime != null) { + data.departTime = this.departTime; + } + if (this.speed != null) { + data.speed = this.speed; + } + if (this.type != null) { + data.type = this.type; + } + if (this.routeId != null) { + data.routeId = this.routeId; + } + if (this.rate != null) { + data.rate = this.rate; + } + if (this.remove != null) { + data.remove = this.remove.toObject(); + } + if (this.block != null) { + data.block = this.block.toObject(); + } + if (this.record != null) { + data.record = this.record.toObject(); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.lineId != 0) + writer.writeInt32(1, this.lineId); + if (this.rtuId != 0) + writer.writeInt32(2, this.rtuId); + if (this.has_window) + writer.writeMessage(3, this.window, () => this.window.serialize(writer)); + if (this.devType != dependency_1.state.DeviceType.UNKNOW) + writer.writeEnum(4, this.devType); + if (this.devName.length) + writer.writeString(5, this.devName); + if (this.trainIndex.length) + writer.writeString(6, this.trainIndex); + if (this.groupId.length) + writer.writeString(7, this.groupId); + if (this.trainId.length) + writer.writeString(8, this.trainId); + if (this.globalId.length) + writer.writeString(9, this.globalId); + if (this.destinationId != 0) + writer.writeInt32(10, this.destinationId); + if (this.rollingStock != 0) + writer.writeInt32(11, this.rollingStock); + if (this.driverId.length) + writer.writeString(12, this.driverId); + if (this.otpTime != 0) + writer.writeInt32(13, this.otpTime); + if (this.has_mode) + writer.writeMessage(14, this.mode, () => this.mode.serialize(writer)); + if (this.arriveTime != 0) + writer.writeInt64(15, this.arriveTime); + if (this.departTime != 0) + writer.writeInt64(16, this.departTime); + if (this.speed != 0) + writer.writeFloat(17, this.speed); + if (this.type != false) + writer.writeBool(18, this.type); + if (this.routeId != 0) + writer.writeInt32(19, this.routeId); + if (this.rate != 0) + writer.writeInt32(20, this.rate); + if (this.has_remove) + writer.writeMessage(21, this.remove, () => this.remove.serialize(writer)); + if (this.has_block) + writer.writeMessage(22, this.block, () => this.block.serialize(writer)); + if (this.has_record) + writer.writeMessage(23, this.record, () => this.record.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): TrainInfo { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new TrainInfo(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.lineId = reader.readInt32(); + break; + case 2: + message.rtuId = reader.readInt32(); + break; + case 3: + reader.readMessage(message.window, () => message.window = NccWindow.deserialize(reader)); + break; + case 4: + message.devType = reader.readEnum(); + break; + case 5: + message.devName = reader.readString(); + break; + case 6: + message.trainIndex = reader.readString(); + break; + case 7: + message.groupId = reader.readString(); + break; + case 8: + message.trainId = reader.readString(); + break; + case 9: + message.globalId = reader.readString(); + break; + case 10: + message.destinationId = reader.readInt32(); + break; + case 11: + message.rollingStock = reader.readInt32(); + break; + case 12: + message.driverId = reader.readString(); + break; + case 13: + message.otpTime = reader.readInt32(); + break; + case 14: + reader.readMessage(message.mode, () => message.mode = dependency_1.state.TrainMode.deserialize(reader)); + break; + case 15: + message.arriveTime = reader.readInt64(); + break; + case 16: + message.departTime = reader.readInt64(); + break; + case 17: + message.speed = reader.readFloat(); + break; + case 18: + message.type = reader.readBool(); + break; + case 19: + message.routeId = reader.readInt32(); + break; + case 20: + message.rate = reader.readInt32(); + break; + case 21: + reader.readMessage(message.remove, () => message.remove = TrainRemove.deserialize(reader)); + break; + case 22: + reader.readMessage(message.block, () => message.block = TrainBlock.deserialize(reader)); + break; + case 23: + reader.readMessage(message.record, () => message.record = TrainRecord.deserialize(reader)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): TrainInfo { + return TrainInfo.deserialize(bytes); + } + } + export class NccWindow extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + nccWindow?: number; + nccWinOffset?: number; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("nccWindow" in data && data.nccWindow != undefined) { + this.nccWindow = data.nccWindow; + } + if ("nccWinOffset" in data && data.nccWinOffset != undefined) { + this.nccWinOffset = data.nccWinOffset; + } + } + } + get nccWindow() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set nccWindow(value: number) { + pb_1.Message.setField(this, 1, value); + } + get nccWinOffset() { + return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; + } + set nccWinOffset(value: number) { + pb_1.Message.setField(this, 2, value); + } + static fromObject(data: { + nccWindow?: number; + nccWinOffset?: number; + }): NccWindow { + const message = new NccWindow({}); + if (data.nccWindow != null) { + message.nccWindow = data.nccWindow; + } + if (data.nccWinOffset != null) { + message.nccWinOffset = data.nccWinOffset; + } + return message; + } + toObject() { + const data: { + nccWindow?: number; + nccWinOffset?: number; + } = {}; + if (this.nccWindow != null) { + data.nccWindow = this.nccWindow; + } + if (this.nccWinOffset != null) { + data.nccWinOffset = this.nccWinOffset; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.nccWindow != 0) + writer.writeInt32(1, this.nccWindow); + if (this.nccWinOffset != 0) + writer.writeInt32(2, this.nccWinOffset); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): NccWindow { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new NccWindow(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.nccWindow = reader.readInt32(); + break; + case 2: + message.nccWinOffset = reader.readInt32(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): NccWindow { + return NccWindow.deserialize(bytes); + } + } + export class TrainRemove extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + lineId?: number; + rtuId?: number; + window?: NccWindow; + deviceType?: dependency_1.state.DeviceType; + devName?: string; + trainIndex?: string; + groupId?: string; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("lineId" in data && data.lineId != undefined) { + this.lineId = data.lineId; + } + if ("rtuId" in data && data.rtuId != undefined) { + this.rtuId = data.rtuId; + } + if ("window" in data && data.window != undefined) { + this.window = data.window; + } + if ("deviceType" in data && data.deviceType != undefined) { + this.deviceType = data.deviceType; + } + if ("devName" in data && data.devName != undefined) { + this.devName = data.devName; + } + if ("trainIndex" in data && data.trainIndex != undefined) { + this.trainIndex = data.trainIndex; + } + if ("groupId" in data && data.groupId != undefined) { + this.groupId = data.groupId; + } + } + } + get lineId() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set lineId(value: number) { + pb_1.Message.setField(this, 1, value); + } + get rtuId() { + return pb_1.Message.getFieldWithDefault(this, 2, 0) as number; + } + set rtuId(value: number) { + pb_1.Message.setField(this, 2, value); + } + get window() { + return pb_1.Message.getWrapperField(this, NccWindow, 3) as NccWindow; + } + set window(value: NccWindow) { + pb_1.Message.setWrapperField(this, 3, value); + } + get has_window() { + return pb_1.Message.getField(this, 3) != null; + } + get deviceType() { + return pb_1.Message.getFieldWithDefault(this, 4, dependency_1.state.DeviceType.UNKNOW) as dependency_1.state.DeviceType; + } + set deviceType(value: dependency_1.state.DeviceType) { + pb_1.Message.setField(this, 4, value); + } + get devName() { + return pb_1.Message.getFieldWithDefault(this, 5, "") as string; + } + set devName(value: string) { + pb_1.Message.setField(this, 5, value); + } + get trainIndex() { + return pb_1.Message.getFieldWithDefault(this, 6, "") as string; + } + set trainIndex(value: string) { + pb_1.Message.setField(this, 6, value); + } + get groupId() { + return pb_1.Message.getFieldWithDefault(this, 7, "") as string; + } + set groupId(value: string) { + pb_1.Message.setField(this, 7, value); + } + static fromObject(data: { + lineId?: number; + rtuId?: number; + window?: ReturnType; + deviceType?: dependency_1.state.DeviceType; + devName?: string; + trainIndex?: string; + groupId?: string; + }): TrainRemove { + const message = new TrainRemove({}); + if (data.lineId != null) { + message.lineId = data.lineId; + } + if (data.rtuId != null) { + message.rtuId = data.rtuId; + } + if (data.window != null) { + message.window = NccWindow.fromObject(data.window); + } + if (data.deviceType != null) { + message.deviceType = data.deviceType; + } + if (data.devName != null) { + message.devName = data.devName; + } + if (data.trainIndex != null) { + message.trainIndex = data.trainIndex; + } + if (data.groupId != null) { + message.groupId = data.groupId; + } + return message; + } + toObject() { + const data: { + lineId?: number; + rtuId?: number; + window?: ReturnType; + deviceType?: dependency_1.state.DeviceType; + devName?: string; + trainIndex?: string; + groupId?: string; + } = {}; + if (this.lineId != null) { + data.lineId = this.lineId; + } + if (this.rtuId != null) { + data.rtuId = this.rtuId; + } + if (this.window != null) { + data.window = this.window.toObject(); + } + if (this.deviceType != null) { + data.deviceType = this.deviceType; + } + if (this.devName != null) { + data.devName = this.devName; + } + if (this.trainIndex != null) { + data.trainIndex = this.trainIndex; + } + if (this.groupId != null) { + data.groupId = this.groupId; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.lineId != 0) + writer.writeInt32(1, this.lineId); + if (this.rtuId != 0) + writer.writeInt32(2, this.rtuId); + if (this.has_window) + writer.writeMessage(3, this.window, () => this.window.serialize(writer)); + if (this.deviceType != dependency_1.state.DeviceType.UNKNOW) + writer.writeEnum(4, this.deviceType); + if (this.devName.length) + writer.writeString(5, this.devName); + if (this.trainIndex.length) + writer.writeString(6, this.trainIndex); + if (this.groupId.length) + writer.writeString(7, this.groupId); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): TrainRemove { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new TrainRemove(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.lineId = reader.readInt32(); + break; + case 2: + message.rtuId = reader.readInt32(); + break; + case 3: + reader.readMessage(message.window, () => message.window = NccWindow.deserialize(reader)); + break; + case 4: + message.deviceType = reader.readEnum(); + break; + case 5: + message.devName = reader.readString(); + break; + case 6: + message.trainIndex = reader.readString(); + break; + case 7: + message.groupId = reader.readString(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): TrainRemove { + return TrainRemove.deserialize(bytes); + } + } + export class TrainBlock extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + lineId?: number; + groupId?: string; + trainId?: string; + direction?: number; + stationIDInUpSide?: number; + stationIDInDownSide?: number; + rtuId?: number; + deviceType?: dependency_1.state.DeviceType; + DevName?: string; + blockFlag?: number; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("lineId" in data && data.lineId != undefined) { + this.lineId = data.lineId; + } + if ("groupId" in data && data.groupId != undefined) { + this.groupId = data.groupId; + } + if ("trainId" in data && data.trainId != undefined) { + this.trainId = data.trainId; + } + if ("direction" in data && data.direction != undefined) { + this.direction = data.direction; + } + if ("stationIDInUpSide" in data && data.stationIDInUpSide != undefined) { + this.stationIDInUpSide = data.stationIDInUpSide; + } + if ("stationIDInDownSide" in data && data.stationIDInDownSide != undefined) { + this.stationIDInDownSide = data.stationIDInDownSide; + } + if ("rtuId" in data && data.rtuId != undefined) { + this.rtuId = data.rtuId; + } + if ("deviceType" in data && data.deviceType != undefined) { + this.deviceType = data.deviceType; + } + if ("DevName" in data && data.DevName != undefined) { + this.DevName = data.DevName; + } + if ("blockFlag" in data && data.blockFlag != undefined) { + this.blockFlag = data.blockFlag; + } + } + } + get lineId() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set lineId(value: number) { + pb_1.Message.setField(this, 1, value); + } + get groupId() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set groupId(value: string) { + pb_1.Message.setField(this, 2, value); + } + get trainId() { + return pb_1.Message.getFieldWithDefault(this, 3, "") as string; + } + set trainId(value: string) { + pb_1.Message.setField(this, 3, value); + } + get direction() { + return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; + } + set direction(value: number) { + pb_1.Message.setField(this, 4, value); + } + get stationIDInUpSide() { + return pb_1.Message.getFieldWithDefault(this, 5, 0) as number; + } + set stationIDInUpSide(value: number) { + pb_1.Message.setField(this, 5, value); + } + get stationIDInDownSide() { + return pb_1.Message.getFieldWithDefault(this, 6, 0) as number; + } + set stationIDInDownSide(value: number) { + pb_1.Message.setField(this, 6, value); + } + get rtuId() { + return pb_1.Message.getFieldWithDefault(this, 7, 0) as number; + } + set rtuId(value: number) { + pb_1.Message.setField(this, 7, value); + } + get deviceType() { + return pb_1.Message.getFieldWithDefault(this, 8, dependency_1.state.DeviceType.UNKNOW) as dependency_1.state.DeviceType; + } + set deviceType(value: dependency_1.state.DeviceType) { + pb_1.Message.setField(this, 8, value); + } + get DevName() { + return pb_1.Message.getFieldWithDefault(this, 9, "") as string; + } + set DevName(value: string) { + pb_1.Message.setField(this, 9, value); + } + get blockFlag() { + return pb_1.Message.getFieldWithDefault(this, 10, 0) as number; + } + set blockFlag(value: number) { + pb_1.Message.setField(this, 10, value); + } + static fromObject(data: { + lineId?: number; + groupId?: string; + trainId?: string; + direction?: number; + stationIDInUpSide?: number; + stationIDInDownSide?: number; + rtuId?: number; + deviceType?: dependency_1.state.DeviceType; + DevName?: string; + blockFlag?: number; + }): TrainBlock { + const message = new TrainBlock({}); + if (data.lineId != null) { + message.lineId = data.lineId; + } + if (data.groupId != null) { + message.groupId = data.groupId; + } + if (data.trainId != null) { + message.trainId = data.trainId; + } + if (data.direction != null) { + message.direction = data.direction; + } + if (data.stationIDInUpSide != null) { + message.stationIDInUpSide = data.stationIDInUpSide; + } + if (data.stationIDInDownSide != null) { + message.stationIDInDownSide = data.stationIDInDownSide; + } + if (data.rtuId != null) { + message.rtuId = data.rtuId; + } + if (data.deviceType != null) { + message.deviceType = data.deviceType; + } + if (data.DevName != null) { + message.DevName = data.DevName; + } + if (data.blockFlag != null) { + message.blockFlag = data.blockFlag; + } + return message; + } + toObject() { + const data: { + lineId?: number; + groupId?: string; + trainId?: string; + direction?: number; + stationIDInUpSide?: number; + stationIDInDownSide?: number; + rtuId?: number; + deviceType?: dependency_1.state.DeviceType; + DevName?: string; + blockFlag?: number; + } = {}; + if (this.lineId != null) { + data.lineId = this.lineId; + } + if (this.groupId != null) { + data.groupId = this.groupId; + } + if (this.trainId != null) { + data.trainId = this.trainId; + } + if (this.direction != null) { + data.direction = this.direction; + } + if (this.stationIDInUpSide != null) { + data.stationIDInUpSide = this.stationIDInUpSide; + } + if (this.stationIDInDownSide != null) { + data.stationIDInDownSide = this.stationIDInDownSide; + } + if (this.rtuId != null) { + data.rtuId = this.rtuId; + } + if (this.deviceType != null) { + data.deviceType = this.deviceType; + } + if (this.DevName != null) { + data.DevName = this.DevName; + } + if (this.blockFlag != null) { + data.blockFlag = this.blockFlag; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.lineId != 0) + writer.writeInt32(1, this.lineId); + if (this.groupId.length) + writer.writeString(2, this.groupId); + if (this.trainId.length) + writer.writeString(3, this.trainId); + if (this.direction != 0) + writer.writeInt32(4, this.direction); + if (this.stationIDInUpSide != 0) + writer.writeInt32(5, this.stationIDInUpSide); + if (this.stationIDInDownSide != 0) + writer.writeInt32(6, this.stationIDInDownSide); + if (this.rtuId != 0) + writer.writeInt32(7, this.rtuId); + if (this.deviceType != dependency_1.state.DeviceType.UNKNOW) + writer.writeEnum(8, this.deviceType); + if (this.DevName.length) + writer.writeString(9, this.DevName); + if (this.blockFlag != 0) + writer.writeInt32(10, this.blockFlag); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): TrainBlock { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new TrainBlock(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.lineId = reader.readInt32(); + break; + case 2: + message.groupId = reader.readString(); + break; + case 3: + message.trainId = reader.readString(); + break; + case 4: + message.direction = reader.readInt32(); + break; + case 5: + message.stationIDInUpSide = reader.readInt32(); + break; + case 6: + message.stationIDInDownSide = reader.readInt32(); + break; + case 7: + message.rtuId = reader.readInt32(); + break; + case 8: + message.deviceType = reader.readEnum(); + break; + case 9: + message.DevName = reader.readString(); + break; + case 10: + message.blockFlag = reader.readInt32(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): TrainBlock { + return TrainBlock.deserialize(bytes); + } + } + export class TrainRecord extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + lineId?: number; + trainId?: string; + globalId?: string; + localSubId?: number; + groupId?: string; + destinationId?: number; + trainType?: number; + dir?: number; + stationId?: number; + sideId?: number; + trackName?: string; + recordType?: boolean; + recordTime?: number; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("lineId" in data && data.lineId != undefined) { + this.lineId = data.lineId; + } + if ("trainId" in data && data.trainId != undefined) { + this.trainId = data.trainId; + } + if ("globalId" in data && data.globalId != undefined) { + this.globalId = data.globalId; + } + if ("localSubId" in data && data.localSubId != undefined) { + this.localSubId = data.localSubId; + } + if ("groupId" in data && data.groupId != undefined) { + this.groupId = data.groupId; + } + if ("destinationId" in data && data.destinationId != undefined) { + this.destinationId = data.destinationId; + } + if ("trainType" in data && data.trainType != undefined) { + this.trainType = data.trainType; + } + if ("dir" in data && data.dir != undefined) { + this.dir = data.dir; + } + if ("stationId" in data && data.stationId != undefined) { + this.stationId = data.stationId; + } + if ("sideId" in data && data.sideId != undefined) { + this.sideId = data.sideId; + } + if ("trackName" in data && data.trackName != undefined) { + this.trackName = data.trackName; + } + if ("recordType" in data && data.recordType != undefined) { + this.recordType = data.recordType; + } + if ("recordTime" in data && data.recordTime != undefined) { + this.recordTime = data.recordTime; + } + } + } + get lineId() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set lineId(value: number) { + pb_1.Message.setField(this, 1, value); + } + get trainId() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set trainId(value: string) { + pb_1.Message.setField(this, 2, value); + } + get globalId() { + return pb_1.Message.getFieldWithDefault(this, 3, "") as string; + } + set globalId(value: string) { + pb_1.Message.setField(this, 3, value); + } + get localSubId() { + return pb_1.Message.getFieldWithDefault(this, 4, 0) as number; + } + set localSubId(value: number) { + pb_1.Message.setField(this, 4, value); + } + get groupId() { + return pb_1.Message.getFieldWithDefault(this, 5, "") as string; + } + set groupId(value: string) { + pb_1.Message.setField(this, 5, value); + } + get destinationId() { + return pb_1.Message.getFieldWithDefault(this, 6, 0) as number; + } + set destinationId(value: number) { + pb_1.Message.setField(this, 6, value); + } + get trainType() { + return pb_1.Message.getFieldWithDefault(this, 7, 0) as number; + } + set trainType(value: number) { + pb_1.Message.setField(this, 7, value); + } + get dir() { + return pb_1.Message.getFieldWithDefault(this, 8, 0) as number; + } + set dir(value: number) { + pb_1.Message.setField(this, 8, value); + } + get stationId() { + return pb_1.Message.getFieldWithDefault(this, 9, 0) as number; + } + set stationId(value: number) { + pb_1.Message.setField(this, 9, value); + } + get sideId() { + return pb_1.Message.getFieldWithDefault(this, 10, 0) as number; + } + set sideId(value: number) { + pb_1.Message.setField(this, 10, value); + } + get trackName() { + return pb_1.Message.getFieldWithDefault(this, 11, "") as string; + } + set trackName(value: string) { + pb_1.Message.setField(this, 11, value); + } + get recordType() { + return pb_1.Message.getFieldWithDefault(this, 12, false) as boolean; + } + set recordType(value: boolean) { + pb_1.Message.setField(this, 12, value); + } + get recordTime() { + return pb_1.Message.getFieldWithDefault(this, 13, 0) as number; + } + set recordTime(value: number) { + pb_1.Message.setField(this, 13, value); + } + static fromObject(data: { + lineId?: number; + trainId?: string; + globalId?: string; + localSubId?: number; + groupId?: string; + destinationId?: number; + trainType?: number; + dir?: number; + stationId?: number; + sideId?: number; + trackName?: string; + recordType?: boolean; + recordTime?: number; + }): TrainRecord { + const message = new TrainRecord({}); + if (data.lineId != null) { + message.lineId = data.lineId; + } + if (data.trainId != null) { + message.trainId = data.trainId; + } + if (data.globalId != null) { + message.globalId = data.globalId; + } + if (data.localSubId != null) { + message.localSubId = data.localSubId; + } + if (data.groupId != null) { + message.groupId = data.groupId; + } + if (data.destinationId != null) { + message.destinationId = data.destinationId; + } + if (data.trainType != null) { + message.trainType = data.trainType; + } + if (data.dir != null) { + message.dir = data.dir; + } + if (data.stationId != null) { + message.stationId = data.stationId; + } + if (data.sideId != null) { + message.sideId = data.sideId; + } + if (data.trackName != null) { + message.trackName = data.trackName; + } + if (data.recordType != null) { + message.recordType = data.recordType; + } + if (data.recordTime != null) { + message.recordTime = data.recordTime; + } + return message; + } + toObject() { + const data: { + lineId?: number; + trainId?: string; + globalId?: string; + localSubId?: number; + groupId?: string; + destinationId?: number; + trainType?: number; + dir?: number; + stationId?: number; + sideId?: number; + trackName?: string; + recordType?: boolean; + recordTime?: number; + } = {}; + if (this.lineId != null) { + data.lineId = this.lineId; + } + if (this.trainId != null) { + data.trainId = this.trainId; + } + if (this.globalId != null) { + data.globalId = this.globalId; + } + if (this.localSubId != null) { + data.localSubId = this.localSubId; + } + if (this.groupId != null) { + data.groupId = this.groupId; + } + if (this.destinationId != null) { + data.destinationId = this.destinationId; + } + if (this.trainType != null) { + data.trainType = this.trainType; + } + if (this.dir != null) { + data.dir = this.dir; + } + if (this.stationId != null) { + data.stationId = this.stationId; + } + if (this.sideId != null) { + data.sideId = this.sideId; + } + if (this.trackName != null) { + data.trackName = this.trackName; + } + if (this.recordType != null) { + data.recordType = this.recordType; + } + if (this.recordTime != null) { + data.recordTime = this.recordTime; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.lineId != 0) + writer.writeInt32(1, this.lineId); + if (this.trainId.length) + writer.writeString(2, this.trainId); + if (this.globalId.length) + writer.writeString(3, this.globalId); + if (this.localSubId != 0) + writer.writeInt32(4, this.localSubId); + if (this.groupId.length) + writer.writeString(5, this.groupId); + if (this.destinationId != 0) + writer.writeInt32(6, this.destinationId); + if (this.trainType != 0) + writer.writeInt32(7, this.trainType); + if (this.dir != 0) + writer.writeInt32(8, this.dir); + if (this.stationId != 0) + writer.writeInt32(9, this.stationId); + if (this.sideId != 0) + writer.writeInt32(10, this.sideId); + if (this.trackName.length) + writer.writeString(11, this.trackName); + if (this.recordType != false) + writer.writeBool(12, this.recordType); + if (this.recordTime != 0) + writer.writeInt64(13, this.recordTime); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): TrainRecord { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new TrainRecord(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.lineId = reader.readInt32(); + break; + case 2: + message.trainId = reader.readString(); + break; + case 3: + message.globalId = reader.readString(); + break; + case 4: + message.localSubId = reader.readInt32(); + break; + case 5: + message.groupId = reader.readString(); + break; + case 6: + message.destinationId = reader.readInt32(); + break; + case 7: + message.trainType = reader.readInt32(); + break; + case 8: + message.dir = reader.readInt32(); + break; + case 9: + message.stationId = reader.readInt32(); + break; + case 10: + message.sideId = reader.readInt32(); + break; + case 11: + message.trackName = reader.readString(); + break; + case 12: + message.recordType = reader.readBool(); + break; + case 13: + message.recordTime = reader.readInt64(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): TrainRecord { + return TrainRecord.deserialize(bytes); + } + } +} diff --git a/src/protos/ws_message.ts b/src/protos/ws_message.ts new file mode 100644 index 0000000..628cde0 --- /dev/null +++ b/src/protos/ws_message.ts @@ -0,0 +1,646 @@ +/** + * Generated by the protoc-gen-ts. DO NOT EDIT! + * compiler version: 4.23.1 + * source: ws_message.proto + * git: https://github.com/thesayyn/protoc-gen-ts */ +import * as dependency_1 from "./device_status"; +import * as dependency_2 from "./train"; +import * as pb_1 from "google-protobuf"; +export namespace state { + export class WsLineMessage extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + rtu?: dependency_1.state.Rtu[]; + station?: dependency_1.state.Station[]; + signal?: dependency_1.state.Signal[]; + entry?: dependency_1.state.Entry[]; + switch?: dependency_1.state.Switch[]; + track?: dependency_1.state.Track[]; + platform?: dependency_1.state.Platform[]; + scada?: dependency_1.state.Scada[]; + waterProofDoor?: dependency_1.state.WaterProofDoor[]; + workArea?: dependency_1.state.WorkArea[]; + gama?: dependency_1.state.Gama[]; + netWork?: dependency_1.state.OccNccFepNetwork[]; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("rtu" in data && data.rtu != undefined) { + this.rtu = data.rtu; + } + if ("station" in data && data.station != undefined) { + this.station = data.station; + } + if ("signal" in data && data.signal != undefined) { + this.signal = data.signal; + } + if ("entry" in data && data.entry != undefined) { + this.entry = data.entry; + } + if ("switch" in data && data.switch != undefined) { + this.switch = data.switch; + } + if ("track" in data && data.track != undefined) { + this.track = data.track; + } + if ("platform" in data && data.platform != undefined) { + this.platform = data.platform; + } + if ("scada" in data && data.scada != undefined) { + this.scada = data.scada; + } + if ("waterProofDoor" in data && data.waterProofDoor != undefined) { + this.waterProofDoor = data.waterProofDoor; + } + if ("workArea" in data && data.workArea != undefined) { + this.workArea = data.workArea; + } + if ("gama" in data && data.gama != undefined) { + this.gama = data.gama; + } + if ("netWork" in data && data.netWork != undefined) { + this.netWork = data.netWork; + } + } + } + get rtu() { + return pb_1.Message.getRepeatedWrapperField(this, dependency_1.state.Rtu, 1) as dependency_1.state.Rtu[]; + } + set rtu(value: dependency_1.state.Rtu[]) { + pb_1.Message.setRepeatedWrapperField(this, 1, value); + } + get station() { + return pb_1.Message.getRepeatedWrapperField(this, dependency_1.state.Station, 2) as dependency_1.state.Station[]; + } + set station(value: dependency_1.state.Station[]) { + pb_1.Message.setRepeatedWrapperField(this, 2, value); + } + get signal() { + return pb_1.Message.getRepeatedWrapperField(this, dependency_1.state.Signal, 3) as dependency_1.state.Signal[]; + } + set signal(value: dependency_1.state.Signal[]) { + pb_1.Message.setRepeatedWrapperField(this, 3, value); + } + get entry() { + return pb_1.Message.getRepeatedWrapperField(this, dependency_1.state.Entry, 4) as dependency_1.state.Entry[]; + } + set entry(value: dependency_1.state.Entry[]) { + pb_1.Message.setRepeatedWrapperField(this, 4, value); + } + get switch() { + return pb_1.Message.getRepeatedWrapperField(this, dependency_1.state.Switch, 5) as dependency_1.state.Switch[]; + } + set switch(value: dependency_1.state.Switch[]) { + pb_1.Message.setRepeatedWrapperField(this, 5, value); + } + get track() { + return pb_1.Message.getRepeatedWrapperField(this, dependency_1.state.Track, 6) as dependency_1.state.Track[]; + } + set track(value: dependency_1.state.Track[]) { + pb_1.Message.setRepeatedWrapperField(this, 6, value); + } + get platform() { + return pb_1.Message.getRepeatedWrapperField(this, dependency_1.state.Platform, 7) as dependency_1.state.Platform[]; + } + set platform(value: dependency_1.state.Platform[]) { + pb_1.Message.setRepeatedWrapperField(this, 7, value); + } + get scada() { + return pb_1.Message.getRepeatedWrapperField(this, dependency_1.state.Scada, 8) as dependency_1.state.Scada[]; + } + set scada(value: dependency_1.state.Scada[]) { + pb_1.Message.setRepeatedWrapperField(this, 8, value); + } + get waterProofDoor() { + return pb_1.Message.getRepeatedWrapperField(this, dependency_1.state.WaterProofDoor, 9) as dependency_1.state.WaterProofDoor[]; + } + set waterProofDoor(value: dependency_1.state.WaterProofDoor[]) { + pb_1.Message.setRepeatedWrapperField(this, 9, value); + } + get workArea() { + return pb_1.Message.getRepeatedWrapperField(this, dependency_1.state.WorkArea, 10) as dependency_1.state.WorkArea[]; + } + set workArea(value: dependency_1.state.WorkArea[]) { + pb_1.Message.setRepeatedWrapperField(this, 10, value); + } + get gama() { + return pb_1.Message.getRepeatedWrapperField(this, dependency_1.state.Gama, 11) as dependency_1.state.Gama[]; + } + set gama(value: dependency_1.state.Gama[]) { + pb_1.Message.setRepeatedWrapperField(this, 11, value); + } + get netWork() { + return pb_1.Message.getRepeatedWrapperField(this, dependency_1.state.OccNccFepNetwork, 12) as dependency_1.state.OccNccFepNetwork[]; + } + set netWork(value: dependency_1.state.OccNccFepNetwork[]) { + pb_1.Message.setRepeatedWrapperField(this, 12, value); + } + static fromObject(data: { + rtu?: ReturnType[]; + station?: ReturnType[]; + signal?: ReturnType[]; + entry?: ReturnType[]; + switch?: ReturnType[]; + track?: ReturnType[]; + platform?: ReturnType[]; + scada?: ReturnType[]; + waterProofDoor?: ReturnType[]; + workArea?: ReturnType[]; + gama?: ReturnType[]; + netWork?: ReturnType[]; + }): WsLineMessage { + const message = new WsLineMessage({}); + if (data.rtu != null) { + message.rtu = data.rtu.map(item => dependency_1.state.Rtu.fromObject(item)); + } + if (data.station != null) { + message.station = data.station.map(item => dependency_1.state.Station.fromObject(item)); + } + if (data.signal != null) { + message.signal = data.signal.map(item => dependency_1.state.Signal.fromObject(item)); + } + if (data.entry != null) { + message.entry = data.entry.map(item => dependency_1.state.Entry.fromObject(item)); + } + if (data.switch != null) { + message.switch = data.switch.map(item => dependency_1.state.Switch.fromObject(item)); + } + if (data.track != null) { + message.track = data.track.map(item => dependency_1.state.Track.fromObject(item)); + } + if (data.platform != null) { + message.platform = data.platform.map(item => dependency_1.state.Platform.fromObject(item)); + } + if (data.scada != null) { + message.scada = data.scada.map(item => dependency_1.state.Scada.fromObject(item)); + } + if (data.waterProofDoor != null) { + message.waterProofDoor = data.waterProofDoor.map(item => dependency_1.state.WaterProofDoor.fromObject(item)); + } + if (data.workArea != null) { + message.workArea = data.workArea.map(item => dependency_1.state.WorkArea.fromObject(item)); + } + if (data.gama != null) { + message.gama = data.gama.map(item => dependency_1.state.Gama.fromObject(item)); + } + if (data.netWork != null) { + message.netWork = data.netWork.map(item => dependency_1.state.OccNccFepNetwork.fromObject(item)); + } + return message; + } + toObject() { + const data: { + rtu?: ReturnType[]; + station?: ReturnType[]; + signal?: ReturnType[]; + entry?: ReturnType[]; + switch?: ReturnType[]; + track?: ReturnType[]; + platform?: ReturnType[]; + scada?: ReturnType[]; + waterProofDoor?: ReturnType[]; + workArea?: ReturnType[]; + gama?: ReturnType[]; + netWork?: ReturnType[]; + } = {}; + if (this.rtu != null) { + data.rtu = this.rtu.map((item: dependency_1.state.Rtu) => item.toObject()); + } + if (this.station != null) { + data.station = this.station.map((item: dependency_1.state.Station) => item.toObject()); + } + if (this.signal != null) { + data.signal = this.signal.map((item: dependency_1.state.Signal) => item.toObject()); + } + if (this.entry != null) { + data.entry = this.entry.map((item: dependency_1.state.Entry) => item.toObject()); + } + if (this.switch != null) { + data.switch = this.switch.map((item: dependency_1.state.Switch) => item.toObject()); + } + if (this.track != null) { + data.track = this.track.map((item: dependency_1.state.Track) => item.toObject()); + } + if (this.platform != null) { + data.platform = this.platform.map((item: dependency_1.state.Platform) => item.toObject()); + } + if (this.scada != null) { + data.scada = this.scada.map((item: dependency_1.state.Scada) => item.toObject()); + } + if (this.waterProofDoor != null) { + data.waterProofDoor = this.waterProofDoor.map((item: dependency_1.state.WaterProofDoor) => item.toObject()); + } + if (this.workArea != null) { + data.workArea = this.workArea.map((item: dependency_1.state.WorkArea) => item.toObject()); + } + if (this.gama != null) { + data.gama = this.gama.map((item: dependency_1.state.Gama) => item.toObject()); + } + if (this.netWork != null) { + data.netWork = this.netWork.map((item: dependency_1.state.OccNccFepNetwork) => item.toObject()); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.rtu.length) + writer.writeRepeatedMessage(1, this.rtu, (item: dependency_1.state.Rtu) => item.serialize(writer)); + if (this.station.length) + writer.writeRepeatedMessage(2, this.station, (item: dependency_1.state.Station) => item.serialize(writer)); + if (this.signal.length) + writer.writeRepeatedMessage(3, this.signal, (item: dependency_1.state.Signal) => item.serialize(writer)); + if (this.entry.length) + writer.writeRepeatedMessage(4, this.entry, (item: dependency_1.state.Entry) => item.serialize(writer)); + if (this.switch.length) + writer.writeRepeatedMessage(5, this.switch, (item: dependency_1.state.Switch) => item.serialize(writer)); + if (this.track.length) + writer.writeRepeatedMessage(6, this.track, (item: dependency_1.state.Track) => item.serialize(writer)); + if (this.platform.length) + writer.writeRepeatedMessage(7, this.platform, (item: dependency_1.state.Platform) => item.serialize(writer)); + if (this.scada.length) + writer.writeRepeatedMessage(8, this.scada, (item: dependency_1.state.Scada) => item.serialize(writer)); + if (this.waterProofDoor.length) + writer.writeRepeatedMessage(9, this.waterProofDoor, (item: dependency_1.state.WaterProofDoor) => item.serialize(writer)); + if (this.workArea.length) + writer.writeRepeatedMessage(10, this.workArea, (item: dependency_1.state.WorkArea) => item.serialize(writer)); + if (this.gama.length) + writer.writeRepeatedMessage(11, this.gama, (item: dependency_1.state.Gama) => item.serialize(writer)); + if (this.netWork.length) + writer.writeRepeatedMessage(12, this.netWork, (item: dependency_1.state.OccNccFepNetwork) => item.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): WsLineMessage { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new WsLineMessage(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.rtu, () => pb_1.Message.addToRepeatedWrapperField(message, 1, dependency_1.state.Rtu.deserialize(reader), dependency_1.state.Rtu)); + break; + case 2: + reader.readMessage(message.station, () => pb_1.Message.addToRepeatedWrapperField(message, 2, dependency_1.state.Station.deserialize(reader), dependency_1.state.Station)); + break; + case 3: + reader.readMessage(message.signal, () => pb_1.Message.addToRepeatedWrapperField(message, 3, dependency_1.state.Signal.deserialize(reader), dependency_1.state.Signal)); + break; + case 4: + reader.readMessage(message.entry, () => pb_1.Message.addToRepeatedWrapperField(message, 4, dependency_1.state.Entry.deserialize(reader), dependency_1.state.Entry)); + break; + case 5: + reader.readMessage(message.switch, () => pb_1.Message.addToRepeatedWrapperField(message, 5, dependency_1.state.Switch.deserialize(reader), dependency_1.state.Switch)); + break; + case 6: + reader.readMessage(message.track, () => pb_1.Message.addToRepeatedWrapperField(message, 6, dependency_1.state.Track.deserialize(reader), dependency_1.state.Track)); + break; + case 7: + reader.readMessage(message.platform, () => pb_1.Message.addToRepeatedWrapperField(message, 7, dependency_1.state.Platform.deserialize(reader), dependency_1.state.Platform)); + break; + case 8: + reader.readMessage(message.scada, () => pb_1.Message.addToRepeatedWrapperField(message, 8, dependency_1.state.Scada.deserialize(reader), dependency_1.state.Scada)); + break; + case 9: + reader.readMessage(message.waterProofDoor, () => pb_1.Message.addToRepeatedWrapperField(message, 9, dependency_1.state.WaterProofDoor.deserialize(reader), dependency_1.state.WaterProofDoor)); + break; + case 10: + reader.readMessage(message.workArea, () => pb_1.Message.addToRepeatedWrapperField(message, 10, dependency_1.state.WorkArea.deserialize(reader), dependency_1.state.WorkArea)); + break; + case 11: + reader.readMessage(message.gama, () => pb_1.Message.addToRepeatedWrapperField(message, 11, dependency_1.state.Gama.deserialize(reader), dependency_1.state.Gama)); + break; + case 12: + reader.readMessage(message.netWork, () => pb_1.Message.addToRepeatedWrapperField(message, 12, dependency_1.state.OccNccFepNetwork.deserialize(reader), dependency_1.state.OccNccFepNetwork)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): WsLineMessage { + return WsLineMessage.deserialize(bytes); + } + } + export class WsLineTrainMessage extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + trainInfo?: dependency_2.train.TrainInfo[]; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [1], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("trainInfo" in data && data.trainInfo != undefined) { + this.trainInfo = data.trainInfo; + } + } + } + get trainInfo() { + return pb_1.Message.getRepeatedWrapperField(this, dependency_2.train.TrainInfo, 1) as dependency_2.train.TrainInfo[]; + } + set trainInfo(value: dependency_2.train.TrainInfo[]) { + pb_1.Message.setRepeatedWrapperField(this, 1, value); + } + static fromObject(data: { + trainInfo?: ReturnType[]; + }): WsLineTrainMessage { + const message = new WsLineTrainMessage({}); + if (data.trainInfo != null) { + message.trainInfo = data.trainInfo.map(item => dependency_2.train.TrainInfo.fromObject(item)); + } + return message; + } + toObject() { + const data: { + trainInfo?: ReturnType[]; + } = {}; + if (this.trainInfo != null) { + data.trainInfo = this.trainInfo.map((item: dependency_2.train.TrainInfo) => item.toObject()); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.trainInfo.length) + writer.writeRepeatedMessage(1, this.trainInfo, (item: dependency_2.train.TrainInfo) => item.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): WsLineTrainMessage { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new WsLineTrainMessage(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.trainInfo, () => pb_1.Message.addToRepeatedWrapperField(message, 1, dependency_2.train.TrainInfo.deserialize(reader), dependency_2.train.TrainInfo)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): WsLineTrainMessage { + return WsLineTrainMessage.deserialize(bytes); + } + } + export class WsLineNetMessage extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + offset?: WsLineNetTrainOffsetMessage[]; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [1], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("offset" in data && data.offset != undefined) { + this.offset = data.offset; + } + } + } + get offset() { + return pb_1.Message.getRepeatedWrapperField(this, WsLineNetTrainOffsetMessage, 1) as WsLineNetTrainOffsetMessage[]; + } + set offset(value: WsLineNetTrainOffsetMessage[]) { + pb_1.Message.setRepeatedWrapperField(this, 1, value); + } + static fromObject(data: { + offset?: ReturnType[]; + }): WsLineNetMessage { + const message = new WsLineNetMessage({}); + if (data.offset != null) { + message.offset = data.offset.map(item => WsLineNetTrainOffsetMessage.fromObject(item)); + } + return message; + } + toObject() { + const data: { + offset?: ReturnType[]; + } = {}; + if (this.offset != null) { + data.offset = this.offset.map((item: WsLineNetTrainOffsetMessage) => item.toObject()); + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.offset.length) + writer.writeRepeatedMessage(1, this.offset, (item: WsLineNetTrainOffsetMessage) => item.serialize(writer)); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): WsLineNetMessage { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new WsLineNetMessage(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + reader.readMessage(message.offset, () => pb_1.Message.addToRepeatedWrapperField(message, 1, WsLineNetTrainOffsetMessage.deserialize(reader), WsLineNetTrainOffsetMessage)); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): WsLineNetMessage { + return WsLineNetMessage.deserialize(bytes); + } + } + export class WsLineNetTrainOffsetMessage extends pb_1.Message { + #one_of_decls: number[][] = []; + constructor(data?: any[] | { + lineId?: number; + trainIndex?: string; + groupId?: string; + show?: boolean; + kilometerCode?: number; + dir?: number; + }) { + super(); + pb_1.Message.initialize(this, Array.isArray(data) ? data : [], 0, -1, [], this.#one_of_decls); + if (!Array.isArray(data) && typeof data == "object") { + if ("lineId" in data && data.lineId != undefined) { + this.lineId = data.lineId; + } + if ("trainIndex" in data && data.trainIndex != undefined) { + this.trainIndex = data.trainIndex; + } + if ("groupId" in data && data.groupId != undefined) { + this.groupId = data.groupId; + } + if ("show" in data && data.show != undefined) { + this.show = data.show; + } + if ("kilometerCode" in data && data.kilometerCode != undefined) { + this.kilometerCode = data.kilometerCode; + } + if ("dir" in data && data.dir != undefined) { + this.dir = data.dir; + } + } + } + get lineId() { + return pb_1.Message.getFieldWithDefault(this, 1, 0) as number; + } + set lineId(value: number) { + pb_1.Message.setField(this, 1, value); + } + get trainIndex() { + return pb_1.Message.getFieldWithDefault(this, 2, "") as string; + } + set trainIndex(value: string) { + pb_1.Message.setField(this, 2, value); + } + get groupId() { + return pb_1.Message.getFieldWithDefault(this, 3, "") as string; + } + set groupId(value: string) { + pb_1.Message.setField(this, 3, value); + } + get show() { + return pb_1.Message.getFieldWithDefault(this, 4, false) as boolean; + } + set show(value: boolean) { + pb_1.Message.setField(this, 4, value); + } + get kilometerCode() { + return pb_1.Message.getFieldWithDefault(this, 5, 0) as number; + } + set kilometerCode(value: number) { + pb_1.Message.setField(this, 5, value); + } + get dir() { + return pb_1.Message.getFieldWithDefault(this, 6, 0) as number; + } + set dir(value: number) { + pb_1.Message.setField(this, 6, value); + } + static fromObject(data: { + lineId?: number; + trainIndex?: string; + groupId?: string; + show?: boolean; + kilometerCode?: number; + dir?: number; + }): WsLineNetTrainOffsetMessage { + const message = new WsLineNetTrainOffsetMessage({}); + if (data.lineId != null) { + message.lineId = data.lineId; + } + if (data.trainIndex != null) { + message.trainIndex = data.trainIndex; + } + if (data.groupId != null) { + message.groupId = data.groupId; + } + if (data.show != null) { + message.show = data.show; + } + if (data.kilometerCode != null) { + message.kilometerCode = data.kilometerCode; + } + if (data.dir != null) { + message.dir = data.dir; + } + return message; + } + toObject() { + const data: { + lineId?: number; + trainIndex?: string; + groupId?: string; + show?: boolean; + kilometerCode?: number; + dir?: number; + } = {}; + if (this.lineId != null) { + data.lineId = this.lineId; + } + if (this.trainIndex != null) { + data.trainIndex = this.trainIndex; + } + if (this.groupId != null) { + data.groupId = this.groupId; + } + if (this.show != null) { + data.show = this.show; + } + if (this.kilometerCode != null) { + data.kilometerCode = this.kilometerCode; + } + if (this.dir != null) { + data.dir = this.dir; + } + return data; + } + serialize(): Uint8Array; + serialize(w: pb_1.BinaryWriter): void; + serialize(w?: pb_1.BinaryWriter): Uint8Array | void { + const writer = w || new pb_1.BinaryWriter(); + if (this.lineId != 0) + writer.writeInt32(1, this.lineId); + if (this.trainIndex.length) + writer.writeString(2, this.trainIndex); + if (this.groupId.length) + writer.writeString(3, this.groupId); + if (this.show != false) + writer.writeBool(4, this.show); + if (this.kilometerCode != 0) + writer.writeInt64(5, this.kilometerCode); + if (this.dir != 0) + writer.writeInt32(6, this.dir); + if (!w) + return writer.getResultBuffer(); + } + static deserialize(bytes: Uint8Array | pb_1.BinaryReader): WsLineNetTrainOffsetMessage { + const reader = bytes instanceof pb_1.BinaryReader ? bytes : new pb_1.BinaryReader(bytes), message = new WsLineNetTrainOffsetMessage(); + while (reader.nextField()) { + if (reader.isEndGroup()) + break; + switch (reader.getFieldNumber()) { + case 1: + message.lineId = reader.readInt32(); + break; + case 2: + message.trainIndex = reader.readString(); + break; + case 3: + message.groupId = reader.readString(); + break; + case 4: + message.show = reader.readBool(); + break; + case 5: + message.kilometerCode = reader.readInt64(); + break; + case 6: + message.dir = reader.readInt32(); + break; + default: reader.skipField(); + } + } + return message; + } + serializeBinary(): Uint8Array { + return this.serialize(); + } + static deserializeBinary(bytes: Uint8Array): WsLineNetTrainOffsetMessage { + return WsLineNetTrainOffsetMessage.deserialize(bytes); + } + } +} diff --git a/src/quasar.d.ts b/src/quasar.d.ts new file mode 100644 index 0000000..5937f7a --- /dev/null +++ b/src/quasar.d.ts @@ -0,0 +1,9 @@ +/* eslint-disable */ + +// Forces TS to apply `@quasar/app-vite` augmentations of `quasar` package +// Removing this would break `quasar/wrappers` imports as those typings are declared +// into `@quasar/app-vite` +// As a side effect, since `@quasar/app-vite` reference `quasar` to augment it, +// this declaration also apply `quasar` own +// augmentations (eg. adds `$q` into Vue component context) +/// diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..4531114 --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,36 @@ +import { route } from 'quasar/wrappers'; +import { + createMemoryHistory, + createRouter, + createWebHashHistory, + createWebHistory, +} from 'vue-router'; + +import routes from './routes'; + +/* + * If not building with SSR mode, you can + * directly export the Router instantiation; + * + * The function below can be async too; either use + * async/await or return a Promise which resolves + * with the Router instance. + */ + +export default route(function (/* { store, ssrContext } */) { + const createHistory = process.env.SERVER + ? createMemoryHistory + : (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory); + + const Router = createRouter({ + scrollBehavior: () => ({ left: 0, top: 0 }), + routes, + + // Leave this as is and make changes in quasar.conf.js instead! + // quasar.conf.js -> build -> vueRouterMode + // quasar.conf.js -> build -> publicPath + history: createHistory(process.env.VUE_ROUTER_BASE), + }); + + return Router; +}); diff --git a/src/router/routes.ts b/src/router/routes.ts new file mode 100644 index 0000000..b553b77 --- /dev/null +++ b/src/router/routes.ts @@ -0,0 +1,90 @@ +import { RouteRecordRaw } from 'vue-router'; + +const routes: RouteRecordRaw[] = [ + { + path: '/', + name: 'home', + redirect: '/monitor', + component: () => import('layouts/MainLayout.vue'), + children: [{ path: '', component: () => import('pages/IndexPage.vue') }], + }, + + { + path: '/login', + name: 'login', + component: () => import('pages/UserLogin.vue'), + }, + + { + path: '/register', + name: 'register', + component: () => import('pages/UserRegister.vue'), + }, + { + path: '/dataManage', + name: 'dataManage', + component: () => import('layouts/MainLayout.vue'), + children: [ + { + path: 'draft', + name: 'draft', + component: () => import('pages/DraftManage.vue'), + }, + { + path: 'publish', + name: 'publish', + component: () => import('pages/PublishManage.vue'), + }, + { + path: 'lineInfo', + name: 'lineInfo', + component: () => import('pages/LineInfoManage.vue'), + }, + ], + }, + { + path: '/sysManage', + name: 'sysManage', + component: () => import('layouts/MainLayout.vue'), + children: [ + { + path: 'user', + name: 'user', + meta: { + description: '用户管理', + }, + component: () => import('pages/UserManage.vue'), + }, + ], + }, + { + path: '/painting/:id/:type', + name: 'painting', + component: () => import('layouts/DrawLayout.vue'), + }, + { + path: '/linemap/:id/:type', + name: 'linemap', + component: () => import('layouts/LineLayout.vue'), + }, + { + path: '/line/monitor/:lineId', + name: 'linemonitor', + component: () => import('pages/LineMonitorPage.vue'), + }, + { + path: '/monitor', + name: 'monitor', + component: () => import('layouts/MainLayout.vue'), + children: [{ path: '', component: () => import('pages/MonitorPage.vue') }], + }, + + // Always leave this as last one, + // but you can also remove it + { + path: '/:catchAll(.*)*', + component: () => import('pages/ErrorNotFound.vue'), + }, +]; + +export default routes; diff --git a/src/shims-vue.d.ts b/src/shims-vue.d.ts new file mode 100644 index 0000000..4e6894b --- /dev/null +++ b/src/shims-vue.d.ts @@ -0,0 +1,10 @@ +/* eslint-disable */ + +/// + +// Mocks all files ending in `.vue` showing them as plain Vue instances +declare module '*.vue' { + import type { DefineComponent } from 'vue'; + const component: DefineComponent<{}, {}, any>; + export default component; +} diff --git a/src/stores/draw-store.ts b/src/stores/draw-store.ts new file mode 100644 index 0000000..e1a35af --- /dev/null +++ b/src/stores/draw-store.ts @@ -0,0 +1,87 @@ +import { defineStore } from 'pinia'; +import { destroyDrawApp, getDrawApp, initDrawApp } from 'src/drawApp'; +import { DrawAssistant, JlCanvas, JlDrawApp, JlGraphic } from 'src/jl-graphic'; + +export const useDrawStore = defineStore('draw', { + state: () => ({ + drawAssistant: null as DrawAssistant | null, + selectedGraphics: null as JlGraphic[] | null, + draftId: null as number | null, + draftType: 'Line', + oneClickType: '', + }), + getters: { + drawMode: (state) => state.drawAssistant != null, + drawGraphicType: (state) => state.drawAssistant?.type, + drawGraphicName: (state) => state.drawAssistant?.description, + drawGraphicTemplate: (state) => state.drawAssistant?.graphicTemplate, + + selectedGraphicType: (state) => { + if (state.selectedGraphics) { + if (state.selectedGraphics.length === 1) { + return state.selectedGraphics[0].type; + } + } + }, + selectedObjName: (state) => { + if (state.selectedGraphics) { + if (state.selectedGraphics.length == 0) { + return '画布'; + } else if (state.selectedGraphics.length == 1) { + return state.selectedGraphics[0].type; + } + return '多选'; + } + return ''; + }, + selectedGraphic: (state) => { + if (state.selectedGraphics) { + if (state.selectedGraphics.length === 1) { + return state.selectedGraphics[0]; + } + } + return null; + }, + }, + actions: { + getDrawApp(): JlDrawApp { + const app = getDrawApp(); + if (app == null) { + throw new Error('未初始化app'); + } + return app; + }, + getJlCanvas(): JlCanvas { + return this.getDrawApp().canvas; + }, + initDrawApp(dom: HTMLElement) { + const app = initDrawApp(dom); + app.on('interaction-plugin-resume', (plugin) => { + if (plugin.isAppPlugin()) { + if (Object.hasOwn(plugin, '__GraphicDrawAssistant')) { + this.drawAssistant = plugin as DrawAssistant; + } else { + this.drawAssistant = null; + } + } + }); + app.on('graphicselectedchange', () => { + this.selectedGraphics = app.selectedGraphics; + }); + this.selectedGraphics = []; + return app; + }, + destroy() { + // console.log('绘制状态清空,绘制应用销毁'); + this.drawAssistant = null; + this.selectedGraphics = null; + destroyDrawApp(); + }, + setDraftId(id: number | null) { + this.draftId = id; + }, + setDraftType(type: string) { + this.draftType = type; + }, + }, +}); diff --git a/src/stores/example-store.ts b/src/stores/example-store.ts new file mode 100644 index 0000000..83e8390 --- /dev/null +++ b/src/stores/example-store.ts @@ -0,0 +1,15 @@ +import { defineStore } from 'pinia'; + +export const useCounterStore = defineStore('counter', { + state: () => ({ + counter: 0, + }), + getters: { + doubleCount: (state) => state.counter * 2, + }, + actions: { + increment() { + this.counter++; + }, + }, +}); diff --git a/src/stores/index.ts b/src/stores/index.ts new file mode 100644 index 0000000..d30b7cf --- /dev/null +++ b/src/stores/index.ts @@ -0,0 +1,32 @@ +import { store } from 'quasar/wrappers' +import { createPinia } from 'pinia' +import { Router } from 'vue-router'; + +/* + * When adding new properties to stores, you should also + * extend the `PiniaCustomProperties` interface. + * @see https://pinia.vuejs.org/core-concepts/plugins.html#typing-new-store-properties + */ +declare module 'pinia' { + export interface PiniaCustomProperties { + readonly router: Router; + } +} + +/* + * If not building with SSR mode, you can + * directly export the Store instantiation; + * + * The function below can be async too; either use + * async/await or return a Promise which resolves + * with the Store instance. + */ + +export default store((/* { ssrContext } */) => { + const pinia = createPinia() + + // You can add Pinia plugins here + // pinia.use(SomePiniaPlugin) + + return pinia +}) diff --git a/src/stores/line-net-store.ts b/src/stores/line-net-store.ts new file mode 100644 index 0000000..c8fdad6 --- /dev/null +++ b/src/stores/line-net-store.ts @@ -0,0 +1,58 @@ +import { defineStore } from 'pinia'; +import { JlCanvas, JlGraphic, GraphicApp } from 'src/jl-graphic'; +import { + initLineNetApp, + getLineNetApp, + destroyLineNetApp, +} from 'src/drawApp/lineNetApp'; + +export const useLineNetStore = defineStore('lineNet', { + state: () => ({ + selectedGraphics: null as JlGraphic[] | null, + lineNetName: null as string | null, + }), + getters: { + selectedGraphicType: (state) => { + if (state.selectedGraphics) { + if (state.selectedGraphics.length === 1) { + return state.selectedGraphics[0].type; + } + } + }, + selectedGraphic: (state) => { + if (state.selectedGraphics) { + if (state.selectedGraphics.length === 1) { + return state.selectedGraphics[0]; + } + } + return null; + }, + }, + actions: { + getLineNetApp(): GraphicApp { + const app = getLineNetApp(); + if (app == null) { + throw new Error('未初始化app'); + } + return app; + }, + getJlCanvas(): JlCanvas { + return this.getLineNetApp().canvas; + }, + initLineNetApp(dom: HTMLElement) { + const app = initLineNetApp(dom); + app.on('graphicselectedchange', () => { + this.selectedGraphics = app.selectedGraphics; + }); + this.selectedGraphics = []; + return app; + }, + destroy() { + this.selectedGraphics = null; + destroyLineNetApp(); + }, + setLineNetName(name: string | null) { + this.lineNetName = name; + }, + }, +}); diff --git a/src/stores/line-store.ts b/src/stores/line-store.ts new file mode 100644 index 0000000..5a6ae1a --- /dev/null +++ b/src/stores/line-store.ts @@ -0,0 +1,50 @@ +import { defineStore } from 'pinia'; +import { JlCanvas, JlGraphic, GraphicApp } from 'src/jl-graphic'; +import { initLineApp, getLineApp, destroyLineApp } from 'src/drawApp/lineApp'; + +export const useLineStore = defineStore('line', { + state: () => ({ + selectedGraphics: null as JlGraphic[] | null, + lineId: null as number | null, + lineName: null as string | null, + }), + getters: { + selectedGraphicType: (state) => { + if (state.selectedGraphics) { + if (state.selectedGraphics.length === 1) { + return state.selectedGraphics[0].type; + } + } + }, + }, + actions: { + getLineApp(): GraphicApp { + const app = getLineApp(); + if (app == null) { + throw new Error('未初始化app'); + } + return app; + }, + getJlCanvas(): JlCanvas { + return this.getLineApp().canvas; + }, + initLineApp(dom: HTMLElement) { + const app = initLineApp(dom); + app.on('graphicselectedchange', () => { + this.selectedGraphics = app.selectedGraphics; + }); + this.selectedGraphics = []; + return app; + }, + destroy() { + this.selectedGraphics = null; + destroyLineApp(); + }, + setLineId(id: number | null) { + this.lineId = id; + }, + setLineName(name: string | null) { + this.lineName = name; + }, + }, +}); diff --git a/src/stores/store-flag.d.ts b/src/stores/store-flag.d.ts new file mode 100644 index 0000000..7677175 --- /dev/null +++ b/src/stores/store-flag.d.ts @@ -0,0 +1,10 @@ +/* eslint-disable */ +// THIS FEATURE-FLAG FILE IS AUTOGENERATED, +// REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING +import "quasar/dist/types/feature-flag"; + +declare module "quasar/dist/types/feature-flag" { + interface QuasarFeatureFlags { + store: true; + } +} diff --git a/src/utils/CommonNotify.ts b/src/utils/CommonNotify.ts new file mode 100644 index 0000000..aee90fd --- /dev/null +++ b/src/utils/CommonNotify.ts @@ -0,0 +1,38 @@ +import { AxiosError } from 'axios'; +import { Notify } from 'quasar'; + +export function successNotify(message: string) { + Notify.create({ + type: 'positive', + message: message, + }); +} + +export function errorNotify(message: string, error: any): void { + console.error(error); + let errMsg = ''; + if (error instanceof AxiosError) { + errMsg = error.response?.data.errMsg; + } else if (error.data) { + errMsg = error.data.errMsg; + } else if (error.message) { + errMsg = error.message; + } + Notify.create({ + type: 'negative', + message: `${message}: ${errMsg}`, + }); +} + +export function errorDismissNotify( + message: string, + onDismiss: () => void, + error: any +): void { + console.error(error); + Notify.create({ + type: 'negative', + message: message, + onDismiss, + }); +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..483ae96 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@quasar/app-vite/tsconfig-preset", + "compilerOptions": { + "baseUrl": "." + }, + "include": ["src/**/*"], + "exclude": ["/graphic-pixi/*/**.ts"] +} diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..e9656b7 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,3399 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/parser@^7.20.15", "@babel/parser@^7.21.3": + version "7.22.4" + resolved "https://registry.npmmirror.com/@babel/parser/-/parser-7.22.4.tgz" + integrity sha512-VLLsx06XkEYqBtE5YGPwfSGwfrjnyPP5oiGty3S8pQLFDFLaS8VwWSIxkTXpcvr5zeYLE6+MBNl2npl/YnfofA== + +"@esbuild/linux-loong64@0.14.54": + version "0.14.54" + resolved "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz#de2a4be678bd4d0d1ffbb86e6de779cde5999028" + integrity sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw== + +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.3.0": + version "4.4.0" + resolved "https://registry.npmmirror.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0": + version "4.5.1" + resolved "https://registry.npmmirror.com/@eslint-community/regexpp/-/regexpp-4.5.1.tgz" + integrity sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ== + +"@eslint/eslintrc@^2.0.3": + version "2.0.3" + resolved "https://registry.npmmirror.com/@eslint/eslintrc/-/eslintrc-2.0.3.tgz" + integrity sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.5.2" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.41.0": + version "8.41.0" + resolved "https://registry.npmmirror.com/@eslint/js/-/js-8.41.0.tgz" + integrity sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA== + +"@humanwhocodes/config-array@^0.11.8": + version "0.11.8" + resolved "https://registry.npmmirror.com/@humanwhocodes/config-array/-/config-array-0.11.8.tgz" + integrity sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.npmmirror.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.npmmirror.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@jridgewell/sourcemap-codec@^1.4.13": + version "1.4.15" + resolved "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@pixi/accessibility@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/accessibility/-/accessibility-7.2.4.tgz" + integrity sha512-EVjuqUqv9FeYFXCv0S0qj1hgCtbAMNBPCbOGEtiMogpM++/IySxBZvcOYg3rRgo9inwt2s4Bi7kUiqMPD8hItw== + +"@pixi/app@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/app/-/app-7.2.4.tgz" + integrity sha512-eJ2jpu5P28ip07nLItw6sETXn45P4KR/leMJ6zPHRlhT1m8t5zTsWr3jK4Uj8LF2E+6KlPNzLQh5Alf/unn/aQ== + +"@pixi/assets@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/assets/-/assets-7.2.4.tgz" + integrity sha512-7199re3wvMAlVqXLaCyAr8IkJSXqkeVAxcYyB2rBu4Id5m2hhlGX1dQsdMBiCXLwu6/LLVqDvJggSNVQBzL6ZQ== + dependencies: + "@types/css-font-loading-module" "^0.0.7" + +"@pixi/color@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/color/-/color-7.2.4.tgz" + integrity sha512-B/+9JRcXe2uE8wQfsueFRPZVayF2VEMRB7XGeRAsWCryOX19nmWhv0Nt3nOU2rvzI0niz9XgugJXsB6vVmDFSg== + dependencies: + colord "^2.9.3" + +"@pixi/compressed-textures@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/compressed-textures/-/compressed-textures-7.2.4.tgz" + integrity sha512-atnWyw/ot/Wg69qhgskKiuTYCZx15IxV35sa0KyXMthyjyvDLCIvOn0nczM6wCBy9H96SjJbfgynVWhVrip6qw== + +"@pixi/constants@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/constants/-/constants-7.2.4.tgz" + integrity sha512-hKuHBWR6N4Q0Sf5MGF3/9l+POg/G5rqhueHfzofiuelnKg7aBs3BVjjZ+6hZbd6M++vOUmxYelEX/NEFBxrheA== + +"@pixi/core@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/core/-/core-7.2.4.tgz" + integrity sha512-0XtvrfxHlS2T+beBBSpo7GI8+QLyyTqMVQpNmPqB4woYxzrOEJ9JaUFBaBfCvycLeUkfVih1u6HAbtF+2d1EjQ== + dependencies: + "@pixi/color" "7.2.4" + "@pixi/constants" "7.2.4" + "@pixi/extensions" "7.2.4" + "@pixi/math" "7.2.4" + "@pixi/runner" "7.2.4" + "@pixi/settings" "7.2.4" + "@pixi/ticker" "7.2.4" + "@pixi/utils" "7.2.4" + "@types/offscreencanvas" "^2019.6.4" + +"@pixi/display@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/display/-/display-7.2.4.tgz" + integrity sha512-w5tqb8cWEO5qIDaO9GEqRvxYhL0iMk0Wsngw23bbLm1gLEQmrFkB2tpJlRAqd7H82C3DrDDeWvkrrxW6+m4apg== + +"@pixi/events@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/events/-/events-7.2.4.tgz" + integrity sha512-/JtmoB98fzIU8giN9xvlRvmvOi6u4MaD2DnKNOMHkQ1MBraj3pmrXM9fZ0JbNzi+324GraAAY76QidgHjIYoYQ== + +"@pixi/extensions@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/extensions/-/extensions-7.2.4.tgz" + integrity sha512-Mnqv9scbL1ARD3QFKfOWs2aSVJJfP1dL8g5UiqGImYO3rZbz/9QCzXOeMVIZ5n3iaRyKMNhFFr84/zUja2H7Dw== + +"@pixi/extract@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/extract/-/extract-7.2.4.tgz" + integrity sha512-wlXZg+J2L/1jQhRi5nZQP/cXshovhjksjss91eAKMvY5aGxNAQovCP4xotJ/XJjfTvPMpeRzHPFYzm3PrOPQ7g== + +"@pixi/filter-alpha@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/filter-alpha/-/filter-alpha-7.2.4.tgz" + integrity sha512-UTUMSGyktUr+I9vmigqJo9iUhb0nwGyqTTME2xBWZvVGCnl5z+/wHxvIBBCe5pNZ66IM15pGXQ4cDcfqCuP2kA== + +"@pixi/filter-blur@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/filter-blur/-/filter-blur-7.2.4.tgz" + integrity sha512-aLyXIoxy14bTansCPtbY8x7Sdn2OrrqkF/pcKiRXHJGGhi7wPacvB/NcmYJdnI/n2ExQ6V5Njuj/nfrsejVwcA== + +"@pixi/filter-color-matrix@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/filter-color-matrix/-/filter-color-matrix-7.2.4.tgz" + integrity sha512-DFtayybYXoUh73eHUFRK5REbi1t3FZuVUnaQTj+euHKF9L7EaYc3Q9wctpx1WPRcwkqEX50M4SNFhxpA7Pxtaw== + +"@pixi/filter-displacement@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/filter-displacement/-/filter-displacement-7.2.4.tgz" + integrity sha512-Simq3IBJKt7+Gvk4kK7OFkfoeYUMhNhIyATCdeT+Jkdkq5WV7pYnH5hqO0YW7eAHrgjV13yn6t4H/GC4+6LhEA== + +"@pixi/filter-fxaa@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/filter-fxaa/-/filter-fxaa-7.2.4.tgz" + integrity sha512-qzKjdL+Ih18uGTJLg8tT/H+YCsTeGkw2uF7lyKnw/lxGLJQhLWIhM95M9qSNgxbXyW1vp7SbG81a9aAEz2HAhA== + +"@pixi/filter-noise@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/filter-noise/-/filter-noise-7.2.4.tgz" + integrity sha512-QAU9Ybj2ZQrWM9ZEjTTC0iLnQcuyNoZNRinxSbg1G0yacpmsSb9wvV5ltIZ66+hfY+90+u2Nudt/v9g6pvOdGg== + +"@pixi/filter-outline@^5.2.0": + version "5.2.0" + resolved "https://registry.npmmirror.com/@pixi/filter-outline/-/filter-outline-5.2.0.tgz" + integrity sha512-xKfAouhZNKl6A0RvxT5i+2/ean7r16dE/QswwIkbWvr2hhHlp4p9U6XsqdgUERCDxK+IZibMAumbWs4DGxOUeQ== + +"@pixi/graphics-extras@^7.2.4": + version "7.2.4" + resolved "https://registry.yarnpkg.com/@pixi/graphics-extras/-/graphics-extras-7.2.4.tgz#72ac967992f239d3671d6e680ac891471619fe07" + integrity sha512-0yT91yqF3KLiZI/iLRcfcYlTVpkVyWsfGtWEIorZs0eX+/zYx7um7EJ2h7tFORI/1FxA2maR4td5vpgCwOLJAQ== + +"@pixi/graphics@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/graphics/-/graphics-7.2.4.tgz" + integrity sha512-3A2EumTjWJgXlDLOyuBrl9b6v1Za/E+/IjOGUIX843HH4NYaf1a2sfDfljx6r3oiDvy+VhuBFmgynRcV5IyA0Q== + +"@pixi/math@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/math/-/math-7.2.4.tgz" + integrity sha512-LJB+mozyEPllxa0EssFZrKNfVwysfaBun4b2dJKQQInp0DafgbA0j7A+WVg0oe51KhFULTJMpDqbLn/ITFc41A== + +"@pixi/mesh-extras@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/mesh-extras/-/mesh-extras-7.2.4.tgz" + integrity sha512-Lxqq/1E2EmDgjZX8KzjhBy3VvITIQ00arr2ikyHYF1d0XtQTKEYpr8VKzhchqZ5/9DuyTDbDMYGhcxoNXQmZrQ== + +"@pixi/mesh@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/mesh/-/mesh-7.2.4.tgz" + integrity sha512-wiALIqcRKib2BqeH9kOA5fOKWN352nqAspgbDa8gA7OyWzmNwqIedIlElixd0oLFOrIN5jOZAdzeKnoYQlt9Aw== + +"@pixi/mixin-cache-as-bitmap@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/mixin-cache-as-bitmap/-/mixin-cache-as-bitmap-7.2.4.tgz" + integrity sha512-95L/9nzfLHw6GoeqqRl/RjSloKvRt0xrc2inCmjMZvMsFUEtHN2F8IWd1k5vcv0S+83NCreFkJg6nJm1m5AZqg== + +"@pixi/mixin-get-child-by-name@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/mixin-get-child-by-name/-/mixin-get-child-by-name-7.2.4.tgz" + integrity sha512-9g17KgSBEEhkinnKk4dqmxagzHOCPSTvGB6lOopBq4yyXmr/2WVv+QGjuzE0O+p80szQeBJjPBQxzrfBILaSRw== + +"@pixi/mixin-get-global-position@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/mixin-get-global-position/-/mixin-get-global-position-7.2.4.tgz" + integrity sha512-UrAUF2BXCeWtFgR2m+er41Ky7zShT7r228cZkB6ZfYwMeThhwqG5mH68UeCyP6p68JMpT1gjI2DPfeSRY3ecnA== + +"@pixi/particle-container@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/particle-container/-/particle-container-7.2.4.tgz" + integrity sha512-tpSzilZGFtAoi8XhzL0TecLPNRQAbY8nWV9XNGXJDw+nxXp18GCe8L6eEmnHLlAug67BRHl65DtrdvTknPX+4g== + +"@pixi/prepare@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/prepare/-/prepare-7.2.4.tgz" + integrity sha512-Yff5Sh4kTLdKc5VkkM44LW9gpj7Izw8ns3P1TzWxqeGjzPZ3folr/tQujGL+Qw+8A9VESp+hX9MSIHyw+jpyrg== + +"@pixi/runner@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/runner/-/runner-7.2.4.tgz" + integrity sha512-YtyqPk1LA+0guEFKSFx6t/YSvbEQwajFwi4Ft8iDhioa6VK2MmTir1GjWwy7JQYLcDmYSAcQjnmFtVTZohyYSw== + +"@pixi/settings@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/settings/-/settings-7.2.4.tgz" + integrity sha512-ZPKRar9EwibijGmH8EViu4Greq1I/O7V/xQx2rNqN23XA7g09Qo6yfaeQpufu5xl8+/lZrjuHtQSnuY7OgG1CA== + dependencies: + "@pixi/constants" "7.2.4" + "@types/css-font-loading-module" "^0.0.7" + ismobilejs "^1.1.0" + +"@pixi/sprite-animated@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/sprite-animated/-/sprite-animated-7.2.4.tgz" + integrity sha512-9eRriPSC0QVS7U9zQlrG3uEI5+h3fi+mqofXy+yjk1sGCmXSIJME5p2wg2mzxoJk3qkSMagQA9QHtL26Fti8Iw== + +"@pixi/sprite-tiling@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/sprite-tiling/-/sprite-tiling-7.2.4.tgz" + integrity sha512-nGfxQoACRx49dUN0oW1vFm3141M+7gkAbzoNJym2Pljd2dpLME9fb5E6Lyahu0yWMaPRhhGorn6z9VIGmTF3Jw== + +"@pixi/sprite@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/sprite/-/sprite-7.2.4.tgz" + integrity sha512-DhR1B+/d0eXpxHIesJMXcVPrKFwQ+zRA1LvEIFfzewqfaRN3X6PMIuoKX8SIb6tl+Hq8Ba9Pe28zI7d2rmRzrA== + +"@pixi/spritesheet@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/spritesheet/-/spritesheet-7.2.4.tgz" + integrity sha512-LNmlavyiMQeCF0U4S+yhzxUYmPmat6EpLjLnkGukQTZV5CZkxDCVgXM9uKoRF2DvNydj4yuwZ6+JjK8QssHI8Q== + +"@pixi/text-bitmap@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/text-bitmap/-/text-bitmap-7.2.4.tgz" + integrity sha512-3u2CP4VN+muCaq/jtj7gn0hb3DET/X2S04zTBcgc2WVGufJc62yz+UDzS9jC+ellotVdt9c8U74++vpz3zJGfw== + +"@pixi/text-html@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/text-html/-/text-html-7.2.4.tgz" + integrity sha512-0NfLAE/w51ZtatxVqLvDS62iO0VLKsSdctqTAVv4Zlgdk9TKJmX1WUucHJboTvbm2SbDjNDGfZ6qXM5nAslIDQ== + +"@pixi/text@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/text/-/text-7.2.4.tgz" + integrity sha512-DGu7ktpe+zHhqR2sG9NsJt4mgvSObv5EqXTtUxD4Z0li1gmqF7uktpLyn5I6vSg1TTEL4TECClRDClVDGiykWw== + +"@pixi/ticker@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/ticker/-/ticker-7.2.4.tgz" + integrity sha512-hQQHIHvGeFsP4GNezZqjzuhUgNQEVgCH9+qU05UX1Mc5UHC9l6OJnY4VTVhhcHxZjA6RnyaY+1zBxCnoXuazpg== + dependencies: + "@pixi/extensions" "7.2.4" + "@pixi/settings" "7.2.4" + "@pixi/utils" "7.2.4" + +"@pixi/utils@7.2.4": + version "7.2.4" + resolved "https://registry.npmmirror.com/@pixi/utils/-/utils-7.2.4.tgz" + integrity sha512-VUGQHBOINIS4ePzoqafwxaGPVRTa3oM/mEutIIHbNGI3b+QvSO+1Dnk40M0zcH6Bo+MxQZbOZK5X/wO9oU5+LQ== + dependencies: + "@pixi/color" "7.2.4" + "@pixi/constants" "7.2.4" + "@pixi/settings" "7.2.4" + "@types/earcut" "^2.1.0" + earcut "^2.2.4" + eventemitter3 "^4.0.0" + url "^0.11.0" + +"@quasar/app-vite@^1.0.0": + version "1.4.3" + resolved "https://registry.npmmirror.com/@quasar/app-vite/-/app-vite-1.4.3.tgz" + integrity sha512-5iMs1sk6fyYTFoRVySwFXWL/PS23UEsdk+YSFejhXnSs5fVDmb2GQMguCHwDl3jPIHjZ7A+XKkb2iWx9pjiPXw== + dependencies: + "@quasar/render-ssr-error" "^1.0.1" + "@quasar/vite-plugin" "^1.3.3" + "@rollup/pluginutils" "^4.1.2" + "@types/chrome" "^0.0.208" + "@types/compression" "^1.7.2" + "@types/cordova" "0.0.34" + "@types/express" "^4.17.13" + "@vitejs/plugin-vue" "^2.2.0" + archiver "^5.3.0" + chokidar "^3.5.3" + ci-info "^3.7.1" + compression "^1.7.4" + cross-spawn "^7.0.3" + dot-prop "6.0.1" + elementtree "0.1.7" + esbuild "0.14.51" + express "^4.17.3" + fast-glob "3.2.12" + fs-extra "^11.1.0" + html-minifier "^4.0.0" + inquirer "^8.2.1" + isbinaryfile "^5.0.0" + kolorist "^1.5.1" + lodash "^4.17.21" + minimist "^1.2.6" + open "^8.4.0" + register-service-worker "^1.7.2" + rollup-plugin-visualizer "^5.5.4" + sass "1.32.12" + semver "^7.3.5" + serialize-javascript "^6.0.0" + table "^6.8.0" + vite "^2.9.13" + webpack-merge "^5.8.0" + +"@quasar/extras@^1.0.0": + version "1.16.4" + resolved "https://registry.npmmirror.com/@quasar/extras/-/extras-1.16.4.tgz" + integrity sha512-q2kPTNHI5aprgE2yQfRIf6aud+qSXH3YTNmhcfRp/rENh7kRjoM+b5BBPxgHlO1si1ARddbmr+Fxu/L05hfXnQ== + +"@quasar/render-ssr-error@^1.0.1": + version "1.0.1" + resolved "https://registry.npmmirror.com/@quasar/render-ssr-error/-/render-ssr-error-1.0.1.tgz" + integrity sha512-4Shxl079hew/yZnIsDtWpRD8enOmqMjMu/s2bkGN0QBvlsRkpWv9pwOz5geJXZxBa17q1S4txvByBxkhPfhWaQ== + dependencies: + stack-trace "^1.0.0-pre2" + +"@quasar/vite-plugin@^1.3.3": + version "1.3.3" + resolved "https://registry.npmmirror.com/@quasar/vite-plugin/-/vite-plugin-1.3.3.tgz" + integrity sha512-HSX/Vgec5/Y8fiJRfpf1MR7+um+rdpbilktBGQkYOKw4A9d0smGq4jtSS/K4O2GTXRYqDmZ/5sgCeBcmhB3OCw== + +"@rollup/pluginutils@^4.1.2": + version "4.2.1" + resolved "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz" + integrity sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ== + dependencies: + estree-walker "^2.0.1" + picomatch "^2.2.2" + +"@stomp/stompjs@^7.0.0": + version "7.0.0" + resolved "https://registry.npmmirror.com/@stomp/stompjs/-/stompjs-7.0.0.tgz" + integrity sha512-fGdq4wPDnSV/KyOsjq4P+zLc8MFWC3lMmP5FBgLWKPJTYcuCbAIrnRGjB7q2jHZdYCOD5vxLuFoKIYLy5/u8Pw== + +"@types/body-parser@*": + version "1.19.2" + resolved "https://registry.npmmirror.com/@types/body-parser/-/body-parser-1.19.2.tgz" + integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/chrome@^0.0.208": + version "0.0.208" + resolved "https://registry.npmmirror.com/@types/chrome/-/chrome-0.0.208.tgz" + integrity sha512-VDU/JnXkF5qaI7WBz14Azpa2VseZTgML0ia/g/B1sr9OfdOnHiH/zZ7P7qCDqxSlkqJh76/bPc8jLFcx8rHJmw== + dependencies: + "@types/filesystem" "*" + "@types/har-format" "*" + +"@types/compression@^1.7.2": + version "1.7.2" + resolved "https://registry.npmmirror.com/@types/compression/-/compression-1.7.2.tgz" + integrity sha512-lwEL4M/uAGWngWFLSG87ZDr2kLrbuR8p7X+QZB1OQlT+qkHsCPDVFnHPyXf4Vyl4yDDorNY+mAhosxkCvppatg== + dependencies: + "@types/express" "*" + +"@types/connect@*": + version "3.4.35" + resolved "https://registry.npmmirror.com/@types/connect/-/connect-3.4.35.tgz" + integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + dependencies: + "@types/node" "*" + +"@types/cordova@0.0.34": + version "0.0.34" + resolved "https://registry.npmmirror.com/@types/cordova/-/cordova-0.0.34.tgz" + integrity sha512-rkiiTuf/z2wTd4RxFOb+clE7PF4AEJU0hsczbUdkHHBtkUmpWQpEddynNfJYKYtZFJKbq4F+brfekt1kx85IZA== + +"@types/css-font-loading-module@^0.0.7": + version "0.0.7" + resolved "https://registry.npmmirror.com/@types/css-font-loading-module/-/css-font-loading-module-0.0.7.tgz" + integrity sha512-nl09VhutdjINdWyXxHWN/w9zlNCfr60JUqJbd24YXUuCwgeL0TpFSdElCwb6cxfB6ybE19Gjj4g0jsgkXxKv1Q== + +"@types/earcut@^2.1.0": + version "2.1.1" + resolved "https://registry.npmmirror.com/@types/earcut/-/earcut-2.1.1.tgz" + integrity sha512-w8oigUCDjElRHRRrMvn/spybSMyX8MTkKA5Dv+tS1IE/TgmNZPqUYtvYBXGY8cieSE66gm+szeK+bnbxC2xHTQ== + +"@types/express-serve-static-core@^4.17.33": + version "4.17.35" + resolved "https://registry.npmmirror.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz" + integrity sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + "@types/send" "*" + +"@types/express@*", "@types/express@^4.17.13": + version "4.17.17" + resolved "https://registry.npmmirror.com/@types/express/-/express-4.17.17.tgz" + integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.33" + "@types/qs" "*" + "@types/serve-static" "*" + +"@types/filesystem@*": + version "0.0.32" + resolved "https://registry.npmmirror.com/@types/filesystem/-/filesystem-0.0.32.tgz" + integrity sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ== + dependencies: + "@types/filewriter" "*" + +"@types/filewriter@*": + version "0.0.29" + resolved "https://registry.npmmirror.com/@types/filewriter/-/filewriter-0.0.29.tgz" + integrity sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ== + +"@types/google-protobuf@^3.15.6": + version "3.15.6" + resolved "https://registry.npmmirror.com/@types/google-protobuf/-/google-protobuf-3.15.6.tgz" + integrity sha512-pYVNNJ+winC4aek+lZp93sIKxnXt5qMkuKmaqS3WGuTq0Bw1ZDYNBgzG5kkdtwcv+GmYJGo3yEg6z2cKKAiEdw== + +"@types/har-format@*": + version "1.2.10" + resolved "https://registry.npmmirror.com/@types/har-format/-/har-format-1.2.10.tgz" + integrity sha512-o0J30wqycjF5miWDKYKKzzOU1ZTLuA42HZ4HE7/zqTOc/jTLdQ5NhYWvsRQo45Nfi1KHoRdNhteSI4BAxTF1Pg== + +"@types/json-schema@^7.0.9": + version "7.0.12" + resolved "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.12.tgz" + integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== + +"@types/mime@*": + version "3.0.1" + resolved "https://registry.npmmirror.com/@types/mime/-/mime-3.0.1.tgz" + integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== + +"@types/mime@^1": + version "1.3.2" + resolved "https://registry.npmmirror.com/@types/mime/-/mime-1.3.2.tgz" + integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== + +"@types/node@*": + version "20.2.5" + resolved "https://registry.npmmirror.com/@types/node/-/node-20.2.5.tgz" + integrity sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ== + +"@types/node@^12.20.21": + version "12.20.55" + resolved "https://registry.npmmirror.com/@types/node/-/node-12.20.55.tgz" + integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== + +"@types/offscreencanvas@^2019.6.4": + version "2019.7.0" + resolved "https://registry.npmmirror.com/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz" + integrity sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg== + +"@types/qs@*": + version "6.9.7" + resolved "https://registry.npmmirror.com/@types/qs/-/qs-6.9.7.tgz" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/range-parser@*": + version "1.2.4" + resolved "https://registry.npmmirror.com/@types/range-parser/-/range-parser-1.2.4.tgz" + integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + +"@types/semver@^7.3.12": + version "7.5.0" + resolved "https://registry.npmmirror.com/@types/semver/-/semver-7.5.0.tgz" + integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== + +"@types/send@*": + version "0.17.1" + resolved "https://registry.npmmirror.com/@types/send/-/send-0.17.1.tgz" + integrity sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + +"@types/serve-static@*": + version "1.15.1" + resolved "https://registry.npmmirror.com/@types/serve-static/-/serve-static-1.15.1.tgz" + integrity sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ== + dependencies: + "@types/mime" "*" + "@types/node" "*" + +"@typescript-eslint/eslint-plugin@^5.10.0": + version "5.59.8" + resolved "https://registry.npmmirror.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.8.tgz" + integrity sha512-JDMOmhXteJ4WVKOiHXGCoB96ADWg9q7efPWHRViT/f09bA8XOMLAVHHju3l0MkZnG1izaWXYmgvQcUjTRcpShQ== + dependencies: + "@eslint-community/regexpp" "^4.4.0" + "@typescript-eslint/scope-manager" "5.59.8" + "@typescript-eslint/type-utils" "5.59.8" + "@typescript-eslint/utils" "5.59.8" + debug "^4.3.4" + grapheme-splitter "^1.0.4" + ignore "^5.2.0" + natural-compare-lite "^1.4.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/parser@^5.10.0": + version "5.59.8" + resolved "https://registry.npmmirror.com/@typescript-eslint/parser/-/parser-5.59.8.tgz" + integrity sha512-AnR19RjJcpjoeGojmwZtCwBX/RidqDZtzcbG3xHrmz0aHHoOcbWnpDllenRDmDvsV0RQ6+tbb09/kyc+UT9Orw== + dependencies: + "@typescript-eslint/scope-manager" "5.59.8" + "@typescript-eslint/types" "5.59.8" + "@typescript-eslint/typescript-estree" "5.59.8" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.59.8": + version "5.59.8" + resolved "https://registry.npmmirror.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.8.tgz" + integrity sha512-/w08ndCYI8gxGf+9zKf1vtx/16y8MHrZs5/tnjHhMLNSixuNcJavSX4wAiPf4aS5x41Es9YPCn44MIe4cxIlig== + dependencies: + "@typescript-eslint/types" "5.59.8" + "@typescript-eslint/visitor-keys" "5.59.8" + +"@typescript-eslint/type-utils@5.59.8": + version "5.59.8" + resolved "https://registry.npmmirror.com/@typescript-eslint/type-utils/-/type-utils-5.59.8.tgz" + integrity sha512-+5M518uEIHFBy3FnyqZUF3BMP+AXnYn4oyH8RF012+e7/msMY98FhGL5SrN29NQ9xDgvqCgYnsOiKp1VjZ/fpA== + dependencies: + "@typescript-eslint/typescript-estree" "5.59.8" + "@typescript-eslint/utils" "5.59.8" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.59.8": + version "5.59.8" + resolved "https://registry.npmmirror.com/@typescript-eslint/types/-/types-5.59.8.tgz" + integrity sha512-+uWuOhBTj/L6awoWIg0BlWy0u9TyFpCHrAuQ5bNfxDaZ1Ppb3mx6tUigc74LHcbHpOHuOTOJrBoAnhdHdaea1w== + +"@typescript-eslint/typescript-estree@5.59.8": + version "5.59.8" + resolved "https://registry.npmmirror.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.8.tgz" + integrity sha512-Jy/lPSDJGNow14vYu6IrW790p7HIf/SOV1Bb6lZ7NUkLc2iB2Z9elESmsaUtLw8kVqogSbtLH9tut5GCX1RLDg== + dependencies: + "@typescript-eslint/types" "5.59.8" + "@typescript-eslint/visitor-keys" "5.59.8" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.59.8": + version "5.59.8" + resolved "https://registry.npmmirror.com/@typescript-eslint/utils/-/utils-5.59.8.tgz" + integrity sha512-Tr65630KysnNn9f9G7ROF3w1b5/7f6QVCJ+WK9nhIocWmx9F+TmCAcglF26Vm7z8KCTwoKcNEBZrhlklla3CKg== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.59.8" + "@typescript-eslint/types" "5.59.8" + "@typescript-eslint/typescript-estree" "5.59.8" + eslint-scope "^5.1.1" + semver "^7.3.7" + +"@typescript-eslint/visitor-keys@5.59.8": + version "5.59.8" + resolved "https://registry.npmmirror.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.8.tgz" + integrity sha512-pJhi2ms0x0xgloT7xYabil3SGGlojNNKjK/q6dB3Ey0uJLMjK2UDGJvHieiyJVW/7C3KI+Z4Q3pEHkm4ejA+xQ== + dependencies: + "@typescript-eslint/types" "5.59.8" + eslint-visitor-keys "^3.3.0" + +"@vitejs/plugin-vue@^2.2.0": + version "2.3.4" + resolved "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-2.3.4.tgz" + integrity sha512-IfFNbtkbIm36O9KB8QodlwwYvTEsJb4Lll4c2IwB3VHc2gie2mSPtSzL0eYay7X2jd/2WX02FjSGTWR6OPr/zg== + +"@vue/compiler-core@3.3.4": + version "3.3.4" + resolved "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.3.4.tgz" + integrity sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g== + dependencies: + "@babel/parser" "^7.21.3" + "@vue/shared" "3.3.4" + estree-walker "^2.0.2" + source-map-js "^1.0.2" + +"@vue/compiler-dom@3.3.4": + version "3.3.4" + resolved "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz" + integrity sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w== + dependencies: + "@vue/compiler-core" "3.3.4" + "@vue/shared" "3.3.4" + +"@vue/compiler-sfc@3.3.4": + version "3.3.4" + resolved "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz" + integrity sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ== + dependencies: + "@babel/parser" "^7.20.15" + "@vue/compiler-core" "3.3.4" + "@vue/compiler-dom" "3.3.4" + "@vue/compiler-ssr" "3.3.4" + "@vue/reactivity-transform" "3.3.4" + "@vue/shared" "3.3.4" + estree-walker "^2.0.2" + magic-string "^0.30.0" + postcss "^8.1.10" + source-map-js "^1.0.2" + +"@vue/compiler-ssr@3.3.4": + version "3.3.4" + resolved "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz" + integrity sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ== + dependencies: + "@vue/compiler-dom" "3.3.4" + "@vue/shared" "3.3.4" + +"@vue/devtools-api@^6.5.0": + version "6.5.0" + resolved "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.5.0.tgz" + integrity sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q== + +"@vue/reactivity-transform@3.3.4": + version "3.3.4" + resolved "https://registry.npmmirror.com/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz" + integrity sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw== + dependencies: + "@babel/parser" "^7.20.15" + "@vue/compiler-core" "3.3.4" + "@vue/shared" "3.3.4" + estree-walker "^2.0.2" + magic-string "^0.30.0" + +"@vue/reactivity@3.3.4": + version "3.3.4" + resolved "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.3.4.tgz" + integrity sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ== + dependencies: + "@vue/shared" "3.3.4" + +"@vue/runtime-core@3.3.4": + version "3.3.4" + resolved "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.3.4.tgz" + integrity sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA== + dependencies: + "@vue/reactivity" "3.3.4" + "@vue/shared" "3.3.4" + +"@vue/runtime-dom@3.3.4": + version "3.3.4" + resolved "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.3.4.tgz" + integrity sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ== + dependencies: + "@vue/runtime-core" "3.3.4" + "@vue/shared" "3.3.4" + csstype "^3.1.1" + +"@vue/server-renderer@3.3.4": + version "3.3.4" + resolved "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.3.4.tgz" + integrity sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ== + dependencies: + "@vue/compiler-ssr" "3.3.4" + "@vue/shared" "3.3.4" + +"@vue/shared@3.3.4": + version "3.3.4" + resolved "https://registry.npmmirror.com/@vue/shared/-/shared-3.3.4.tgz" + integrity sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ== + +accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.npmmirror.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.8.0: + version "8.8.2" + resolved "https://registry.npmmirror.com/acorn/-/acorn-8.8.2.tgz" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.npmmirror.com/ajv/-/ajv-6.12.6.tgz" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^8.0.1: + version "8.12.0" + resolved "https://registry.npmmirror.com/ajv/-/ajv-8.12.0.tgz" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +archiver-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/archiver-utils/-/archiver-utils-2.1.0.tgz" + integrity sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw== + dependencies: + glob "^7.1.4" + graceful-fs "^4.2.0" + lazystream "^1.0.0" + lodash.defaults "^4.2.0" + lodash.difference "^4.5.0" + lodash.flatten "^4.4.0" + lodash.isplainobject "^4.0.6" + lodash.union "^4.6.0" + normalize-path "^3.0.0" + readable-stream "^2.0.0" + +archiver@^5.3.0: + version "5.3.1" + resolved "https://registry.npmmirror.com/archiver/-/archiver-5.3.1.tgz" + integrity sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w== + dependencies: + archiver-utils "^2.1.0" + async "^3.2.3" + buffer-crc32 "^0.2.1" + readable-stream "^3.6.0" + readdir-glob "^1.0.0" + tar-stream "^2.2.0" + zip-stream "^4.1.0" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.npmmirror.com/argparse/-/argparse-2.0.1.tgz" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.npmmirror.com/array-flatten/-/array-flatten-1.1.1.tgz" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/array-union/-/array-union-2.1.0.tgz" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/astral-regex/-/astral-regex-2.0.0.tgz" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +async@^3.2.3: + version "3.2.4" + resolved "https://registry.npmmirror.com/async/-/async-3.2.4.tgz" + integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +autoprefixer@^10.4.2: + version "10.4.14" + resolved "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.14.tgz" + integrity sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ== + dependencies: + browserslist "^4.21.5" + caniuse-lite "^1.0.30001464" + fraction.js "^4.2.0" + normalize-range "^0.1.2" + picocolors "^1.0.0" + postcss-value-parser "^4.2.0" + +axios@^1.2.1: + version "1.4.0" + resolved "https://registry.npmmirror.com/axios/-/axios-1.4.0.tgz" + integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.2.0.tgz" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +bl@^4.0.3, bl@^4.1.0: + version "4.1.0" + resolved "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +body-parser@1.20.1: + version "1.20.1" + resolved "https://registry.npmmirror.com/body-parser/-/body-parser-1.20.1.tgz" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/boolbase/-/boolbase-1.0.0.tgz" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.2, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.npmmirror.com/braces/-/braces-3.0.2.tgz" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browserslist@^4.21.5: + version "4.21.7" + resolved "https://registry.npmmirror.com/browserslist/-/browserslist-4.21.7.tgz" + integrity sha512-BauCXrQ7I2ftSqd2mvKHGo85XR0u7Ru3C/Hxsy/0TkfCtjrmAbPdzLGasmoiBxplpDXlPvdjX9u7srIMfgasNA== + dependencies: + caniuse-lite "^1.0.30001489" + electron-to-chromium "^1.4.411" + node-releases "^2.0.12" + update-browserslist-db "^1.0.11" + +buffer-crc32@^0.2.1, buffer-crc32@^0.2.13: + version "0.2.13" + resolved "https://registry.npmmirror.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz" + integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== + +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/bytes/-/bytes-3.0.0.tgz" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.2.tgz" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.npmmirror.com/callsites/-/callsites-3.1.0.tgz" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camel-case@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/camel-case/-/camel-case-3.0.0.tgz" + integrity sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w== + dependencies: + no-case "^2.2.0" + upper-case "^1.1.1" + +caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001489: + version "1.0.30001489" + resolved "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001489.tgz" + integrity sha512-x1mgZEXK8jHIfAxm+xgdpHpk50IN3z3q3zP261/WS+uvePxW8izXuCu6AHz0lkuYTlATDehiZ/tNyYBdSQsOUQ== + +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1: + version "4.1.2" + resolved "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.npmmirror.com/chardet/-/chardet-0.7.0.tgz" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.npmmirror.com/chokidar/-/chokidar-3.5.3.tgz" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +ci-info@^3.7.1: + version "3.8.0" + resolved "https://registry.npmmirror.com/ci-info/-/ci-info-3.8.0.tgz" + integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== + +clean-css@^4.2.1: + version "4.2.4" + resolved "https://registry.npmmirror.com/clean-css/-/clean-css-4.2.4.tgz" + integrity sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A== + dependencies: + source-map "~0.6.0" + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-3.1.0.tgz" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-spinners@^2.5.0: + version "2.9.0" + resolved "https://registry.npmmirror.com/cli-spinners/-/cli-spinners-2.9.0.tgz" + integrity sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g== + +cli-width@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/cli-width/-/cli-width-3.0.0.tgz" + integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.npmmirror.com/clone-deep/-/clone-deep-4.0.1.tgz" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.npmmirror.com/clone/-/clone-1.0.4.tgz" + integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colord@^2.9.3: + version "2.9.3" + resolved "https://registry.npmmirror.com/colord/-/colord-2.9.3.tgz" + integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@^2.19.0: + version "2.20.3" + resolved "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +compress-commons@^4.1.0: + version "4.1.1" + resolved "https://registry.npmmirror.com/compress-commons/-/compress-commons-4.1.1.tgz" + integrity sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ== + dependencies: + buffer-crc32 "^0.2.13" + crc32-stream "^4.0.2" + normalize-path "^3.0.0" + readable-stream "^3.6.0" + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.npmmirror.com/compressible/-/compressible-2.0.18.tgz" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.4: + version "1.7.4" + resolved "https://registry.npmmirror.com/compression/-/compression-1.7.4.tgz" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.4.tgz" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4: + version "1.0.5" + resolved "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.npmmirror.com/cookie-signature/-/cookie-signature-1.0.6.tgz" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.npmmirror.com/cookie/-/cookie-0.5.0.tgz" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + +crc-32@^1.2.0: + version "1.2.2" + resolved "https://registry.npmmirror.com/crc-32/-/crc-32-1.2.2.tgz" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + +crc32-stream@^4.0.2: + version "4.0.2" + resolved "https://registry.npmmirror.com/crc32-stream/-/crc32-stream-4.0.2.tgz" + integrity sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w== + dependencies: + crc-32 "^1.2.0" + readable-stream "^3.4.0" + +cross-spawn@^7.0.2, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +csstype@^3.1.1: + version "3.1.2" + resolved "https://registry.npmmirror.com/csstype/-/csstype-3.1.2.tgz" + integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ== + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.npmmirror.com/debug/-/debug-4.3.4.tgz" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +defaults@^1.0.3: + version "1.0.4" + resolved "https://registry.npmmirror.com/defaults/-/defaults-1.0.4.tgz" + integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A== + dependencies: + clone "^1.0.2" + +define-lazy-prop@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz" + integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/doctrine/-/doctrine-3.0.0.tgz" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dot-prop@6.0.1: + version "6.0.1" + resolved "https://registry.npmmirror.com/dot-prop/-/dot-prop-6.0.1.tgz" + integrity sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA== + dependencies: + is-obj "^2.0.0" + +earcut@^2.2.4: + version "2.2.4" + resolved "https://registry.npmmirror.com/earcut/-/earcut-2.2.4.tgz" + integrity sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ== + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +electron-to-chromium@^1.4.411: + version "1.4.413" + resolved "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.413.tgz" + integrity sha512-Gd+/OAhRca06dkVxIQo/W7dr6Nmk9cx6lQdZ19GvFp51k5B/lUAokm6SJfNkdV8kFLsC3Z4sLTyEHWCnB1Efbw== + +elementtree@0.1.7: + version "0.1.7" + resolved "https://registry.npmmirror.com/elementtree/-/elementtree-0.1.7.tgz" + integrity sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg== + dependencies: + sax "1.1.4" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +end-of-stream@^1.4.1: + version "1.4.4" + resolved "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.4.tgz" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +esbuild-android-64@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-android-64/-/esbuild-android-64-0.14.51.tgz#414a087cb0de8db1e347ecca6c8320513de433db" + integrity sha512-6FOuKTHnC86dtrKDmdSj2CkcKF8PnqkaIXqvgydqfJmqBazCPdw+relrMlhGjkvVdiiGV70rpdnyFmA65ekBCQ== + +esbuild-android-64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz#505f41832884313bbaffb27704b8bcaa2d8616be" + integrity sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ== + +esbuild-android-arm64@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.51.tgz#55de3bce2aab72bcd2b606da4318ad00fb9c8151" + integrity sha512-vBtp//5VVkZWmYYvHsqBRCMMi1MzKuMIn5XDScmnykMTu9+TD9v0NMEDqQxvtFToeYmojdo5UCV2vzMQWJcJ4A== + +esbuild-android-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz#8ce69d7caba49646e009968fe5754a21a9871771" + integrity sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg== + +esbuild-darwin-64@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.51.tgz#4259f23ed6b4cea2ec8a28d87b7fb9801f093754" + integrity sha512-YFmXPIOvuagDcwCejMRtCDjgPfnDu+bNeh5FU2Ryi68ADDVlWEpbtpAbrtf/lvFTWPexbgyKgzppNgsmLPr8PA== + +esbuild-darwin-64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz#24ba67b9a8cb890a3c08d9018f887cc221cdda25" + integrity sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug== + +esbuild-darwin-arm64@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.51.tgz#d77b4366a71d84e530ba019d540b538b295d494a" + integrity sha512-juYD0QnSKwAMfzwKdIF6YbueXzS6N7y4GXPDeDkApz/1RzlT42mvX9jgNmyOlWKN7YzQAYbcUEJmZJYQGdf2ow== + +esbuild-darwin-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz#3f7cdb78888ee05e488d250a2bdaab1fa671bf73" + integrity sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw== + +esbuild-freebsd-64@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.51.tgz#27b6587b3639f10519c65e07219d249b01f2ad38" + integrity sha512-cLEI/aXjb6vo5O2Y8rvVSQ7smgLldwYY5xMxqh/dQGfWO+R1NJOFsiax3IS4Ng300SVp7Gz3czxT6d6qf2cw0g== + +esbuild-freebsd-64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz#09250f997a56ed4650f3e1979c905ffc40bbe94d" + integrity sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg== + +esbuild-freebsd-arm64@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.51.tgz#63c435917e566808c71fafddc600aca4d78be1ec" + integrity sha512-TcWVw/rCL2F+jUgRkgLa3qltd5gzKjIMGhkVybkjk6PJadYInPtgtUBp1/hG+mxyigaT7ib+od1Xb84b+L+1Mg== + +esbuild-freebsd-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz#bafb46ed04fc5f97cbdb016d86947a79579f8e48" + integrity sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q== + +esbuild-linux-32@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-linux-32/-/esbuild-linux-32-0.14.51.tgz#c3da774143a37e7f11559b9369d98f11f997a5d9" + integrity sha512-RFqpyC5ChyWrjx8Xj2K0EC1aN0A37H6OJfmUXIASEqJoHcntuV3j2Efr9RNmUhMfNE6yEj2VpYuDteZLGDMr0w== + +esbuild-linux-32@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz#e2a8c4a8efdc355405325033fcebeb941f781fe5" + integrity sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw== + +esbuild-linux-64@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-linux-64/-/esbuild-linux-64-0.14.51.tgz" + integrity sha512-dxjhrqo5i7Rq6DXwz5v+MEHVs9VNFItJmHBe1CxROWNf4miOGoQhqSG8StStbDkQ1Mtobg6ng+4fwByOhoQoeA== + +esbuild-linux-64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz" + integrity sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg== + +esbuild-linux-arm64@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.51.tgz#dac84740516e859d8b14e1ecc478dd5241b10c93" + integrity sha512-D9rFxGutoqQX3xJPxqd6o+kvYKeIbM0ifW2y0bgKk5HPgQQOo2k9/2Vpto3ybGYaFPCE5qTGtqQta9PoP6ZEzw== + +esbuild-linux-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz#dae4cd42ae9787468b6a5c158da4c84e83b0ce8b" + integrity sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig== + +esbuild-linux-arm@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.51.tgz#b3ae7000696cd53ed95b2b458554ff543a60e106" + integrity sha512-LsJynDxYF6Neg7ZC7748yweCDD+N8ByCv22/7IAZglIEniEkqdF4HCaa49JNDLw1UQGlYuhOB8ZT/MmcSWzcWg== + +esbuild-linux-arm@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz#a2c1dff6d0f21dbe8fc6998a122675533ddfcd59" + integrity sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw== + +esbuild-linux-mips64le@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.51.tgz#dad10770fac94efa092b5a0643821c955a9dd385" + integrity sha512-vS54wQjy4IinLSlb5EIlLoln8buh1yDgliP4CuEHumrPk4PvvP4kTRIG4SzMXm6t19N0rIfT4bNdAxzJLg2k6A== + +esbuild-linux-mips64le@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz#d9918e9e4cb972f8d6dae8e8655bf9ee131eda34" + integrity sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw== + +esbuild-linux-ppc64le@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.51.tgz#b68c2f8294d012a16a88073d67e976edd4850ae0" + integrity sha512-xcdd62Y3VfGoyphNP/aIV9LP+RzFw5M5Z7ja+zdpQHHvokJM7d0rlDRMN+iSSwvUymQkqZO+G/xjb4/75du8BQ== + +esbuild-linux-ppc64le@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz#3f9a0f6d41073fb1a640680845c7de52995f137e" + integrity sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ== + +esbuild-linux-riscv64@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.51.tgz#608a318b8697123e44c1e185cdf6708e3df50b93" + integrity sha512-syXHGak9wkAnFz0gMmRBoy44JV0rp4kVCEA36P5MCeZcxFq8+fllBC2t6sKI23w3qd8Vwo9pTADCgjTSf3L3rA== + +esbuild-linux-riscv64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz#618853c028178a61837bc799d2013d4695e451c8" + integrity sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg== + +esbuild-linux-s390x@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.51.tgz#c9e7791170a3295dba79b93aa452beb9838a8625" + integrity sha512-kFAJY3dv+Wq8o28K/C7xkZk/X34rgTwhknSsElIqoEo8armCOjMJ6NsMxm48KaWY2h2RUYGtQmr+RGuUPKBhyw== + +esbuild-linux-s390x@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz#d1885c4c5a76bbb5a0fe182e2c8c60eb9e29f2a6" + integrity sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA== + +esbuild-netbsd-64@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.51.tgz#0abd40b8c2e37fda6f5cc41a04cb2b690823d891" + integrity sha512-ZZBI7qrR1FevdPBVHz/1GSk1x5GDL/iy42Zy8+neEm/HA7ma+hH/bwPEjeHXKWUDvM36CZpSL/fn1/y9/Hb+1A== + +esbuild-netbsd-64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz#69ae917a2ff241b7df1dbf22baf04bd330349e81" + integrity sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w== + +esbuild-openbsd-64@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.51.tgz#4adba0b7ea7eb1428bb00d8e94c199a949b130e8" + integrity sha512-7R1/p39M+LSVQVgDVlcY1KKm6kFKjERSX1lipMG51NPcspJD1tmiZSmmBXoY5jhHIu6JL1QkFDTx94gMYK6vfA== + +esbuild-openbsd-64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz#db4c8495287a350a6790de22edea247a57c5d47b" + integrity sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw== + +esbuild-sunos-64@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.51.tgz#4b8a6d97dfedda30a6e39607393c5c90ebf63891" + integrity sha512-HoHaCswHxLEYN8eBTtyO0bFEWvA3Kdb++hSQ/lLG7TyKF69TeSG0RNoBRAs45x/oCeWaTDntEZlYwAfQlhEtJA== + +esbuild-sunos-64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz#54287ee3da73d3844b721c21bc80c1dc7e1bf7da" + integrity sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw== + +esbuild-windows-32@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-windows-32/-/esbuild-windows-32-0.14.51.tgz#d31d8ca0c1d314fb1edea163685a423b62e9ac17" + integrity sha512-4rtwSAM35A07CBt1/X8RWieDj3ZUHQqUOaEo5ZBs69rt5WAFjP4aqCIobdqOy4FdhYw1yF8Z0xFBTyc9lgPtEg== + +esbuild-windows-32@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz#f8aaf9a5667630b40f0fb3aa37bf01bbd340ce31" + integrity sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w== + +esbuild-windows-64@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-windows-64/-/esbuild-windows-64-0.14.51.tgz#7d3c09c8652d222925625637bdc7e6c223e0085d" + integrity sha512-HoN/5HGRXJpWODprGCgKbdMvrC3A2gqvzewu2eECRw2sYxOUoh2TV1tS+G7bHNapPGI79woQJGV6pFH7GH7qnA== + +esbuild-windows-64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz#bf54b51bd3e9b0f1886ffdb224a4176031ea0af4" + integrity sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ== + +esbuild-windows-arm64@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.51.tgz#0220d2304bfdc11bc27e19b2aaf56edf183e4ae9" + integrity sha512-JQDqPjuOH7o+BsKMSddMfmVJXrnYZxXDHsoLHc0xgmAZkOOCflRmC43q31pk79F9xuyWY45jDBPolb5ZgGOf9g== + +esbuild-windows-arm64@0.14.54: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz#937d15675a15e4b0e4fafdbaa3a01a776a2be982" + integrity sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg== + +esbuild@0.14.51: + version "0.14.51" + resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.14.51.tgz" + integrity sha512-+CvnDitD7Q5sT7F+FM65sWkF8wJRf+j9fPcprxYV4j+ohmzVj2W7caUqH2s5kCaCJAfcAICjSlKhDCcvDpU7nw== + optionalDependencies: + esbuild-android-64 "0.14.51" + esbuild-android-arm64 "0.14.51" + esbuild-darwin-64 "0.14.51" + esbuild-darwin-arm64 "0.14.51" + esbuild-freebsd-64 "0.14.51" + esbuild-freebsd-arm64 "0.14.51" + esbuild-linux-32 "0.14.51" + esbuild-linux-64 "0.14.51" + esbuild-linux-arm "0.14.51" + esbuild-linux-arm64 "0.14.51" + esbuild-linux-mips64le "0.14.51" + esbuild-linux-ppc64le "0.14.51" + esbuild-linux-riscv64 "0.14.51" + esbuild-linux-s390x "0.14.51" + esbuild-netbsd-64 "0.14.51" + esbuild-openbsd-64 "0.14.51" + esbuild-sunos-64 "0.14.51" + esbuild-windows-32 "0.14.51" + esbuild-windows-64 "0.14.51" + esbuild-windows-arm64 "0.14.51" + +esbuild@^0.14.27: + version "0.14.54" + resolved "https://registry.npmmirror.com/esbuild/-/esbuild-0.14.54.tgz" + integrity sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA== + optionalDependencies: + "@esbuild/linux-loong64" "0.14.54" + esbuild-android-64 "0.14.54" + esbuild-android-arm64 "0.14.54" + esbuild-darwin-64 "0.14.54" + esbuild-darwin-arm64 "0.14.54" + esbuild-freebsd-64 "0.14.54" + esbuild-freebsd-arm64 "0.14.54" + esbuild-linux-32 "0.14.54" + esbuild-linux-64 "0.14.54" + esbuild-linux-arm "0.14.54" + esbuild-linux-arm64 "0.14.54" + esbuild-linux-mips64le "0.14.54" + esbuild-linux-ppc64le "0.14.54" + esbuild-linux-riscv64 "0.14.54" + esbuild-linux-s390x "0.14.54" + esbuild-netbsd-64 "0.14.54" + esbuild-openbsd-64 "0.14.54" + esbuild-sunos-64 "0.14.54" + esbuild-windows-32 "0.14.54" + esbuild-windows-64 "0.14.54" + esbuild-windows-arm64 "0.14.54" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.npmmirror.com/escalade/-/escalade-3.1.1.tgz" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-config-prettier@^8.1.0: + version "8.8.0" + resolved "https://registry.npmmirror.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz" + integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA== + +eslint-plugin-vue@^9.0.0: + version "9.14.1" + resolved "https://registry.npmmirror.com/eslint-plugin-vue/-/eslint-plugin-vue-9.14.1.tgz" + integrity sha512-LQazDB1qkNEKejLe/b5a9VfEbtbczcOaui5lQ4Qw0tbRBbQYREyxxOV5BQgNDTqGPs9pxqiEpbMi9ywuIaF7vw== + dependencies: + "@eslint-community/eslint-utils" "^4.3.0" + natural-compare "^1.4.0" + nth-check "^2.0.1" + postcss-selector-parser "^6.0.9" + semver "^7.3.5" + vue-eslint-parser "^9.3.0" + xml-name-validator "^4.0.0" + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^7.1.1, eslint-scope@^7.2.0: + version "7.2.0" + resolved "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-7.2.0.tgz" + integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: + version "3.4.1" + resolved "https://registry.npmmirror.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz" + integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== + +eslint@^8.10.0: + version "8.41.0" + resolved "https://registry.npmmirror.com/eslint/-/eslint-8.41.0.tgz" + integrity sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.4.0" + "@eslint/eslintrc" "^2.0.3" + "@eslint/js" "8.41.0" + "@humanwhocodes/config-array" "^0.11.8" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.0" + eslint-visitor-keys "^3.4.1" + espree "^9.5.2" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.1" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + +espree@^9.3.1, espree@^9.5.2: + version "9.5.2" + resolved "https://registry.npmmirror.com/espree/-/espree-9.5.2.tgz" + integrity sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw== + dependencies: + acorn "^8.8.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esquery@^1.4.0, esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.npmmirror.com/esquery/-/esquery-1.5.0.tgz" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +estree-walker@^2.0.1, estree-walker@^2.0.2: + version "2.0.2" + resolved "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz" + integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +eventemitter3@^4.0.0: + version "4.0.7" + resolved "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-4.0.7.tgz" + integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== + +express@^4.17.3: + version "4.18.2" + resolved "https://registry.npmmirror.com/express/-/express-4.18.2.tgz" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.1" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.5.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.npmmirror.com/external-editor/-/external-editor-3.1.0.tgz" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@3.2.12, fast-glob@^3.2.9: + version "3.2.12" + resolved "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.2.12.tgz" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.npmmirror.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.npmmirror.com/fastq/-/fastq-1.15.0.tgz" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + +figures@^3.0.0: + version "3.2.0" + resolved "https://registry.npmmirror.com/figures/-/figures-3.2.0.tgz" + integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.npmmirror.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.npmmirror.com/fill-range/-/fill-range-7.0.1.tgz" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.2.0.tgz" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.npmmirror.com/flat-cache/-/flat-cache-3.0.4.tgz" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.2.7" + resolved "https://registry.npmmirror.com/flatted/-/flatted-3.2.7.tgz" + integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== + +follow-redirects@^1.15.0: + version "1.15.2" + resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.2.tgz" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fraction.js@^4.2.0: + version "4.2.0" + resolved "https://registry.npmmirror.com/fraction.js/-/fraction.js-4.2.0.tgz" + integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/fs-constants/-/fs-constants-1.0.0.tgz" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + +fs-extra@^11.1.0: + version "11.1.1" + resolved "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.1.1.tgz" + integrity sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.1.tgz" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.0.2: + version "1.2.1" + resolved "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.npmmirror.com/glob-parent/-/glob-parent-6.0.2.tgz" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^7.1.3, glob@^7.1.4: + version "7.2.3" + resolved "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^13.19.0: + version "13.20.0" + resolved "https://registry.npmmirror.com/globals/-/globals-13.20.0.tgz" + integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== + dependencies: + type-fest "^0.20.2" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.npmmirror.com/globby/-/globby-11.1.0.tgz" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +google-protobuf@^3.21.2: + version "3.21.2" + resolved "https://registry.npmmirror.com/google-protobuf/-/google-protobuf-3.21.2.tgz" + integrity sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA== + +graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.11" + resolved "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +grapheme-splitter@^1.0.4: + version "1.0.4" + resolved "https://registry.npmmirror.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz" + integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.npmmirror.com/graphemer/-/graphemer-1.4.0.tgz" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.1.tgz" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.npmmirror.com/has/-/has-1.0.3.tgz" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.npmmirror.com/he/-/he-1.2.0.tgz" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +html-minifier@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/html-minifier/-/html-minifier-4.0.0.tgz" + integrity sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig== + dependencies: + camel-case "^3.0.0" + clean-css "^4.2.1" + commander "^2.19.0" + he "^1.2.0" + param-case "^2.1.1" + relateurl "^0.2.7" + uglify-js "^3.5.1" + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +iconv-lite@0.4.24, iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +ignore@^5.2.0: + version "5.2.4" + resolved "https://registry.npmmirror.com/ignore/-/ignore-5.2.4.tgz" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inquirer@^8.2.1: + version "8.2.5" + resolved "https://registry.npmmirror.com/inquirer/-/inquirer-8.2.5.tgz" + integrity sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ== + dependencies: + ansi-escapes "^4.2.1" + chalk "^4.1.1" + cli-cursor "^3.1.0" + cli-width "^3.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.21" + mute-stream "0.0.8" + ora "^5.4.1" + run-async "^2.4.0" + rxjs "^7.5.5" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + wrap-ansi "^7.0.0" + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-core-module@^2.11.0: + version "2.12.1" + resolved "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.12.1.tgz" + integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== + dependencies: + has "^1.0.3" + +is-docker@^2.0.0, is-docker@^2.1.1: + version "2.2.1" + resolved "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-interactive@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/is-interactive/-/is-interactive-1.0.0.tgz" + integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/is-obj/-/is-obj-2.0.0.tgz" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.npmmirror.com/is-path-inside/-/is-path-inside-3.0.3.tgz" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-2.0.4.tgz" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isbinaryfile@^5.0.0: + version "5.0.0" + resolved "https://registry.npmmirror.com/isbinaryfile/-/isbinaryfile-5.0.0.tgz" + integrity sha512-UDdnyGvMajJUWCkib7Cei/dvyJrrvo4FIrsvSFWdPpXSUorzXrDJ0S+X5Q4ZlasfPjca4yqCNNsjbCeiy8FFeg== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +ismobilejs@^1.1.0: + version "1.1.1" + resolved "https://registry.npmmirror.com/ismobilejs/-/ismobilejs-1.1.1.tgz" + integrity sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw== + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.npmmirror.com/isobject/-/isobject-3.0.1.tgz" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +js-base64@^3.7.5: + version "3.7.5" + resolved "https://registry.npmmirror.com/js-base64/-/js-base64-3.7.5.tgz" + integrity sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.npmmirror.com/js-yaml/-/js-yaml-4.1.0.tgz" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +jsonfile@^6.0.1: + version "6.1.0" + resolved "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.1.0.tgz" + integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + dependencies: + universalify "^2.0.0" + optionalDependencies: + graceful-fs "^4.1.6" + +kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.npmmirror.com/kind-of/-/kind-of-6.0.3.tgz" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +kolorist@^1.5.1: + version "1.8.0" + resolved "https://registry.npmmirror.com/kolorist/-/kolorist-1.8.0.tgz" + integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ== + +lazystream@^1.0.0: + version "1.0.1" + resolved "https://registry.npmmirror.com/lazystream/-/lazystream-1.0.1.tgz" + integrity sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw== + dependencies: + readable-stream "^2.0.5" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.npmmirror.com/levn/-/levn-0.4.1.tgz" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.defaults@^4.2.0: + version "4.2.0" + resolved "https://registry.npmmirror.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz" + integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== + +lodash.difference@^4.5.0: + version "4.5.0" + resolved "https://registry.npmmirror.com/lodash.difference/-/lodash.difference-4.5.0.tgz" + integrity sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA== + +lodash.flatten@^4.4.0: + version "4.4.0" + resolved "https://registry.npmmirror.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz" + integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g== + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.npmmirror.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz" + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.truncate@^4.4.2: + version "4.4.2" + resolved "https://registry.npmmirror.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz" + integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== + +lodash.union@^4.6.0: + version "4.6.0" + resolved "https://registry.npmmirror.com/lodash.union/-/lodash.union-4.6.0.tgz" + integrity sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw== + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.npmmirror.com/log-symbols/-/log-symbols-4.1.0.tgz" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +lower-case@^1.1.1: + version "1.1.4" + resolved "https://registry.npmmirror.com/lower-case/-/lower-case-1.1.4.tgz" + integrity sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.npmmirror.com/lru-cache/-/lru-cache-6.0.0.tgz" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +magic-string@^0.30.0: + version "0.30.0" + resolved "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.0.tgz" + integrity sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.13" + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.npmmirror.com/methods/-/methods-1.1.2.tgz" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.5.tgz" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + version "1.52.0" + resolved "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^5.1.0: + version "5.1.6" + resolved "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.6.tgz" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.npmmirror.com/ms/-/ms-2.1.2.tgz" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +mute-stream@0.0.8: + version "0.0.8" + resolved "https://registry.npmmirror.com/mute-stream/-/mute-stream-0.0.8.tgz" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + +nanoid@^3.3.6: + version "3.3.6" + resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.6.tgz" + integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== + +natural-compare-lite@^1.4.0: + version "1.4.0" + resolved "https://registry.npmmirror.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz" + integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.npmmirror.com/natural-compare/-/natural-compare-1.4.0.tgz" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +no-case@^2.2.0: + version "2.3.2" + resolved "https://registry.npmmirror.com/no-case/-/no-case-2.3.2.tgz" + integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== + dependencies: + lower-case "^1.1.1" + +node-releases@^2.0.12: + version "2.0.12" + resolved "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.12.tgz" + integrity sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.npmmirror.com/normalize-range/-/normalize-range-0.1.2.tgz" + integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== + +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.npmmirror.com/nth-check/-/nth-check-2.1.1.tgz" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + +object-inspect@^1.9.0: + version "1.12.3" + resolved "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.12.3.tgz" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/on-headers/-/on-headers-1.0.2.tgz" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.0, once@^1.4.0: + version "1.4.0" + resolved "https://registry.npmmirror.com/once/-/once-1.4.0.tgz" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^5.1.0: + version "5.1.2" + resolved "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +open@^8.4.0: + version "8.4.2" + resolved "https://registry.npmmirror.com/open/-/open-8.4.2.tgz" + integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ== + dependencies: + define-lazy-prop "^2.0.0" + is-docker "^2.1.1" + is-wsl "^2.2.0" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.npmmirror.com/optionator/-/optionator-0.9.1.tgz" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +ora@^5.4.1: + version "5.4.1" + resolved "https://registry.npmmirror.com/ora/-/ora-5.4.1.tgz" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== + dependencies: + bl "^4.1.0" + chalk "^4.1.0" + cli-cursor "^3.1.0" + cli-spinners "^2.5.0" + is-interactive "^1.0.0" + is-unicode-supported "^0.1.0" + log-symbols "^4.1.0" + strip-ansi "^6.0.0" + wcwidth "^1.0.1" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +param-case@^2.1.1: + version "2.1.1" + resolved "https://registry.npmmirror.com/param-case/-/param-case-2.1.1.tgz" + integrity sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w== + dependencies: + no-case "^2.2.0" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/path-type/-/path-type-4.0.0.tgz" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pinia@^2.0.11: + version "2.1.3" + resolved "https://registry.npmmirror.com/pinia/-/pinia-2.1.3.tgz" + integrity sha512-XNA/z/ye4P5rU1pieVmh0g/hSuDO98/a5UC8oSP0DNdvt6YtetJNHTrXwpwsQuflkGT34qKxAEcp7lSxXNjf/A== + dependencies: + "@vue/devtools-api" "^6.5.0" + vue-demi ">=0.14.5" + +pixi-viewport@^5.0.1: + version "5.0.1" + resolved "https://registry.npmmirror.com/pixi-viewport/-/pixi-viewport-5.0.1.tgz" + integrity sha512-fIILU9xztqGnhGF5SYfjn1Rir/7asWkJ8zSUay2hwzPrdGTWFtB4yiIlZDeFaLf7KHA04RRb2kI01Sy1kNksAw== + +pixi.js@^7.2.4: + version "7.2.4" + resolved "https://registry.npmmirror.com/pixi.js/-/pixi.js-7.2.4.tgz" + integrity sha512-nBH60meoLnHxoMFz17HoMxXS4uJpG5jwIdL+Gx2S11TzWgP3iKF+/WLOTrkSdyuQoQSdIBxVqpnYii0Wiox15A== + dependencies: + "@pixi/accessibility" "7.2.4" + "@pixi/app" "7.2.4" + "@pixi/assets" "7.2.4" + "@pixi/compressed-textures" "7.2.4" + "@pixi/core" "7.2.4" + "@pixi/display" "7.2.4" + "@pixi/events" "7.2.4" + "@pixi/extensions" "7.2.4" + "@pixi/extract" "7.2.4" + "@pixi/filter-alpha" "7.2.4" + "@pixi/filter-blur" "7.2.4" + "@pixi/filter-color-matrix" "7.2.4" + "@pixi/filter-displacement" "7.2.4" + "@pixi/filter-fxaa" "7.2.4" + "@pixi/filter-noise" "7.2.4" + "@pixi/graphics" "7.2.4" + "@pixi/mesh" "7.2.4" + "@pixi/mesh-extras" "7.2.4" + "@pixi/mixin-cache-as-bitmap" "7.2.4" + "@pixi/mixin-get-child-by-name" "7.2.4" + "@pixi/mixin-get-global-position" "7.2.4" + "@pixi/particle-container" "7.2.4" + "@pixi/prepare" "7.2.4" + "@pixi/sprite" "7.2.4" + "@pixi/sprite-animated" "7.2.4" + "@pixi/sprite-tiling" "7.2.4" + "@pixi/spritesheet" "7.2.4" + "@pixi/text" "7.2.4" + "@pixi/text-bitmap" "7.2.4" + "@pixi/text-html" "7.2.4" + +postcss-selector-parser@^6.0.9: + version "6.0.13" + resolved "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz" + integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + +postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== + +postcss@^8.1.10, postcss@^8.4.13: + version "8.4.24" + resolved "https://registry.npmmirror.com/postcss/-/postcss-8.4.24.tgz" + integrity sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg== + dependencies: + nanoid "^3.3.6" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier@^2.5.1: + version "2.8.8" + resolved "https://registry.npmmirror.com/prettier/-/prettier-2.8.8.tgz" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +protoc-gen-ts@^0.8.6: + version "0.8.6" + resolved "https://registry.npmmirror.com/protoc-gen-ts/-/protoc-gen-ts-0.8.6.tgz" + integrity sha512-66oeorGy4QBvYjQGd/gaeOYyFqKyRmRgTpofmnw8buMG0P7A0jQjoKSvKJz5h5tNUaVkIzvGBUTRVGakrhhwpA== + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.npmmirror.com/punycode/-/punycode-1.3.2.tgz" + integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.npmmirror.com/punycode/-/punycode-2.3.0.tgz" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +qs@6.11.0: + version "6.11.0" + resolved "https://registry.npmmirror.com/qs/-/qs-6.11.0.tgz" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + +quasar@^2.6.0: + version "2.12.0" + resolved "https://registry.npmmirror.com/quasar/-/quasar-2.12.0.tgz" + integrity sha512-B8xoeOWNs/Iv7M+FGRvXGYI1qDnJH8AtIb7RiP+zMfMkBcEp+6HJHU/9ODPemC4yteDjO+HPX2f7OhNZKgsPIw== + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.npmmirror.com/querystring/-/querystring-0.2.0.tgz" + integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/randombytes/-/randombytes-2.1.0.tgz" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.1.tgz" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +readable-stream@^2.0.0, readable-stream@^2.0.5: + version "2.3.8" + resolved "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdir-glob@^1.0.0: + version "1.1.3" + resolved "https://registry.npmmirror.com/readdir-glob/-/readdir-glob-1.1.3.tgz" + integrity sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA== + dependencies: + minimatch "^5.1.0" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +register-service-worker@^1.7.2: + version "1.7.2" + resolved "https://registry.npmmirror.com/register-service-worker/-/register-service-worker-1.7.2.tgz" + integrity sha512-CiD3ZSanZqcMPRhtfct5K9f7i3OLCcBBWsJjLh1gW9RO/nS94sVzY59iS+fgYBOBqaBpf4EzfqUF3j9IG+xo8A== + +relateurl@^0.2.7: + version "0.2.7" + resolved "https://registry.npmmirror.com/relateurl/-/relateurl-0.2.7.tgz" + integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/resolve-from/-/resolve-from-4.0.0.tgz" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve@^1.22.0: + version "1.22.2" + resolved "https://registry.npmmirror.com/resolve/-/resolve-1.22.2.tgz" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + dependencies: + is-core-module "^2.11.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-3.1.0.tgz" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.npmmirror.com/reusify/-/reusify-1.0.4.tgz" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rollup-plugin-visualizer@^5.5.4: + version "5.9.0" + resolved "https://registry.npmmirror.com/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.9.0.tgz" + integrity sha512-bbDOv47+Bw4C/cgs0czZqfm8L82xOZssk4ayZjG40y9zbXclNk7YikrZTDao6p7+HDiGxrN0b65SgZiVm9k1Cg== + dependencies: + open "^8.4.0" + picomatch "^2.3.1" + source-map "^0.7.4" + yargs "^17.5.1" + +"rollup@>=2.59.0 <2.78.0": + version "2.77.3" + resolved "https://registry.npmmirror.com/rollup/-/rollup-2.77.3.tgz" + integrity sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g== + optionalDependencies: + fsevents "~2.3.2" + +run-async@^2.4.0: + version "2.4.1" + resolved "https://registry.npmmirror.com/run-async/-/run-async-2.4.1.tgz" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +rxjs@^7.5.5: + version "7.8.1" + resolved "https://registry.npmmirror.com/rxjs/-/rxjs-7.8.1.tgz" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@5.2.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sass@1.32.12: + version "1.32.12" + resolved "https://registry.npmmirror.com/sass/-/sass-1.32.12.tgz" + integrity sha512-zmXn03k3hN0KaiVTjohgkg98C3UowhL1/VSGdj4/VAAiMKGQOE80PFPxFP2Kyq0OUskPKcY5lImkhBKEHlypJA== + dependencies: + chokidar ">=3.0.0 <4.0.0" + +sax@1.1.4: + version "1.1.4" + resolved "https://registry.npmmirror.com/sax/-/sax-1.1.4.tgz" + integrity sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg== + +semver@^7.3.5, semver@^7.3.6, semver@^7.3.7: + version "7.5.1" + resolved "https://registry.npmmirror.com/semver/-/semver-7.5.1.tgz" + integrity sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw== + dependencies: + lru-cache "^6.0.0" + +send@0.18.0: + version "0.18.0" + resolved "https://registry.npmmirror.com/send/-/send-0.18.0.tgz" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serialize-javascript@^6.0.0: + version "6.0.1" + resolved "https://registry.npmmirror.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz" + integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w== + dependencies: + randombytes "^2.1.0" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.npmmirror.com/serve-static/-/serve-static-1.15.0.tgz" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.npmmirror.com/shallow-clone/-/shallow-clone-3.0.1.tgz" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.4.tgz" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.2: + version "3.0.7" + resolved "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-4.0.0.tgz" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.0.2.tgz" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +source-map@^0.7.4: + version "0.7.4" + resolved "https://registry.npmmirror.com/source-map/-/source-map-0.7.4.tgz" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + +source-map@~0.6.0: + version "0.6.1" + resolved "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +stack-trace@^1.0.0-pre2: + version "1.0.0-pre2" + resolved "https://registry.npmmirror.com/stack-trace/-/stack-trace-1.0.0-pre2.tgz" + integrity sha512-2ztBJRek8IVofG9DBJqdy2N5kulaacX30Nz7xmkYF6ale9WBVmIy6mFBchvGX7Vx/MyjBhx+Rcxqrj+dbOnQ6A== + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +table@^6.8.0: + version "6.8.1" + resolved "https://registry.npmmirror.com/table/-/table-6.8.1.tgz" + integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== + dependencies: + ajv "^8.0.1" + lodash.truncate "^4.4.2" + slice-ansi "^4.0.0" + string-width "^4.2.3" + strip-ansi "^6.0.1" + +tar-stream@^2.2.0: + version "2.2.0" + resolved "https://registry.npmmirror.com/tar-stream/-/tar-stream-2.2.0.tgz" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.npmmirror.com/text-table/-/text-table-0.2.0.tgz" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +through@^2.3.6: + version "2.3.8" + resolved "https://registry.npmmirror.com/through/-/through-2.3.8.tgz" + integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.npmmirror.com/tmp/-/tmp-0.0.33.tgz" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +ts-md5@^1.3.1: + version "1.3.1" + resolved "https://registry.npmmirror.com/ts-md5/-/ts-md5-1.3.1.tgz" + integrity sha512-DiwiXfwvcTeZ5wCE0z+2A9EseZsztaiZtGrtSaY5JOD7ekPnR/GoIVD5gXZAlK9Na9Kvpo9Waz5rW64WKAWApg== + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.1.0: + version "2.5.2" + resolved "https://registry.npmmirror.com/tslib/-/tslib-2.5.2.tgz" + integrity sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.npmmirror.com/tsutils/-/tsutils-3.21.0.tgz" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.npmmirror.com/type-check/-/type-check-0.4.0.tgz" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.npmmirror.com/type-fest/-/type-fest-0.20.2.tgz" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.npmmirror.com/type-fest/-/type-fest-0.21.3.tgz" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typescript@^4.5.4: + version "4.9.5" + resolved "https://registry.npmmirror.com/typescript/-/typescript-4.9.5.tgz" + integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== + +uglify-js@^3.5.1: + version "3.17.4" + resolved "https://registry.npmmirror.com/uglify-js/-/uglify-js-3.17.4.tgz" + integrity sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g== + +universalify@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/universalify/-/universalify-2.0.0.tgz" + integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +update-browserslist-db@^1.0.11: + version "1.0.11" + resolved "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz" + integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +upper-case@^1.1.1: + version "1.1.3" + resolved "https://registry.npmmirror.com/upper-case/-/upper-case-1.1.3.tgz" + integrity sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA== + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.npmmirror.com/url/-/url-0.11.0.tgz" + integrity sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ== + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +vite@^2.9.13: + version "2.9.16" + resolved "https://registry.npmmirror.com/vite/-/vite-2.9.16.tgz" + integrity sha512-X+6q8KPyeuBvTQV8AVSnKDvXoBMnTx8zxh54sOwmmuOdxkjMmEJXH2UEchA+vTMps1xw9vL64uwJOWryULg7nA== + dependencies: + esbuild "^0.14.27" + postcss "^8.4.13" + resolve "^1.22.0" + rollup ">=2.59.0 <2.78.0" + optionalDependencies: + fsevents "~2.3.2" + +vue-demi@>=0.14.5: + version "0.14.5" + resolved "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.5.tgz" + integrity sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA== + +vue-eslint-parser@^9.3.0: + version "9.3.0" + resolved "https://registry.npmmirror.com/vue-eslint-parser/-/vue-eslint-parser-9.3.0.tgz" + integrity sha512-48IxT9d0+wArT1+3wNIy0tascRoywqSUe2E1YalIC1L8jsUGe5aJQItWfRok7DVFGz3UYvzEI7n5wiTXsCMAcQ== + dependencies: + debug "^4.3.4" + eslint-scope "^7.1.1" + eslint-visitor-keys "^3.3.0" + espree "^9.3.1" + esquery "^1.4.0" + lodash "^4.17.21" + semver "^7.3.6" + +vue-router@^4.0.0: + version "4.2.2" + resolved "https://registry.npmmirror.com/vue-router/-/vue-router-4.2.2.tgz" + integrity sha512-cChBPPmAflgBGmy3tBsjeoe3f3VOSG6naKyY5pjtrqLGbNEXdzCigFUHgBvp9e3ysAtFtEx7OLqcSDh/1Cq2TQ== + dependencies: + "@vue/devtools-api" "^6.5.0" + +vue@^3.0.0: + version "3.3.4" + resolved "https://registry.npmmirror.com/vue/-/vue-3.3.4.tgz" + integrity sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw== + dependencies: + "@vue/compiler-dom" "3.3.4" + "@vue/compiler-sfc" "3.3.4" + "@vue/runtime-dom" "3.3.4" + "@vue/server-renderer" "3.3.4" + "@vue/shared" "3.3.4" + +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.npmmirror.com/wcwidth/-/wcwidth-1.0.1.tgz" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + +webpack-merge@^5.8.0: + version "5.9.0" + resolved "https://registry.npmmirror.com/webpack-merge/-/webpack-merge-5.9.0.tgz" + integrity sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg== + dependencies: + clone-deep "^4.0.1" + wildcard "^2.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.npmmirror.com/which/-/which-2.0.2.tgz" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wildcard@^2.0.0: + version "2.0.1" + resolved "https://registry.npmmirror.com/wildcard/-/wildcard-2.0.1.tgz" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== + +word-wrap@^1.2.3: + version "1.2.3" + resolved "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.3.tgz" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +xml-name-validator@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-4.0.0.tgz" + integrity sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.5.1: + version "17.7.2" + resolved "https://registry.npmmirror.com/yargs/-/yargs-17.7.2.tgz" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zip-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.npmmirror.com/zip-stream/-/zip-stream-4.1.0.tgz" + integrity sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A== + dependencies: + archiver-utils "^2.1.0" + compress-commons "^4.1.0" + readable-stream "^3.6.0"