├── .eslintrc.json ├── .gitignore ├── .vscode ├── extensions.json ├── launch.json ├── settings.json └── tasks.json ├── .vscodeignore ├── .yarnrc ├── CHANGELOG.md ├── LICENSE ├── README.md ├── live2dExtraConfig.json ├── logo.png ├── media ├── main.css ├── main.js └── vscode.css ├── package.json ├── res └── live2d │ ├── assets │ ├── Ava.png │ ├── Diana.png │ ├── Eileen.png │ ├── au.png │ ├── beijixing.png │ ├── border.png │ ├── chong.jpg │ ├── jellyfish.png │ ├── jiaxintang.png │ ├── naiqilin.png │ ├── pierce.png │ ├── pin.png │ ├── skate.png │ └── yigehun.png │ ├── config.json │ ├── index.html │ ├── lib │ ├── background.js │ ├── live2d_display │ │ ├── index.min.js │ │ ├── live2d.min.js │ │ ├── live2dcubismcore.min.js │ │ └── pixi.min.js │ ├── load.js │ └── pio │ │ ├── avatar.png │ │ ├── pio.css │ │ ├── pio.js │ │ └── pio_sdk4.js │ └── models │ ├── Ava │ ├── Ava.4096 │ │ └── texture_00.png │ ├── Ava.moc3 │ ├── Ava.model3.json │ ├── Ava.physics3.json │ ├── motions │ │ ├── Ava_idle.motion3.json │ │ ├── Ava_shake01.motion3.json │ │ ├── Ava_shake02.motion3.json │ │ ├── Ava_tap01.motion3.json │ │ ├── Ava_tap02.motion3.json │ │ ├── Ava_tap03.motion3.json │ │ ├── Ava_tap04.motion3.json │ │ ├── Ava_tap05.motion3.json │ │ ├── Ava_tap06.motion3.json │ │ ├── Ava_tap07.motion3.json │ │ ├── Ava_tap08.motion3.json │ │ ├── Ava_tap09.motion3.json │ │ ├── Ava_tap10.motion3.json │ │ └── Ava_tap11.motion3.json │ ├── raw.ex.json │ ├── raw.model3.json │ └── raw.preview.png │ └── Diana │ ├── Diana.4096 │ └── texture_00.png │ ├── Diana.moc3 │ ├── Diana.model3.json │ ├── Diana.physics3.json │ ├── audio │ └── jiaxintang-nouse.aac │ ├── motions │ ├── Diana_idle.motion3.json │ ├── Diana_tap01.motion3.json │ ├── Diana_tap02.motion3.json │ ├── Diana_tap03.motion3.json │ ├── Diana_tap04.motion3.json │ ├── Diana_tap05.motion3.json │ ├── Diana_tap06.motion3.json │ ├── Diana_tap07.motion3.json │ ├── Diana_tap08.motion3.json │ ├── Diana_tap09.motion3.json │ ├── Diana_tap10.motion3.json │ └── Diana_tap11.motion3.json │ ├── raw.ex.json │ ├── raw.model3.json │ └── raw.preview.png ├── src ├── extension.ts ├── live2dModify │ ├── Dom.ts │ ├── FileType.ts │ ├── Main.ts │ ├── getJs.ts │ ├── index.ts │ ├── uninstall.ts │ ├── version.ts │ └── vsHelp.ts ├── live2dView │ └── index.ts └── test │ ├── runTest.ts │ └── suite │ ├── extension.test.ts │ └── index.ts ├── tsconfig.json ├── vsc-extension-quickstart.md └── yarn.lock /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "parserOptions": { 5 | "ecmaVersion": 6, 6 | "sourceType": "module" 7 | }, 8 | "plugins": [ 9 | "@typescript-eslint" 10 | ], 11 | "rules": { 12 | "@typescript-eslint/naming-convention": "warn", 13 | "@typescript-eslint/semi": "warn", 14 | "curly": "warn", 15 | "eqeqeq": "warn", 16 | "no-throw-literal": "warn", 17 | "semi": "off", 18 | "@typescript-eslint/no-unused-vars": 0, 19 | "@typescript-eslint/no-explicit-any": 0, 20 | "@typescript-eslint/explicit-module-boundary-types": 0, 21 | "@typescript-eslint/no-non-null-assertion": 0, 22 | }, 23 | "ignorePatterns": [ 24 | "out", 25 | "dist", 26 | "**/*.d.ts" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | dist 3 | node_modules 4 | .vscode-test/ 5 | *.vsix 6 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "dbaeumer.vscode-eslint" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | { 6 | "version": "0.2.0", 7 | "configurations": [ 8 | { 9 | "name": "Run Extension", 10 | "type": "extensionHost", 11 | "request": "launch", 12 | "args": [ 13 | "--extensionDevelopmentPath=${workspaceFolder}" 14 | ], 15 | "outFiles": [ 16 | "${workspaceFolder}/out/**/*.js" 17 | ], 18 | "preLaunchTask": "${defaultBuildTask}" 19 | }, 20 | { 21 | "name": "Extension Tests", 22 | "type": "extensionHost", 23 | "request": "launch", 24 | "args": [ 25 | "--extensionDevelopmentPath=${workspaceFolder}", 26 | "--extensionTestsPath=${workspaceFolder}/out/test/suite/index" 27 | ], 28 | "outFiles": [ 29 | "${workspaceFolder}/out/test/**/*.js" 30 | ], 31 | "preLaunchTask": "${defaultBuildTask}" 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "out": false // set this to true to hide the "out" folder with the compiled JS files 5 | }, 6 | "search.exclude": { 7 | "out": true // set this to false to include "out" folder in search results 8 | }, 9 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts 10 | "typescript.tsc.autoDetect": "off" 11 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // See https://go.microsoft.com/fwlink/?LinkId=733558 2 | // for the documentation about the tasks.json format 3 | { 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "watch", 9 | "problemMatcher": "$tsc-watch", 10 | "isBackground": true, 11 | "presentation": { 12 | "reveal": "never" 13 | }, 14 | "group": { 15 | "kind": "build", 16 | "isDefault": true 17 | } 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | src/** 4 | .gitignore 5 | .yarnrc 6 | vsc-extension-quickstart.md 7 | **/tsconfig.json 8 | **/.eslintrc.json 9 | **/*.map 10 | **/*.ts 11 | -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | --ignore-engines true -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## ver1.1.1 2 | fix: 随vscode更新版本调整,修复无法运行问题 3 | 保留了上次的更新内容和版本 4 | 5 | ## ver1.0.1 6 | fix: 更新部分失效网站信息 7 | 8 | ## ver1.0.0 9 | fix: 随vscode更新版本调整,修复无法运行问题 10 | 11 | ## ver0.1.12 12 | fix: 图标改成本地文件 13 | 14 | ## ver0.1.11 15 | fix: 修改背景图样式时,当前背景图丢失问题 16 | 17 | ## ver0.1.10 18 | feat: 背景图操作添加下载功能 + fix 因为cdn资源可能导致模型加载过慢bug 19 | 20 | ## ver0.1.8 21 | feat: 背景图操作添加配置属性:不透明度和背景图大小 22 | 23 | ## ver0.1.7 24 | fix: 优化点击穿透的处理,处于穿透状态是,右上角的操作栏不会隐藏 25 | 26 | ## ver0.1.6 27 | fix: 修复vscode 1.63.0版本 控制面板失效问题 + 随机背景图范围扩大 28 | 29 | ## ver0.1.5 30 | fix: 溜冰场内容不生效bug修复 31 | 32 | ## ver0.1.4 33 | fix: 溜冰场内容补充 34 | 35 | ## ver0.1.3 36 | fix: 嘉然语音测试添加默认动作 37 | 38 | ## ver0.1.2 39 | fix: 语音测试文件中文更名为英文,中文识别有bug 40 | 41 | ## ver0.1.1 42 | 补充readme介绍,修复 mac系统 容易拖拽失效bug 43 | 44 | ## ver0.1.0 45 | asoul-live2d 可初步使用 (如果有更多的意见或建议,欢迎提供。我会尽量完善) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A-SOUL-live2d 使用简介 2 | 嘉晚饭是真的! 赢! 3 | # 简单预览: 4 | ![](https://s3.bmp.ovh/imgs/2021/10/5a972bb9b3badcd0.png#pic_center) 5 | 6 | # 视频演示 7 | 8 | [插件介绍视频](https://www.bilibili.com/video/BV1mR4y1J7XL) 可以的话请给我点一下赞,能转发分享评论就最好了 9 | [我的b站账号](https://space.bilibili.com/5637882) 关注吗?也不是不行,(*^_^*) 10 | 11 | # 功能概况: 12 | 13 | 使用 iframe 嵌入页面中,实现效果。 14 | 15 | - 启动 live2d 看板娘视图(使用sdk: [pixi-live2d-display](https://github.com/guansss/pixi-live2d-display) [pio](https://paugram.com/)) 16 | - 模型:嘉然、向晚(来源 b 站 up:[木果阿木果](https://space.bilibili.com/886695)) 17 | - 整体操作 18 | - 拖拽位置 19 | - 缩放大小 20 | - 点击穿透 21 | - 随机切换背景图 22 | - 该功能可与 A-SOUl-background插件功能配合使用,本插件的背景图优先级会更高 23 | - 点击切换随机背景图 [图来源](https://asoul.cloud/pic) 24 | - 保存背景图 25 | - 加载保存背景图 26 | - 定时切换背景图 27 | - 背景图样式配置 28 | - 下载背景图 29 | - 随机溜冰场: 部分常见溜冰场,可能会有部分滞后 30 | - [asoul 导航](https://asoulworld.com/)入口 31 | - [一个魂二创](https://asoul.cloud/)入口 32 | 33 | # 使用介绍: 34 | ## TIPS: 当人物无法正常启动时,可尝试点击配置文件生成按钮。(vscode版本更新后也需要手动点一下生成按钮) 35 |
36 | 37 |
38 | 39 | 若依赖文件生成失败: 40 | - windows可尝试使用以管理者身份运行vscode,再点击生成按钮 41 | - mac 请留意是否将vscode从【下载】移动到【应用程序】里 42 | - mac 可通过【检查vscode是否可以更新】来判断软件是否处于可写的硬盘中 43 | 44 | ## Warns 警告: 45 | 46 | > **本插件是通过修改 vscode 的 js 文件的方式运行** 47 | > 所以会在初次安装,或者 vscode 升级的时候,出现以下提示,请选择 【不再提示】: 48 | > 49 | > **This extension works by editting the vscode's css file.** 50 | > So, a warning appears while the first time to install or vscode update. U can click the [never show again] to avoid it. 51 |
52 | 53 |
54 | This is the reason: 55 |
56 | 57 |
58 | 59 | ## 使用流程 60 | 61 |
62 | 63 |
64 | 65 | 本插件下载后,可以在侧边栏 “资源管理区” (第一个图标),的最下面看到新的抽屉层【LIVE2D-A-SOUL】。 66 | 初次打开该抽屉,会进行资源的配置,右下角提示需要重新启动vscode 67 | 68 |
69 | 70 | 71 |
72 | 73 | 再次打开该抽屉可以看到很多对应的功能按钮 74 | - 基本操作 75 | - 启动、关闭live2d: 字面意思,会启动看板人物,初始默认位置右下角 76 | - 保存当前配置: 在调整live2d大小缩放和拖拽位置后,可保存信息,下次启动时自动携带 77 | - 重置默认位置: 当前位置异常,无法拖拽移动时可重置使用【缩放大小也会重置】 78 | - 背景图 79 | - 点击切换: 点击按钮为人物右侧图标第二个 80 | - 保存背景图: 需要当前背景图存在才会生效。只能保存一份,再次点击会覆盖旧的 81 | - 加载背景图: 加载保存的背景图 82 | - 定时切换: 字面意思,可查看 切换按钮 是否旋转判断是否开启定时功能 83 | - 背景图样式配置 84 | - 下载背景图 85 | - 配置信息 86 | - 自启动: 字面意思,开启后。vscode启动,live2d自动启动 87 | - 定位依赖: 人物定位的依赖角 88 | - 补充配置 89 | - 插件依赖文件: 90 | - 插件依赖文件会在初次安装插件并启动时自动生成 91 | - 生成: live2d无法正常启动时,可尝试点击该按钮,强制重新生成覆盖配置信息 92 | - 移除: 卸载该插件前,请尽可能先执行该操作。 可移除插件对vscode文件的所有修改 93 | 94 | - 人物功能 95 | - 目光跟随鼠标 【缺点,暂时无法实现整个页面的跟随】 96 | - 点击互动 97 | - asoul粉丝导航网站入口 98 | - 切换背景图 99 | - 切换模型 100 | - 溜冰场 101 | - 音频测试 102 | - 一个魂二创网站入口 103 | - 模型来源 104 | 105 | ## 卸载流程 106 |
107 | 108 |
109 | 110 | 卸载该插件前,请尽可能先执行该操作。可移除插件对vscode文件的所有修改,恢复正常。 111 | 然后在插件列表卸载该插件 112 | 113 | # 额外要求 【如果想开启音频支持】 114 | 115 | 当前插件仅一个简单的语音测试,暂且可以不用考虑该功能 116 | 117 | [VS Code 使用的 Electron 版本不包含 ffmpeg](https://stackoverflow.com/a/51735036),需替换自带的 ffmpeg 动态链接库才能正常播放 (每次更新 VS Code 都需重新替换) 118 | 119 | _VS Code for Windows 1.31.0 - 1.35.1 不需替换,1.36.0 后无此待遇_ 120 | 121 | _VS Code for macOS 1.43+ 替换后闪退[解决方案](https://github.com/nondanee/vsc-netease-music/issues/86#issuecomment-786546931)_ 122 | 123 |
124 | 125 | 手动替换操作 126 | 127 | 128 | 首先需要查看 vscode 版本对应的electron版本, 然后下载对应系统的electron版本的压缩包,将里面的特定文件ffmpeg 解压到vscode的安装目录下,替换原vscode的ffmpeg文件 129 | 130 | [electron下载](https://npm.taobao.org/mirrors/electron/) 131 | 132 | #### Windows 133 | 界面左上角 点击 help(帮助) => about(关于),弹窗可查看electron版本 134 | 下载 **electron-%version%-win32-x64.zip** 135 | 替换 `./ffmpeg.dll` 文件 136 | #### macOS 137 | 界面左上角 点击 code => about,弹窗可查看electron版本 138 | 下载 **electron-%version%-darwin-x64.zip** 139 | 替换 `./Electron.app/Contents/Frameworks/Electron\ Framework.framework/Libraries/libffmpeg.dylib` 140 | #### Linux 141 | 界面左上角 Help(帮助) → \rightarrow →About(关于) 142 | 下载 **electron-%version%-linux-x64.zip** 143 | 替换 `./libffmpeg.so` 144 | 145 |
146 | 147 | 148 | # 鸣谢 149 | [live2d-widget](https://github.com/stevenjoezhang/live2d-widget) 150 | [vscode-background](https://github.com/shalldie/vscode-background) 151 | [CharlesZ.vscode-live2d](https://marketplace.visualstudio.com/items?itemName=CharlesZ.vscode-live2d) 152 | [pixi-live2d-display](https://github.com/guansss/pixi-live2d-display) 153 | [pio](https://paugram.com/) 154 | [journey-ad](https://github.com/journey-ad) 155 | 156 | 还有乐于分享的一个魂们 157 | [asoul 导航](https://asoulworld.com/) 158 | [一个魂二创](https://asoul.cloud/) 159 | 部分小图标也来源b站一个魂们的分享 160 | 嘉然 向晚 模型:[木果阿木果](https://space.bilibili.com/886695) 161 | 162 | 请勿使用该项目涉及的资源进行商业盈利 163 | -------------------------------------------------------------------------------- /live2dExtraConfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "溜冰场": [ 3 | "https://space.bilibili.com/672328094", 4 | "https://space.bilibili.com/672346917", 5 | "https://space.bilibili.com/672353429", 6 | "https://space.bilibili.com/672342685", 7 | "https://space.bilibili.com/351609538", 8 | "https://www.bilibili.com/video/BV1FZ4y1F7HH", 9 | "https://www.bilibili.com/video/BV1FX4y1g7u8", 10 | "https://www.bilibili.com/video/BV1aK4y1P7Cg", 11 | "https://www.bilibili.com/video/BV17A411V7Uh", 12 | "https://www.bilibili.com/video/BV1AV411v7er", 13 | "https://www.bilibili.com/video/BV1564y1173Q", 14 | "https://www.bilibili.com/video/BV1MX4y1N75X", 15 | "https://www.bilibili.com/video/BV17h411U71w", 16 | "https://www.bilibili.com/video/BV1ry4y1Y71t", 17 | "https://www.bilibili.com/video/BV1Sy4y1n7c4", 18 | "https://www.bilibili.com/video/BV1PN411X7QW", 19 | "https://www.bilibili.com/video/BV1Dp4y1H7iB", 20 | "https://www.bilibili.com/video/BV1bi4y1P7Eh", 21 | "https://www.bilibili.com/video/BV1vQ4y1Z7C2", 22 | "https://www.bilibili.com/video/BV1oU4y1h7Sc", 23 | "https://www.bilibili.com/video/BV1M64y1a7zh", 24 | "https://www.bilibili.com/video/BV1L5411w7eM", 25 | "https://www.bilibili.com/video/BV1HU4y1L7cF", 26 | "https://www.bilibili.com/video/BV1Pq4y1Z7aa", 27 | "https://www.bilibili.com/video/BV1x64y1Y7JR", 28 | "https://www.bilibili.com/video/BV1NL4y1a7KM", 29 | "https://www.bilibili.com/video/BV1n44y1b7G2", 30 | "https://www.bilibili.com/video/BV1EQ4y1z7WL", 31 | "https://www.bilibili.com/video/BV1sv411u78Q", 32 | "https://www.bilibili.com/video/BV1Lv411N7Bm", 33 | "https://www.bilibili.com/video/BV1eo4y1S79a", 34 | "https://www.bilibili.com/video/BV1Rq4y1p7sY", 35 | "https://www.bilibili.com/video/BV1T5411T7u8", 36 | "https://www.bilibili.com/video/BV1DU4y15767", 37 | "https://www.bilibili.com/video/BV1c5411u7Zv", 38 | "https://www.bilibili.com/video/BV1m54y1V7mX", 39 | "https://www.bilibili.com/video/BV1a44y1z71P", 40 | "https://www.bilibili.com/video/BV1sV41177qM", 41 | "https://www.bilibili.com/video/BV1go4y1y7kV", 42 | "https://www.bilibili.com/video/BV1JM4y157Tg", 43 | "https://www.bilibili.com/video/BV1e44y147nb", 44 | "https://www.bilibili.com/video/BV1Ur4y1y7RP", 45 | "https://www.bilibili.com/video/BV1kQ4y1i7LG", 46 | "https://www.bilibili.com/video/BV1Jq4y157r1", 47 | "https://www.bilibili.com/video/BV14q4y1K71L", 48 | "https://www.bilibili.com/video/BV1ty4y1V7k4", 49 | "https://www.bilibili.com/video/BV1B54y1V7Ta", 50 | "https://www.bilibili.com/video/BV1Mh411Y7vS", 51 | "https://www.bilibili.com/video/BV1L64y1z7Df", 52 | "https://www.bilibili.com/video/BV1p5411w71j", 53 | "https://www.bilibili.com/video/BV1b64y117Kk", 54 | "https://www.bilibili.com/video/BV1RB4y1T723", 55 | "https://www.bilibili.com/video/BV1HP4y1Y7kq", 56 | "https://www.bilibili.com/video/BV1vL4y1z7Fh", 57 | "https://www.bilibili.com/video/BV1764y1q7JA", 58 | "https://www.bilibili.com/video/BV1Kq4y1n7p4", 59 | "https://www.bilibili.com/video/BV1JA411G7Dk", 60 | "https://www.bilibili.com/video/BV14A411P7Tg", 61 | "https://www.bilibili.com/video/BV1vQ4y1Z7C2", 62 | "https://www.bilibili.com/video/BV1TV411H7uf", 63 | "https://www.bilibili.com/video/BV1kq4y1W7hW", 64 | "https://www.bilibili.com/video/BV1Eb4y1C7oJ", 65 | "https://www.bilibili.com/video/BV1dL411n7sY", 66 | "https://www.bilibili.com/video/BV18h411z7gh", 67 | "https://www.bilibili.com/video/BV1sv411j7W8", 68 | "https://www.bilibili.com/video/BV1JP4y1x73T", 69 | "https://www.bilibili.com/video/BV1CM4y1V7ho", 70 | "https://www.bilibili.com/video/BV1444y1z7EV", 71 | "https://www.bilibili.com/video/BV1Ah41167DS", 72 | "https://www.bilibili.com/video/BV1FN411o7nt", 73 | "https://www.bilibili.com/video/BV1Rb4y1k7F7", 74 | "https://www.bilibili.com/video/BV1AB4y1g7CQ", 75 | "https://www.bilibili.com/video/BV1Gq4y1W7wT", 76 | "https://www.bilibili.com/video/BV1z3411y7nP", 77 | "https://www.bilibili.com/video/BV14h411B7mE", 78 | "https://www.bilibili.com/video/BV1Uy4y1j7rN", 79 | "https://www.bilibili.com/video/BV1NX4y1w7JN", 80 | "https://www.bilibili.com/video/BV1464y1W7gv", 81 | "https://www.bilibili.com/video/BV19V411H7tn", 82 | "https://www.bilibili.com/video/BV1L54y1n7yA", 83 | "https://www.bilibili.com/video/BV1f64y1k7Ff", 84 | "https://www.bilibili.com/video/BV12b4y1X7S8", 85 | "https://www.bilibili.com/video/BV1QQ4y1272S", 86 | "https://www.bilibili.com/video/BV12f4y1F7jD", 87 | "https://www.bilibili.com/video/BV1sM4y1g7Dg", 88 | "https://www.bilibili.com/video/BV1tA411V7b5", 89 | "https://www.bilibili.com/video/BV15V411E7hr", 90 | "https://www.bilibili.com/video/BV1J64y1m7Eu", 91 | "https://www.bilibili.com/video/BV1W54y1V7bV", 92 | "https://www.bilibili.com/video/BV15v411e7qa", 93 | "https://www.bilibili.com/video/BV1gy4y147vp", 94 | "https://www.bilibili.com/video/BV1DA411c7U3", 95 | "https://www.bilibili.com/video/BV11b4y167Gc", 96 | "https://www.bilibili.com/video/BV1bQ4y1d7n6", 97 | "https://www.bilibili.com/video/BV1X5411K7W5", 98 | "https://www.bilibili.com/video/BV12V411E7sn", 99 | "https://www.bilibili.com/video/BV1wv411K7LT", 100 | "https://www.bilibili.com/video/BV1Eq4y197ho", 101 | "https://www.bilibili.com/video/BV1aP4y1s7Wy", 102 | "https://www.bilibili.com/video/BV1Y64y1U7FZ" 103 | ] 104 | } 105 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/logo.png -------------------------------------------------------------------------------- /media/main.css: -------------------------------------------------------------------------------- 1 | html { 2 | box-sizing: border-box; 3 | font-size: 12px; 4 | } 5 | 6 | *, 7 | *:before, 8 | *:after { 9 | box-sizing: inherit; 10 | } 11 | 12 | body, 13 | h1, 14 | h2, 15 | h3, 16 | h4, 17 | h5, 18 | h6, 19 | p, 20 | ol, 21 | ul { 22 | margin: 0; 23 | padding: 0; 24 | font-weight: normal; 25 | } 26 | 27 | body { 28 | background-color: transparent; 29 | } 30 | 31 | 32 | /* new */ 33 | .common-title { 34 | font-size: 16px; 35 | font-weight: 600; 36 | } 37 | 38 | .common-subtitle { 39 | font-size: 14px; 40 | font-weight: 500; 41 | } 42 | 43 | .common-bar { 44 | display: flex; 45 | flex-wrap: wrap; 46 | justify-content: space-between; 47 | align-items: center; 48 | } 49 | 50 | .common-bar+.common-bar { 51 | margin-top: 4px; 52 | } 53 | 54 | .common-button { 55 | min-width: 100px; 56 | width: 45%; 57 | margin-bottom: 6px; 58 | } 59 | 60 | /* 下载图片样式 */ 61 | .download-img { 62 | width: 19%; 63 | cursor: pointer; 64 | } 65 | 66 | .download-img:hover { 67 | width: 20%; 68 | border: solid 1px white; 69 | } -------------------------------------------------------------------------------- /media/main.js: -------------------------------------------------------------------------------- 1 | const vscode = acquireVsCodeApi(); 2 | const MainOrigin = "vscode-file://vscode-app"; 3 | function generateResources() { 4 | vscode.postMessage({ type: 'generateResources' }); 5 | } 6 | 7 | function removeResources() { 8 | vscode.postMessage({ type: 'removeResources' }); 9 | } 10 | 11 | function sendCommand(type, data) { 12 | window.top.postMessage({ type, data }, MainOrigin); 13 | } 14 | 15 | const receiveMessage = (event) => { 16 | const origin = event.origin || event.originalEvent.origin; 17 | if (origin !== MainOrigin) 18 | return; 19 | const { type, data } = event?.data || {}; 20 | if (type) 21 | switch (type) { 22 | case 'live2d-asoul-initDownloadBackground': 23 | initDownloadBackground(data); 24 | break; 25 | default: 26 | break; 27 | } 28 | } 29 | window.addEventListener('message', receiveMessage, false); 30 | 31 | let background_time = 30; 32 | let background_opacity = 0.2; 33 | let background_mode = 'cover'; 34 | 35 | function handleChangeTime(e) { 36 | const value = Number(e.target.value); 37 | if (value > 0) { 38 | background_time = value; 39 | } 40 | else e.target.value = '0.5'; 41 | } 42 | 43 | function handleChangeOpacity(e) { 44 | let value = e.target.value; 45 | value = value === 0 ? 0 : value ? Number(value) : 0.2; 46 | if (value >= 0 && value <= 1) { 47 | background_opacity = value; 48 | } 49 | } 50 | 51 | function handleChangeMode(e) { 52 | background_mode = e.target.value; 53 | } 54 | 55 | function setEleBackgroundConfig(input, select) { 56 | const eleInput = document.getElementById('background-opacity-input'); 57 | eleInput && (eleInput.value = input); 58 | background_opacity = input === undefined ? 0.2 : input; 59 | const eleSelect = document.getElementById('background-mode-select'); 60 | eleSelect && (eleSelect.value = select || ''); 61 | background_mode = select ? select : 'cover'; 62 | } 63 | 64 | function restoreBgConfig() { 65 | setEleBackgroundConfig(undefined, ''); 66 | modifyBackgroundConfig(); 67 | } 68 | 69 | function modifyBackgroundConfig() { 70 | const config = { opacity: background_opacity, backgroundSize: background_mode }; 71 | sendCommand('live2d-asoul-modifyBackgroundConfig', config); 72 | } 73 | 74 | function openBackgroundSetTime() { 75 | sendCommand('live2d-asoul-openBackgroundSetTime', background_time); 76 | } 77 | 78 | function closeBackgroundSetTime() { 79 | sendCommand('live2d-asoul-closeBackgroundSetTime'); 80 | } 81 | 82 | function openAutoLodash() { 83 | sendCommand('live2d-asoul-openAutoLodash'); 84 | } 85 | function closeAutoLodash() { 86 | sendCommand('live2d-asoul-closeAutoLodash'); 87 | } 88 | function lodashLive2d() { 89 | sendCommand('live2d-asoul-lodash'); 90 | } 91 | function closeLive2d() { 92 | sendCommand('live2d-asoul-close'); 93 | } 94 | function setAnchor(type) { 95 | sendCommand('live2d-asoul-setAnchor', type); 96 | } 97 | function saveCurrentConfig() { 98 | sendCommand('live2d-asoul-saveCurrentConfig'); 99 | } 100 | function resetPosition() { 101 | sendCommand('live2d-asoul-resetPosition'); 102 | } 103 | function saveBackground() { 104 | sendCommand('live2d-asoul-saveBackground'); 105 | } 106 | function loadBackground() { 107 | sendCommand('live2d-asoul-loadBackground'); 108 | } 109 | // 背景图下载相关 110 | function downloadBackground() { 111 | sendCommand('live2d-asoul-downloadBackground'); 112 | } 113 | function removeDownloadBackground() { 114 | const ele = document.getElementById('currentBackground'); 115 | while (ele.firstChild) { 116 | ele.removeChild(ele.firstChild); 117 | } 118 | } 119 | function initDownloadBackground(list) { 120 | const ele = document.getElementById('currentBackground'); 121 | while (ele.firstChild) { 122 | ele.removeChild(ele.firstChild); 123 | } 124 | list?.forEach(obj => { 125 | let eleImg = document.createElement("img"); 126 | eleImg.src = obj.img; 127 | eleImg.classList.add('download-img') 128 | eleImg.onclick = () => downloadIamge(obj.img, obj.author); 129 | ele.appendChild(eleImg); 130 | }) 131 | } 132 | //下载图片地址和图片名 133 | function downloadIamge(imgsrc, filename) { 134 | let image = new Image(); 135 | // 解决跨域 Canvas 污染问题 136 | image.setAttribute("crossOrigin", "anonymous"); 137 | image.onload = function () { 138 | let canvas = document.createElement("canvas"); 139 | canvas.width = image.width; 140 | canvas.height = image.height; 141 | let context = canvas.getContext("2d"); 142 | context.drawImage(image, 0, 0, image.width, image.height); 143 | let url = canvas.toDataURL("image/png"); //得到图片的base64编码数据 144 | let a = document.createElement("a"); // 生成一个a元素 145 | let event = new MouseEvent("click"); // 创建一个单击事件 146 | a.download = (filename || "photo") + new Date().getTime().toString(); // 设置图片名称 147 | a.href = url; // 将生成的URL设置为a.href属性 148 | a.dispatchEvent(event); // 触发a的单击事件 149 | }; 150 | image.src = imgsrc; 151 | } 152 | 153 | -------------------------------------------------------------------------------- /media/vscode.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --container-paddding: 20px; 3 | --input-padding-vertical: 6px; 4 | --input-padding-horizontal: 4px; 5 | --input-margin-vertical: 4px; 6 | --input-margin-horizontal: 0; 7 | } 8 | 9 | body { 10 | padding: 0 var(--container-paddding); 11 | color: var(--vscode-foreground); 12 | font-size: var(--vscode-font-size); 13 | font-weight: var(--vscode-font-weight); 14 | font-family: var(--vscode-font-family); 15 | background-color: var(--vscode-editor-background); 16 | } 17 | 18 | ol, 19 | ul { 20 | padding-left: var(--container-paddding); 21 | } 22 | 23 | body > *, 24 | form > * { 25 | margin-block-start: var(--input-margin-vertical); 26 | margin-block-end: var(--input-margin-vertical); 27 | } 28 | 29 | *:focus { 30 | outline-color: var(--vscode-focusBorder) !important; 31 | } 32 | 33 | a { 34 | color: var(--vscode-textLink-foreground); 35 | } 36 | 37 | a:hover, 38 | a:active { 39 | color: var(--vscode-textLink-activeForeground); 40 | } 41 | 42 | code { 43 | font-size: var(--vscode-editor-font-size); 44 | font-family: var(--vscode-editor-font-family); 45 | } 46 | 47 | button { 48 | border: none; 49 | padding: var(--input-padding-vertical) var(--input-padding-horizontal); 50 | width: 100%; 51 | text-align: center; 52 | outline: 1px solid transparent; 53 | outline-offset: 2px !important; 54 | color: var(--vscode-button-foreground); 55 | background: var(--vscode-button-background); 56 | } 57 | 58 | button:hover { 59 | cursor: pointer; 60 | background: var(--vscode-button-hoverBackground); 61 | } 62 | 63 | button:focus { 64 | outline-color: var(--vscode-focusBorder); 65 | } 66 | 67 | button.secondary { 68 | color: var(--vscode-button-secondaryForeground); 69 | background: var(--vscode-button-secondaryBackground); 70 | } 71 | 72 | button.secondary:hover { 73 | background: var(--vscode-button-secondaryHoverBackground); 74 | } 75 | 76 | input:not([type='checkbox']), 77 | textarea { 78 | display: block; 79 | width: 100%; 80 | border: none; 81 | font-family: var(--vscode-font-family); 82 | padding: var(--input-padding-vertical) var(--input-padding-horizontal); 83 | color: var(--vscode-input-foreground); 84 | outline-color: var(--vscode-input-border); 85 | background-color: var(--vscode-input-background); 86 | } 87 | 88 | input::placeholder, 89 | textarea::placeholder, 90 | select::placeholder { 91 | color: var(--vscode-input-placeholderForeground); 92 | } 93 | 94 | 95 | select { 96 | display: block; 97 | width: 100%; 98 | border: none; 99 | font-family: var(--vscode-font-family); 100 | padding: var(--input-padding-vertical) var(--input-padding-horizontal); 101 | color: var(--vscode-input-foreground); 102 | outline-color: var(--vscode-input-border); 103 | background-color: var(--vscode-input-background); 104 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vscode-live2d", 3 | "displayName": "A-SOUL-live2d", 4 | "description": "vscode插件-live2d看板娘。 默认角色会设置为asoul的嘉然", 5 | "version": "1.1.1", 6 | "author": "TheSecondAkari", 7 | "publisher": "TheSecondAkari", 8 | "license": "MIT", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/TheSecondAkari/vscode-live2d" 12 | }, 13 | "engines": { 14 | "vscode": "^1.95.3" 15 | }, 16 | "keywords": [ 17 | "vscode看板娘", 18 | "看板娘", 19 | "kanbanniang", 20 | "live2d", 21 | "asoul", 22 | "a-soul", 23 | "vtuber", 24 | "国内顶级偶像", 25 | "虚拟偶像" 26 | ], 27 | "icon": "logo.png", 28 | "categories": [ 29 | "Other" 30 | ], 31 | "activationEvents": [ 32 | "onView:vscode-live2d.live2dView" 33 | ], 34 | "main": "./out/extension.js", 35 | "contributes": { 36 | "views": { 37 | "explorer": [ 38 | { 39 | "type": "webview", 40 | "id": "vscode-live2d.live2dView", 41 | "name": "live2d-A-Soul" 42 | } 43 | ] 44 | }, 45 | "configuration": [ 46 | { 47 | "title": "看板娘配置", 48 | "type": "Object", 49 | "properties": { 50 | "vscode-live2d-asoul.enabled": { 51 | "type": "boolean", 52 | "default": true, 53 | "description": "是否启用live2d-asoul" 54 | } 55 | } 56 | } 57 | ] 58 | }, 59 | "scripts": { 60 | "vscode:prepublish": "yarn run compile", 61 | "compile": "tsc -p ./", 62 | "watch": "tsc -watch -p ./", 63 | "pretest": "yarn run compile && yarn run lint", 64 | "lint": "eslint src --ext ts", 65 | "test": "node ./out/test/runTest.js", 66 | "build": "vsce package" 67 | }, 68 | "devDependencies": { 69 | "@types/vscode": "^1.47.0", 70 | "@types/glob": "^7.1.4", 71 | "@types/mocha": "^9.0.0", 72 | "@types/node": "14.x", 73 | "@typescript-eslint/eslint-plugin": "^4.31.1", 74 | "@typescript-eslint/parser": "^4.31.1", 75 | "eslint": "^7.32.0", 76 | "glob": "^7.1.7", 77 | "mocha": "^9.1.1", 78 | "typescript": "^4.4.3", 79 | "@vscode/test-electron": "^1.6.2" 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /res/live2d/assets/Ava.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/assets/Ava.png -------------------------------------------------------------------------------- /res/live2d/assets/Diana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/assets/Diana.png -------------------------------------------------------------------------------- /res/live2d/assets/Eileen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/assets/Eileen.png -------------------------------------------------------------------------------- /res/live2d/assets/au.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/assets/au.png -------------------------------------------------------------------------------- /res/live2d/assets/beijixing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/assets/beijixing.png -------------------------------------------------------------------------------- /res/live2d/assets/border.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/assets/border.png -------------------------------------------------------------------------------- /res/live2d/assets/chong.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/assets/chong.jpg -------------------------------------------------------------------------------- /res/live2d/assets/jellyfish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/assets/jellyfish.png -------------------------------------------------------------------------------- /res/live2d/assets/jiaxintang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/assets/jiaxintang.png -------------------------------------------------------------------------------- /res/live2d/assets/naiqilin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/assets/naiqilin.png -------------------------------------------------------------------------------- /res/live2d/assets/pierce.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/assets/pierce.png -------------------------------------------------------------------------------- /res/live2d/assets/pin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/assets/pin.png -------------------------------------------------------------------------------- /res/live2d/assets/skate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/assets/skate.png -------------------------------------------------------------------------------- /res/live2d/assets/yigehun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/assets/yigehun.png -------------------------------------------------------------------------------- /res/live2d/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstload": false 3 | } -------------------------------------------------------------------------------- /res/live2d/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /res/live2d/lib/background.js: -------------------------------------------------------------------------------- 1 | // 背景图样式基础样式 2 | let backgroundCssNode; 3 | const typeList = [1, 2, 3, 4, 1, 2, 4, 1, 4]; // sort 参数的随机 1是浏览量,2是分享数,3是新发布,4是热门 4 | const pageList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]; 5 | var currentImgs = undefined; 6 | const IMGKEY = 'live2d-asoul-background'; 7 | const BgConfKey = 'live2d-asoul-background-config'; 8 | let backgroundConfig = JSON.parse(localStorage.getItem(BgConfKey) || '{}'); 9 | 10 | const getRandom = (arr) => arr[Math.floor((Math.random() * arr.length))]; 11 | 12 | const getRandomArray = (arr, num) => { 13 | let sData = arr.slice(0), i = arr.length, min = i - num, item, index; 14 | while (i-- > min) { 15 | index = Math.floor((i + 1) * Math.random()); 16 | item = sData[index]; 17 | sData[index] = sData[i]; 18 | sData[i] = item; 19 | } 20 | return sData.slice(min); 21 | } 22 | 23 | function addBackgroundStyle(styleContent) { 24 | removeBackgroundStyle(); //先清除旧样式 25 | const topDocument = window.top.document; 26 | backgroundCssNode = topDocument.createElement('style'); 27 | backgroundCssNode.appendChild(topDocument.createTextNode(styleContent)) 28 | topDocument.head.appendChild(backgroundCssNode); 29 | } 30 | 31 | function removeBackgroundStyle() { 32 | if (backgroundCssNode) { 33 | backgroundCssNode.remove(); 34 | backgroundCssNode = undefined; 35 | } 36 | } 37 | 38 | function getBackgroundStyleText(mainImgs, siderImgs) { 39 | const { opacity = 0.2, backgroundSize = 'cover' } = backgroundConfig; 40 | const commonStyle = ` 41 | content: ''; 42 | pointer-events: none; 43 | position: absolute; 44 | top: 0; 45 | left: 0; 46 | z-index: 99999; 47 | width: 100%; 48 | height: 100%; 49 | background-position: center center; 50 | background-repeat: no-repeat; 51 | background-size: ${backgroundSize}; 52 | opacity:${opacity}; 53 | `; 54 | 55 | const styleContent = ` 56 | ${addMainImagesCss(mainImgs, commonStyle)} 57 | ${addSidebarImagesCss(siderImgs, commonStyle)} 58 | `; 59 | 60 | return styleContent; 61 | } 62 | 63 | function addMainImagesCss(images, commonStyle, loop) { 64 | 65 | // ------ 在前景图时使用 ::after ------ 66 | const frontContent = '::after'; // useFront ? '::after' : '::before'; 67 | 68 | // ------ 组合样式 ------ 69 | const imageStyleContent = images 70 | .map((img, index) => { 71 | // ------ nth-child ------ 72 | // nth-child(1) 73 | let nthChildIndex = index + 1 + ''; 74 | // nth-child(3n + 1) 75 | if (loop) { 76 | nthChildIndex = `${images.length}n + ${nthChildIndex}`; 77 | } 78 | 79 | return ( 80 | // code editor 81 | `[id="workbench.parts.editor"] .split-view-view:nth-child(${nthChildIndex}) ` + 82 | `.editor-container .editor-instance>.monaco-editor ` + 83 | `.overflow-guard>.monaco-scrollable-element${frontContent}{background-image: url('${img}') !important;${commonStyle}}` + 84 | '\n' + 85 | // home screen 86 | `[id="workbench.parts.editor"] .split-view-view:nth-child(${nthChildIndex}) ` + 87 | `.empty::before { background-image: url('${img}') !important;${commonStyle} }` 88 | ); 89 | }) 90 | .join('\n'); 91 | 92 | const content = ` 93 | ${imageStyleContent} 94 | [id="workbench.parts.editor"] .split-view-view .editor-container .editor-instance>.monaco-editor .overflow-guard>.monaco-scrollable-element>.monaco-editor-background{background: none;} 95 | `; 96 | 97 | return content; 98 | } 99 | 100 | const addSidebarImagesCss = function (images, commonStyle, loop) { 101 | const sidebarItems = [ 102 | "workbench.view.explorer", 103 | "workbench.view.search", 104 | "workbench.view.scm", 105 | "workbench.view.debug", 106 | "workbench.view.extensions" 107 | ]; 108 | 109 | // ------ 组合样式 ------ 110 | const imageStyleContent = images 111 | .map((img, index) => { 112 | // ------ nth-child ------ 113 | // nth-child(1) 114 | let nthChildIndex = index + 1 + ''; 115 | // nth-child(3n + 1) 116 | if (loop) { 117 | nthChildIndex = `${images.length}n + ${nthChildIndex}`; 118 | } 119 | const Items = sidebarItems && sidebarItems.length ? sidebarItems : ['workbench.view.explorer']; 120 | // sidebar content css 121 | return ( 122 | Items.map( 123 | id => 124 | `[id="${id}"] .split-view-view:nth-child(${nthChildIndex}) ` + 125 | `.pane-body .monaco-list>.monaco-scrollable-element::before{background-image: url('${img}') !important;${commonStyle}}` 126 | ).join('\n') + '\n' 127 | ); 128 | }) 129 | .join('\n'); 130 | return imageStyleContent; 131 | }; 132 | 133 | function getAsoulImgs(callback) { 134 | fetch(`https://api.asoulfanart.com:9000/getPic?page=${getRandom(pageList)}&tag_id=0&sort=${getRandom(typeList)}&part=0&rank=0&ctime=0&type=1`, { 135 | cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached 136 | credentials: "same-origin", // include, same-origin, *omit 137 | headers: { 138 | "user-agent": "Mozilla/4.0 MDN Example", 139 | "content-type": "application/json" 140 | }, 141 | method: "GET", // *GET, POST, PUT, DELETE, etc. 142 | mode: "cors", // no-cors, cors, *same-origin 143 | redirect: "follow", // manual, *follow, error 144 | referrer: "no-referrer" // *client, no-referrer 145 | }) 146 | .then(response => response.json()) 147 | .then(function (myJson) { 148 | if (Array.isArray(myJson) && myJson.length > 0) { 149 | const imgs = myJson.map(item => ({ author: item.name || 'none', img: getRandom(item.pic_url).img_src })); 150 | const targets = getRandomArray(imgs, 10); 151 | callback && callback(targets); 152 | } 153 | }); 154 | } 155 | 156 | // 切换背景的具体操作 157 | function changeAction(targets) { 158 | if (targets) { 159 | const imgs = targets.map(i => i.img); 160 | const sidebar = imgs.slice(0, 5); 161 | const coding = imgs.slice(5, 10); 162 | currentImgs = targets; 163 | const css = getBackgroundStyleText(sidebar, coding); 164 | addBackgroundStyle(css); 165 | } 166 | } 167 | 168 | // 设置背景图,从接口获取,随机设置 169 | const changeBackground = () => getAsoulImgs(changeAction) 170 | 171 | // 移除背景图 172 | function removeBackground() { 173 | removeBackgroundStyle(); 174 | } 175 | 176 | // 保存背景图 177 | function saveBackground() { 178 | if (currentImgs) 179 | localStorage.setItem(IMGKEY, JSON.stringify(currentImgs)); 180 | } 181 | 182 | // 加载背景图 183 | function loadBackground() { 184 | const str = localStorage.getItem(IMGKEY); 185 | if (str) { 186 | const imgs = JSON.parse(str); 187 | changeAction(typeof imgs[0] === 'string' ? imgs.map(img => ({ img })) : imgs); 188 | } 189 | } 190 | 191 | // 设置定时切换背景图 192 | let timer = undefined; 193 | function openBackgroundSetTime(time) { 194 | closeBackgroundSetTime(); 195 | if (typeof time === 'number' && time > 0) { 196 | timer = setInterval(() => { 197 | changeBackground(); 198 | }, 1000 * 60 * time) 199 | // 加入旋转样式 200 | document.getElementsByClassName('pio-background')[0].classList.add('normal-cycle'); 201 | } 202 | } 203 | 204 | // 关闭定时切换背景图 205 | function closeBackgroundSetTime() { 206 | if (timer) { 207 | clearInterval(timer); 208 | timer = undefined; 209 | // 移除旋转样式 210 | document.getElementsByClassName('pio-background')[0].classList.remove('normal-cycle'); 211 | } 212 | } 213 | 214 | // 修改背景图样式配置: 不透明度、适配模式 215 | function modifyBackgroundConfig(config) { 216 | backgroundConfig = config; 217 | localStorage.setItem(BgConfKey, JSON.stringify(config)); 218 | if (currentImgs?.length) { 219 | changeAction(currentImgs) 220 | } 221 | } -------------------------------------------------------------------------------- /res/live2d/lib/load.js: -------------------------------------------------------------------------------- 1 | // 通过读取远程配置文件,进行设置默认信息 2 | function getInitConfig(callback) { 3 | fetch(`https://cdn.jsdelivr.net/gh/TheSecondAkari/vscode-live2d@latest/live2dExtraConfig.json`, { 4 | cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached 5 | credentials: "same-origin", // include, same-origin, *omit 6 | headers: { 7 | "user-agent": "Mozilla/4.0 MDN Example", 8 | }, 9 | method: "GET", // *GET, POST, PUT, DELETE, etc. 10 | mode: "cors", // no-cors, cors, *same-origin 11 | redirect: "follow", // manual, *follow, error 12 | referrer: "no-referrer" // *client, no-referrer 13 | }) 14 | .then(response => response.json()) 15 | .then(function (myJson) { 16 | callback && callback(myJson) 17 | }) 18 | .catch(e => { 19 | callback && callback() 20 | }); 21 | } 22 | 23 | var 溜冰场; 24 | 25 | // ExtraInfo 是远程维护的配置信息 26 | getInitConfig((ExtraInfo) => { 27 | if (ExtraInfo) { 28 | const list = ExtraInfo["溜冰场"]; 29 | if (Array.isArray(list) && list.length > 0) { 30 | 溜冰场 = list; 31 | } 32 | } 33 | }) 34 | 35 | var 引流 = [ 36 | "https://space.bilibili.com/672328094", 37 | "https://space.bilibili.com/672346917", 38 | "https://space.bilibili.com/672353429", 39 | "https://space.bilibili.com/672342685", 40 | "https://space.bilibili.com/351609538", 41 | "https://www.bilibili.com/video/BV1FZ4y1F7HH", 42 | "https://www.bilibili.com/video/BV1FX4y1g7u8", 43 | "https://www.bilibili.com/video/BV1aK4y1P7Cg", 44 | "https://www.bilibili.com/video/BV17A411V7Uh", 45 | "https://www.bilibili.com/video/BV1AV411v7er", 46 | "https://www.bilibili.com/video/BV1564y1173Q", 47 | "https://www.bilibili.com/video/BV1MX4y1N75X", 48 | "https://www.bilibili.com/video/BV17h411U71w", 49 | "https://www.bilibili.com/video/BV1ry4y1Y71t", 50 | "https://www.bilibili.com/video/BV1Sy4y1n7c4", 51 | "https://www.bilibili.com/video/BV1PN411X7QW", 52 | "https://www.bilibili.com/video/BV1Dp4y1H7iB", 53 | "https://www.bilibili.com/video/BV1bi4y1P7Eh", 54 | "https://www.bilibili.com/video/BV1vQ4y1Z7C2", 55 | "https://www.bilibili.com/video/BV1oU4y1h7Sc", 56 | "https://www.bilibili.com/video/BV1M64y1a7zh", 57 | "https://www.bilibili.com/video/BV1L5411w7eM", 58 | "https://www.bilibili.com/video/BV1HU4y1L7cF", 59 | "https://www.bilibili.com/video/BV1Pq4y1Z7aa", 60 | "https://www.bilibili.com/video/BV1x64y1Y7JR", 61 | "https://www.bilibili.com/video/BV1NL4y1a7KM", 62 | "https://www.bilibili.com/video/BV1n44y1b7G2", 63 | "https://www.bilibili.com/video/BV1EQ4y1z7WL", 64 | "https://www.bilibili.com/video/BV1sv411u78Q", 65 | "https://www.bilibili.com/video/BV1Lv411N7Bm", 66 | "https://www.bilibili.com/video/BV1eo4y1S79a", 67 | "https://www.bilibili.com/video/BV1Rq4y1p7sY", 68 | "https://www.bilibili.com/video/BV1T5411T7u8", 69 | "https://www.bilibili.com/video/BV1DU4y15767", 70 | "https://www.bilibili.com/video/BV1c5411u7Zv", 71 | "https://www.bilibili.com/video/BV1m54y1V7mX", 72 | "https://www.bilibili.com/video/BV1a44y1z71P", 73 | "https://www.bilibili.com/video/BV1sV41177qM", 74 | "https://www.bilibili.com/video/BV1go4y1y7kV", 75 | "https://www.bilibili.com/video/BV1JM4y157Tg", 76 | "https://www.bilibili.com/video/BV1e44y147nb", 77 | "https://www.bilibili.com/video/BV1Ur4y1y7RP", 78 | "https://www.bilibili.com/video/BV1kQ4y1i7LG", 79 | "https://www.bilibili.com/video/BV1Jq4y157r1", 80 | "https://www.bilibili.com/video/BV14q4y1K71L", 81 | "https://www.bilibili.com/video/BV1ty4y1V7k4", 82 | "https://www.bilibili.com/video/BV1B54y1V7Ta", 83 | "https://www.bilibili.com/video/BV1Mh411Y7vS", 84 | "https://www.bilibili.com/video/BV1L64y1z7Df", 85 | "https://www.bilibili.com/video/BV1p5411w71j", 86 | "https://www.bilibili.com/video/BV1b64y117Kk", 87 | "https://www.bilibili.com/video/BV1RB4y1T723", 88 | "https://www.bilibili.com/video/BV1HP4y1Y7kq", 89 | "https://www.bilibili.com/video/BV1vL4y1z7Fh", 90 | "https://www.bilibili.com/video/BV1764y1q7JA", 91 | "https://www.bilibili.com/video/BV1Kq4y1n7p4", 92 | "https://www.bilibili.com/video/BV1JA411G7Dk", 93 | "https://www.bilibili.com/video/BV14A411P7Tg", 94 | "https://www.bilibili.com/video/BV1vQ4y1Z7C2", 95 | "https://www.bilibili.com/video/BV1TV411H7uf", 96 | "https://www.bilibili.com/video/BV1kq4y1W7hW", 97 | "https://www.bilibili.com/video/BV1Eb4y1C7oJ", 98 | "https://www.bilibili.com/video/BV1dL411n7sY", 99 | "https://www.bilibili.com/video/BV18h411z7gh", 100 | "https://www.bilibili.com/video/BV1sv411j7W8", 101 | "https://www.bilibili.com/video/BV1JP4y1x73T", 102 | "https://www.bilibili.com/video/BV1CM4y1V7ho", 103 | "https://www.bilibili.com/video/BV1444y1z7EV", 104 | "https://www.bilibili.com/video/BV1Ah41167DS", 105 | "https://www.bilibili.com/video/BV1FN411o7nt", 106 | "https://www.bilibili.com/video/BV1Rb4y1k7F7", 107 | "https://www.bilibili.com/video/BV1AB4y1g7CQ", 108 | "https://www.bilibili.com/video/BV1Gq4y1W7wT", 109 | "https://www.bilibili.com/video/BV1z3411y7nP", 110 | "https://www.bilibili.com/video/BV14h411B7mE", 111 | "https://www.bilibili.com/video/BV1Uy4y1j7rN", 112 | "https://www.bilibili.com/video/BV1NX4y1w7JN", 113 | "https://www.bilibili.com/video/BV1464y1W7gv", 114 | "https://www.bilibili.com/video/BV19V411H7tn", 115 | "https://www.bilibili.com/video/BV1L54y1n7yA", 116 | "https://www.bilibili.com/video/BV1f64y1k7Ff", 117 | "https://www.bilibili.com/video/BV12b4y1X7S8", 118 | "https://www.bilibili.com/video/BV1QQ4y1272S", 119 | "https://www.bilibili.com/video/BV12f4y1F7jD", 120 | "https://www.bilibili.com/video/BV1sM4y1g7Dg", 121 | "https://www.bilibili.com/video/BV1tA411V7b5", 122 | "https://www.bilibili.com/video/BV15V411E7hr", 123 | "https://www.bilibili.com/video/BV1J64y1m7Eu", 124 | "https://www.bilibili.com/video/BV1W54y1V7bV", 125 | "https://www.bilibili.com/video/BV15v411e7qa", 126 | "https://www.bilibili.com/video/BV1gy4y147vp", 127 | "https://www.bilibili.com/video/BV1DA411c7U3", 128 | "https://www.bilibili.com/video/BV11b4y167Gc", 129 | "https://www.bilibili.com/video/BV1bQ4y1d7n6", 130 | "https://www.bilibili.com/video/BV1X5411K7W5", 131 | "https://www.bilibili.com/video/BV12V411E7sn", 132 | "https://www.bilibili.com/video/BV1wv411K7LT", 133 | "https://www.bilibili.com/video/BV1Eq4y197ho", 134 | "https://www.bilibili.com/video/BV1aP4y1s7Wy", 135 | "https://www.bilibili.com/video/BV1Y64y1U7FZ" 136 | ] 137 | 138 | const initConfig = { 139 | mode: "fixed", 140 | hidden: false, 141 | content: { 142 | link: 引流, 143 | welcome: ["Hi!"], 144 | touch: "", 145 | home: ["这里有很多好听的", "边听asoul的演唱边敲代码?"], 146 | skin: [["诶,想看看其他团员吗?", "嘉晚饭yyds", "嘉晚饭是真的"], "替换后入场文本"], 147 | background: ["要切换背景图吗?", "这次切背景图会切到我吗?", "换,换一下背景图也不是不可以啦",], 148 | }, 149 | model: [ 150 | "./models/Diana/Diana.model3.json", 151 | "./models/Ava/Ava.model3.json", 152 | ], 153 | tips: true, 154 | onModelLoad: onModelLoad 155 | } 156 | 157 | function 加载圣·嘉然() { 158 | pio_reference = new Paul_Pio(initConfig) 159 | 160 | pio_alignment = "left" 161 | 162 | // Then apply style 163 | pio_refresh_style() 164 | } 165 | 166 | function reSizeLive2d() { 167 | const defaultWidth = 280; // 默认宽度280px , zoom = 1 168 | const container = document.getElementById("pio-container"); 169 | if (container) 170 | container.style.zoom = Math.round(window.innerWidth / defaultWidth * 100) / 100; 171 | } 172 | 173 | window.addEventListener("resize", reSizeLive2d); 174 | 175 | function onModelLoad(model) { 176 | const container = document.getElementById("pio-container") 177 | reSizeLive2d(); // 初始加载 178 | const canvas = document.getElementById("pio") 179 | const modelNmae = model.internalModel.settings.name 180 | const coreModel = model.internalModel.coreModel 181 | const motionManager = model.internalModel.motionManager 182 | 183 | let touchList = [ 184 | { 185 | text: "点击展示文本1", 186 | motion: "Idle" 187 | }, 188 | { 189 | text: "点击展示文本2", 190 | motion: "Idle" 191 | } 192 | ] 193 | 194 | function playAction(action) { 195 | action.text && pio_reference.modules.render(action.text) 196 | action.motion && pio_reference.model.motion(action.motion) 197 | 198 | if (action.from && action.to) { 199 | Object.keys(action.from).forEach(id => { 200 | const hidePartIndex = coreModel._partIds.indexOf(id) 201 | TweenLite.to(coreModel._partOpacities, 0.6, { [hidePartIndex]: action.from[id] }); 202 | // coreModel._partOpacities[hidePartIndex] = action.from[id] 203 | }) 204 | 205 | motionManager.once("motionFinish", (data) => { 206 | Object.keys(action.to).forEach(id => { 207 | const hidePartIndex = coreModel._partIds.indexOf(id) 208 | TweenLite.to(coreModel._partOpacities, 0.6, { [hidePartIndex]: action.to[id] }); 209 | // coreModel._partOpacities[hidePartIndex] = action.to[id] 210 | }) 211 | }) 212 | } 213 | } 214 | 215 | window.live2d_playAction = playAction; // 挂载到window上,方便调用 216 | 217 | canvas.onclick = function () { 218 | if (motionManager.state.currentGroup !== "Idle") return 219 | 220 | const action = pio_reference.modules.rand(touchList) 221 | playAction(action) 222 | } 223 | 224 | if (modelNmae === "Diana") { 225 | container.dataset.model = "Diana" 226 | initConfig.content.skin[1] = ["我是吃货担当 嘉然 Diana~"] 227 | playAction({ motion: "Tap抱阿草-左手" }) 228 | 229 | touchList = [ 230 | { 231 | text: "嘉心糖屁用没有", 232 | motion: "Tap生气 -领结" 233 | }, 234 | { 235 | text: "有人急了,但我不说是谁~", 236 | motion: "Tap= = 左蝴蝶结" 237 | }, 238 | { 239 | text: "呜呜...呜呜呜....", 240 | motion: "Tap哭 -眼角" 241 | }, 242 | { 243 | text: "想然然了没有呀~", 244 | motion: "Tap害羞-中间刘海" 245 | }, 246 | { 247 | text: "阿草好软呀~", 248 | motion: "Tap抱阿草-左手" 249 | }, 250 | { 251 | text: "不要再戳啦!好痒!", 252 | motion: "Tap摇头- 身体" 253 | }, 254 | { 255 | text: "嗷呜~~~", 256 | motion: "Tap耳朵-发卡" 257 | }, 258 | { 259 | text: "zzZ。。。", 260 | motion: "Leave" 261 | }, 262 | { 263 | text: "哇!好吃的!", 264 | motion: "Tap右头发" 265 | }, 266 | ] 267 | 268 | } else if (modelNmae === "Ava") { 269 | container.dataset.model = "Ava" 270 | initConfig.content.skin[1] = ["我是拉胯Gamer担当 向晚 AvA~"] 271 | playAction({ 272 | motion: "Tap左眼", 273 | from: { 274 | "Part15": 1 275 | }, 276 | to: { 277 | "Part15": 0 278 | } 279 | }) 280 | 281 | touchList = [ 282 | { 283 | text: "水母 水母~ 只是普通的生物", 284 | motion: "Tap右手" 285 | }, 286 | { 287 | text: "可爱的鸽子鸽子~我喜欢你~", 288 | motion: "Tap胸口项链", 289 | from: { 290 | "Part12": 1 291 | }, 292 | to: { 293 | "Part12": 0 294 | } 295 | }, 296 | { 297 | text: "好...好兄弟之间喜欢很正常啦", 298 | motion: "Tap中间刘海", 299 | from: { 300 | "Part12": 1 301 | }, 302 | to: { 303 | "Part12": 0 304 | } 305 | }, 306 | { 307 | text: "啊啊啊!怎么推流辣", 308 | motion: "Tap右眼", 309 | from: { 310 | "Part16": 1 311 | }, 312 | to: { 313 | "Part16": 0 314 | } 315 | }, 316 | { 317 | text: "你怎么老摸我,我的身体是不是可有魅力", 318 | motion: "Tap嘴" 319 | }, 320 | { 321 | text: "AAAAAAAAAAvvvvAAA 向晚!", 322 | motion: "Tap左眼", 323 | from: { 324 | "Part15": 1 325 | }, 326 | to: { 327 | "Part15": 0 328 | } 329 | } 330 | ] 331 | canvas.width = model.width * 1.2 332 | const hideParts = [ 333 | "Part5", // 晕 334 | "neko", // 喵喵拳 335 | "game", // 左手游戏手柄 336 | "Part15", // 墨镜 337 | // "Part21", // 右手小臂 338 | // "Part22", // 左手垂下 339 | "gitar", // 吉他 !和 上面 part21 22 冲突 340 | "Part", // 双手抱拳 341 | "Part16", // 惊讶特效 342 | "Part12" // 小心心 343 | ] 344 | const hidePartsIndex = hideParts.map(id => coreModel._partIds.indexOf(id)) 345 | hidePartsIndex.forEach(idx => { 346 | coreModel._partOpacities[idx] = 0 347 | }) 348 | } 349 | } 350 | 351 | 352 | var pio_reference 353 | window.onload = 加载圣·嘉然 354 | -------------------------------------------------------------------------------- /res/live2d/lib/pio/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/lib/pio/avatar.png -------------------------------------------------------------------------------- /res/live2d/lib/pio/pio.css: -------------------------------------------------------------------------------- 1 | /* ---- 2 | 3 | # Pio Plugin 4 | # By: Dreamer-Paul 5 | # Modify: journey-ad 6 | # Last Update: 2021.5.10 7 | 8 | 一个支持更换 Live2D 模型的 Typecho 插件。 9 | 10 | 本代码为奇趣保罗原创,并遵守 GPL 2.0 开源协议。欢迎访问我的博客:https://paugram.com 11 | 12 | ---- */ 13 | 14 | .pio-container { 15 | bottom: 0; 16 | z-index: 52; 17 | color: #666; 18 | position: fixed; 19 | user-select: none; 20 | cursor: grab; 21 | font-size: 12px; 22 | /* 子元素的em动态调整 */ 23 | } 24 | 25 | .pio-container:active { 26 | cursor: grabbing; 27 | } 28 | 29 | .pio-container .pio-show { 30 | left: -1.2em; 31 | bottom: -0.2em; 32 | width: 6em; 33 | height: 6.8em; 34 | display: none; 35 | cursor: pointer; 36 | position: absolute; 37 | transition: all .3s; 38 | background: url(avatar.png) center/contain; 39 | opacity: 0.7; 40 | } 41 | 42 | .pio-container.hidden .pio-show { 43 | display: block; 44 | } 45 | 46 | .pio-container.hidden .pio-show:hover { 47 | opacity: 0.9; 48 | transform: translateX(.5em); 49 | } 50 | 51 | .pio-container.hidden #pio { 52 | display: none; 53 | } 54 | 55 | .pio-container.hidden .pio-dialog { 56 | display: none; 57 | } 58 | 59 | .pio-container.left { 60 | left: 0 61 | } 62 | 63 | .pio-container.right { 64 | right: 0 65 | } 66 | 67 | .pio-container.active { 68 | cursor: move 69 | } 70 | 71 | .pio-container.static { 72 | pointer-events: none 73 | } 74 | 75 | .pio-container .pio-action { 76 | top: 1.2em; 77 | opacity: 0; 78 | position: absolute; 79 | transition: opacity .3s; 80 | } 81 | 82 | .pio-container.left .pio-action { 83 | right: 0 84 | } 85 | 86 | .pio-container.right .pio-action { 87 | left: 0 88 | } 89 | 90 | .pio-container:hover .pio-action { 91 | opacity: 1 92 | } 93 | 94 | .pio-action span { 95 | color: #fff; 96 | width: 2em; 97 | height: 2em; 98 | margin-bottom: 0.6em; 99 | display: block; 100 | cursor: pointer; 101 | text-align: center; 102 | margin-bottom: .5em; 103 | background-size: 100%; 104 | } 105 | 106 | .pio-action .pio-home { 107 | background-image: url("../../assets/yigehun.png"); 108 | } 109 | 110 | .pio-action .pio-skin { 111 | background-image: url("../../assets/chong.jpg"); 112 | } 113 | 114 | .pio-action .pio-skate { 115 | background-image: url("../../assets/jellyfish.png"); 116 | } 117 | 118 | .pio-action .pio-info { 119 | background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 500 500' xmlns='http://www.w3.org/2000/svg'%3E%3Crect transform='rotate(45.001 238.211 363.575)' x='29.285' y='22.411' width='273.903' height='505.038' rx='70' ry='70' fill='%23dcdcdc'/%3E%3Cpath d='M218.543 249.999l-47.186 47.186c-8.987 8.988-8.987 22.47 0 31.457 8.988 8.988 22.47 8.988 31.457 0L250 281.456l15.728 15.729c17.976 17.976 17.976 46.063 0 64.038l-64.037 64.038c-17.976 17.975-46.063 17.975-64.038 0l-64.038-64.038c-17.975-17.975-17.975-46.062 0-64.038l64.038-64.037c17.975-17.976 46.062-17.976 64.038 0l16.852 16.851z' fill='%23fff'/%3E%3Cpath d='M281.457 249.999l47.186-47.186c8.988-8.987 8.988-22.469 0-31.457-8.987-8.987-22.469-8.987-31.457 0L250 218.542l-15.729-15.729c-17.975-17.975-17.975-46.062 0-64.037l64.038-64.038c17.975-17.975 46.062-17.975 64.038 0l64.037 64.038c17.977 17.975 17.977 46.062 0 64.037l-64.037 64.038c-17.976 17.976-46.063 17.976-64.038 0l-16.852-16.852z' fill='%2361a3e0'/%3E%3C/svg%3E"); 120 | } 121 | 122 | .pio-action .pio-ava { 123 | background-image: url('../../assets/Ava.png'); 124 | } 125 | 126 | .pio-action .pio-diana { 127 | background-image: url('../../assets/jiaxintang.png'); 128 | } 129 | 130 | .pio-action .pio-eileen { 131 | background-image: url('../../assets/naiqilin.png'); 132 | } 133 | 134 | /* 背景图图标是和eileen是一样的 */ 135 | .pio-action .pio-background { 136 | background-image: url('../../assets/naiqilin.png'); 137 | } 138 | 139 | .pio-action .pio-asoulfans { 140 | background-image: url('../../assets/beijixing.png'); 141 | } 142 | 143 | .normal-cycle { 144 | animation: cycle 1s linear infinite; 145 | } 146 | 147 | @keyframes cycle { 148 | 0% { 149 | -webkit-transform: rotate(0deg); 150 | } 151 | 152 | 25% { 153 | -webkit-transform: rotate(90deg); 154 | } 155 | 156 | 50% { 157 | -webkit-transform: rotate(180deg); 158 | } 159 | 160 | 75% { 161 | -webkit-transform: rotate(270deg); 162 | } 163 | 164 | 100% { 165 | -webkit-transform: rotate(360deg); 166 | } 167 | } 168 | 169 | .pio-container .pio-dialog { 170 | top: -2.2em; 171 | opacity: 0; 172 | z-index: -1; 173 | font-size: 1.2em; 174 | min-width: 12em; 175 | background: #fff; 176 | padding: .75em 1em; 177 | border-radius: 1em; 178 | visibility: hidden; 179 | position: absolute; 180 | word-break: break-all; 181 | border: 1px solid #eee; 182 | transition: opacity .3s, visibility .3s; 183 | } 184 | 185 | .pio-container .pio-dialog.active { 186 | opacity: 1; 187 | visibility: visible; 188 | } 189 | 190 | .pio-container.left .pio-dialog { 191 | left: 1.5em 192 | } 193 | 194 | .pio-container.right .pio-dialog { 195 | right: 1.5em 196 | } 197 | 198 | #pio { 199 | vertical-align: middle; 200 | width: 22em; 201 | } -------------------------------------------------------------------------------- /res/live2d/lib/pio/pio.js: -------------------------------------------------------------------------------- 1 | /* ---- 2 | 3 | # Pio Plugin 4 | # By: Dreamer-Paul 5 | # Modify: journey-ad 6 | # Last Update: 2021.5.4 7 | 8 | 一个支持更换 Live2D 模型的 Typecho 插件。 9 | 10 | 本代码为奇趣保罗原创,并遵守 GPL 2.0 开源协议。欢迎访问我的博客:https://paugram.com 11 | 12 | ---- */ 13 | 14 | var Paul_Pio = function (prop) { 15 | var that = this; 16 | 17 | // 音频实例,只维护一个 18 | var audioInstance = new Audio(); 19 | 20 | var current = { 21 | idol: localStorage.getItem('live2d-asoul-model') ? Number(localStorage.getItem('live2d-asoul-model')) : 0, 22 | menu: document.querySelector(".pio-container .pio-action"), 23 | canvas: document.getElementById("pio"), 24 | body: document.querySelector(".pio-container"), 25 | root: document.location.protocol + '//' + document.location.hostname + '/' 26 | }; 27 | 28 | /* - 方法 */ 29 | var modules = { 30 | // 更换模型 31 | idol: function () { 32 | current.idol < (prop.model.length - 1) ? current.idol++ : current.idol = 0; 33 | return current.idol; 34 | }, 35 | // 创建内容 36 | create: function (tag, prop) { 37 | var e = document.createElement(tag); 38 | if (prop.class) e.className = prop.class; 39 | return e; 40 | }, 41 | // 随机内容 42 | rand: function (arr) { 43 | return arr[Math.floor(Math.random() * arr.length)]; 44 | }, 45 | // 播放音频 46 | audioPlay: function (url) { 47 | if (url && audioInstance) { 48 | audioInstance.pause(); 49 | audioInstance.src = url; 50 | audioInstance.play().catch((e) => { 51 | if (e.toString() == 'NotSupportedError: Failed to load because no supported source was found.') 52 | this.render('vscode默认不支持html音频处理,如何开启可查看该插件简介') 53 | }) 54 | } 55 | }, 56 | // 创建对话框方法 57 | render: function (text) { 58 | if (text.constructor === Array) { 59 | dialog.innerHTML = modules.rand(text); 60 | } 61 | else if (text.constructor === String) { 62 | dialog.innerHTML = text; 63 | } 64 | else { 65 | dialog.innerHTML = "输入内容出现问题了 X_X"; 66 | } 67 | 68 | dialog.classList.add("active"); 69 | 70 | clearTimeout(this.t); 71 | this.t = setTimeout(function () { 72 | dialog.classList.remove("active"); 73 | }, 3000); 74 | }, 75 | // 是否为移动设备 76 | isMobile: function () { 77 | var ua = window.navigator.userAgent.toLowerCase(); 78 | ua = ua.indexOf("mobile") || ua.indexOf("android") || ua.indexOf("ios"); 79 | 80 | return window.innerWidth < 500 || ua !== -1; 81 | } 82 | }; 83 | this.modules = modules; 84 | 85 | var elements = { 86 | home: modules.create("span", { class: "pio-home" }), 87 | background: modules.create("span", { class: "pio-background" }), // 用于切换背景图 88 | skin: modules.create("span", { class: "pio-skin" }), 89 | skate: modules.create("span", { class: "pio-skate" }), 90 | audio: modules.create("span", { class: "pio-diana" }), // 语音功能测试 91 | fans: modules.create("span", { class: "pio-asoulfans" }), 92 | info: modules.create("span", { class: "pio-info" }), 93 | // close: modules.create("span", { class: "pio-close" }), 94 | // show: modules.create("div", { class: "pio-show" }) 95 | }; 96 | 97 | var dialog = modules.create("div", { class: "pio-dialog" }); 98 | current.body.appendChild(dialog); 99 | // current.body.appendChild(elements.show); // 自带的显示和关闭 注释掉 100 | 101 | /* - 提示操作 */ 102 | var action = { 103 | // 欢迎 104 | welcome: function () { 105 | if (prop.tips) { 106 | var text, hour = new Date().getHours(); 107 | 108 | if (hour > 22 || hour <= 5) { 109 | text = '你是夜猫子呀?这么晚还不睡觉,明天起的来嘛'; 110 | } 111 | else if (hour > 5 && hour <= 8) { 112 | text = '早上好!'; 113 | } 114 | else if (hour > 8 && hour <= 11) { 115 | text = '上午好!工作顺利嘛,不要久坐,多起来走动走动哦!'; 116 | } 117 | else if (hour > 11 && hour <= 14) { 118 | text = '中午了,工作了一个上午,现在是午餐时间!'; 119 | } 120 | else if (hour > 14 && hour <= 17) { 121 | text = '午后很容易犯困呢,今天的运动目标完成了吗?'; 122 | } 123 | else if (hour > 17 && hour <= 19) { 124 | text = '傍晚了!窗外夕阳的景色很美丽呢,最美不过夕阳红~'; 125 | } 126 | else if (hour > 19 && hour <= 21) { 127 | text = '晚上好,今天过得怎么样?'; 128 | } 129 | else if (hour > 21 && hour <= 23) { 130 | text = '已经这么晚了呀,早点休息吧,晚安~'; 131 | } 132 | else { 133 | text = "奇趣保罗说:这个是无法被触发的吧,哈哈"; 134 | } 135 | 136 | modules.render(text); 137 | } 138 | else { 139 | modules.render(prop.content.welcome || "欢迎使用本插件,记得去B站关注a-soul!"); 140 | } 141 | 142 | // 定时提醒,每一小时提示一下需要休息了 143 | setInterval(() => { 144 | modules.render('已经连续一个小时写代码了,请注意活动一下身体'); 145 | }, 1000 * 60 * 60); 146 | }, 147 | // 触摸 148 | touch: function () { 149 | current.canvas.onclick = function () { 150 | modules.render(prop.content.touch || ["你在干什么?", "再摸我就报警了!", "HENTAI!", "不可以这样欺负我啦!"]); 151 | }; 152 | }, 153 | // 右侧按钮 154 | buttons: function () { 155 | // asoulworld网站 156 | elements.home.onclick = function () { 157 | window.open('https://studio.asf.ink/'); 158 | }; 159 | elements.home.onmouseover = function () { 160 | modules.render(prop.content.home || "想查看更多A-Soul的信息吗?"); 161 | }; 162 | current.menu.appendChild(elements.home); 163 | 164 | // 更换背景图 165 | elements.background.onclick = function () { 166 | changeBackground && changeBackground(); 167 | }; 168 | elements.background.onmouseover = function () { 169 | modules.render(prop.content.background || "背景图?早该换换了"); 170 | }; 171 | current.menu.appendChild(elements.background); 172 | 173 | // 更换模型 174 | elements.skin.onclick = function () { 175 | const modelIndex = modules.idol(); 176 | localStorage.setItem('live2d-asoul-model', modelIndex); 177 | that.model = loadlive2d("pio", prop.model[modelIndex], model => { 178 | prop.onModelLoad && prop.onModelLoad(model) 179 | prop.content.skin && prop.content.skin[1] ? modules.render(prop.content.skin[1]) : modules.render("新衣服真漂亮~"); 180 | }); 181 | }; 182 | elements.skin.onmouseover = function () { 183 | prop.content.skin && prop.content.skin[0] ? modules.render(prop.content.skin[0]) : modules.render("想看看我的新衣服吗?"); 184 | }; 185 | if (prop.model.length > 1) current.menu.appendChild(elements.skin); 186 | 187 | // 溜冰场 188 | elements.skate.onclick = function () { 189 | const link = window.溜冰场 || prop.content.link; 190 | if (link) { 191 | if (Array.isArray(link)) 192 | window.open(modules.rand(link)) 193 | else if (typeof link === 'string') 194 | window.open(link); 195 | } 196 | else { 197 | window.open("https://paugram.com/coding/add-poster-girl-with-plugin.html"); 198 | } 199 | }; 200 | elements.skate.onmouseover = function () { 201 | const list = ["溜冰去咯", "随机挑战开启", "溜冰的意思不是让你咬咬牙溜十次八次,而是要上百次", "你想摸鱼???"] 202 | modules.render(list); 203 | }; 204 | current.menu.appendChild(elements.skate); 205 | 206 | 207 | // 音频测试 208 | elements.audio.onclick = function () { 209 | if (current.idol === 0) { 210 | window.live2d_playAction({ 211 | text: "嘉心糖屁都用没有", 212 | motion: "Tap生气 -领结" 213 | }) 214 | // 播放音频 215 | modules.audioPlay(`./models/Diana/audio/jiaxintang-nouse.aac`); 216 | } 217 | else { 218 | modules.render('晚晚的语音测试未添加'); 219 | } 220 | }; 221 | elements.audio.onmouseover = function () { 222 | modules.render("音频测试"); 223 | }; 224 | current.menu.appendChild(elements.audio); 225 | 226 | // 一个魂们的二创 227 | elements.fans.onclick = function () { 228 | window.open("https://asoulfanart.com/pic"); 229 | }; 230 | elements.fans.onmouseover = function () { 231 | modules.render("想看更多一个魂们的二创吗?"); 232 | }; 233 | current.menu.appendChild(elements.fans); 234 | 235 | // 关于我 236 | elements.info.onclick = function () { 237 | window.open("https://www.bilibili.com/video/BV1FZ4y1F7HH"); 238 | }; 239 | elements.info.onmouseover = function () { 240 | modules.render(["想了解更多关于我的信息吗?", "模型来源"]); 241 | }; 242 | current.menu.appendChild(elements.info); 243 | } 244 | }; 245 | 246 | /* - 运行 */ 247 | var begin = { 248 | static: function () { 249 | current.body.classList.add("static"); 250 | }, 251 | fixed: function () { 252 | action.touch(); action.buttons(); 253 | }, 254 | draggable: function () { 255 | action.touch(); action.buttons(); 256 | 257 | var body = current.body; 258 | body.onmousedown = function (downEvent) { 259 | var location = { 260 | x: downEvent.clientX - this.offsetLeft, 261 | y: downEvent.clientY - this.offsetTop 262 | }; 263 | 264 | function move(moveEvent) { 265 | body.classList.add("active"); 266 | body.classList.remove("right"); 267 | body.style.left = (moveEvent.clientX - location.x) + 'px'; 268 | body.style.top = (moveEvent.clientY - location.y) + 'px'; 269 | body.style.bottom = "auto"; 270 | } 271 | 272 | document.addEventListener("mousemove", move); 273 | document.addEventListener("mouseup", function () { 274 | body.classList.remove("active"); 275 | document.removeEventListener("mousemove", move); 276 | }); 277 | }; 278 | } 279 | }; 280 | 281 | // 运行 282 | this.init = function (onlyText) { 283 | if (!(prop.hidden && modules.isMobile())) { 284 | if (!onlyText) { 285 | action.welcome(); 286 | that.model = loadlive2d("pio", prop.model[current.idol], model => { 287 | prop.onModelLoad && prop.onModelLoad(model) 288 | }); 289 | } 290 | 291 | switch (prop.mode) { 292 | case "static": begin.static(); break; 293 | case "fixed": begin.fixed(); break; 294 | case "draggable": begin.draggable(); break; 295 | } 296 | 297 | } 298 | }; 299 | 300 | this.init(); 301 | }; 302 | 303 | // 请保留版权说明 304 | if (window.console && window.console.log) { 305 | console.log("%c Pio %c https://paugram.com ", "color: #fff; margin: 1em 0; padding: 5px 0; background: #673ab7;", "margin: 1em 0; padding: 5px 0; background: #efefef;"); 306 | } -------------------------------------------------------------------------------- /res/live2d/lib/pio/pio_sdk4.js: -------------------------------------------------------------------------------- 1 | /* ---- 2 | 3 | # Pio SDK 2/3/4 support 4 | # By: jupiterbjy 5 | # Modify: journey-ad 6 | # Last Update: 2021.5.4 7 | 8 | To use this, you need to include following sources to your HTML file first. 9 | With this script, you don't have to include `l2d.js`. Testing is done without it. 10 | Basic usage is same with Paul-Pio. 11 | 12 | Make sure to call `pio_refresh_style()` upon changing styles on anything related to 'pio-container' and it's children. 13 | 14 | To change alignment, modify variable `pio_alignment` to either `left` or `right`, then call `pio_refresh_style()`. 15 | 16 | 17 | 18 | 19 | 20 | 21 | If you have trouble setting up this, check following example's sources. 22 | https://jupiterbjy.github.io/PaulPio_PIXI_Demo/ 23 | 24 | ---- */ 25 | 26 | 27 | function loadlive2d(canvas_id, json_object_or_url, on_load) { 28 | // Replaces original l2d method 'loadlive2d' for Pio. 29 | // Heavily relies on pixi_live2d_display. 30 | 31 | console.log("[Pio] Loading new model") 32 | 33 | const canvas = document.getElementById(canvas_id) 34 | 35 | // When pio was start minimized on browser refresh or reload, 36 | // canvas is set to 0, 0 dimension and need to be changed. 37 | if (canvas.width === 0) { 38 | canvas.removeAttribute("height") 39 | pio_refresh_style() 40 | } 41 | 42 | // Try to remove previous model, if any exists. 43 | try { 44 | app.stage.removeChildAt(0) 45 | } catch (error) { 46 | 47 | } 48 | 49 | let model = PIXI.live2d.Live2DModel.fromSync(json_object_or_url) 50 | 51 | model.once("load", () => { 52 | app.stage.addChild(model) 53 | 54 | const vertical_factor = canvas.height / model.height 55 | model.scale.set(vertical_factor) 56 | 57 | // match canvas to model width 58 | canvas.width = model.width 59 | canvas.height = model.height 60 | pio_refresh_style() 61 | 62 | // check alignment, and align model to corner 63 | if (document.getElementsByClassName("pio-container").item(0).className.includes("left")){ 64 | model.x = 0 65 | } else { 66 | model.x = canvas.width - model.width 67 | } 68 | 69 | // Hit callback definition 70 | model.on("hit", hitAreas => { 71 | if (hitAreas.includes("body")) { 72 | console.log("[Pio] Touch on body (SDK2)") 73 | model.motion('tap_body') 74 | 75 | } else if (hitAreas.includes("Body")) { 76 | console.log("[Pio] Touch on body (SDK3/4)") 77 | model.motion("Tap") 78 | 79 | } else if (hitAreas.includes("head") || hitAreas.includes("Head")){ 80 | console.log("[Pio] Touch on head") 81 | model.expression() 82 | } 83 | }) 84 | 85 | on_load(model) 86 | }) 87 | 88 | return model 89 | } 90 | 91 | 92 | function _pio_initialize_container(){ 93 | 94 | // Generate structure 95 | let pio_container = document.createElement("div") 96 | pio_container.classList.add("pio-container") 97 | pio_container.id = "pio-container" 98 | document.body.insertAdjacentElement("beforeend", pio_container) 99 | 100 | // Generate action 101 | let pio_action = document.createElement("div") 102 | pio_action.classList.add("pio-action") 103 | pio_container.insertAdjacentElement("beforeend", pio_action) 104 | 105 | // Generate canvas 106 | let pio_canvas = document.createElement("canvas") 107 | pio_canvas.id = "pio" 108 | pio_container.insertAdjacentElement("beforeend", pio_canvas) 109 | 110 | console.log("[Pio] Initialized container.") 111 | } 112 | 113 | 114 | function pio_refresh_style(){ 115 | // Always make sure to call this after container/canvas style changes! 116 | // You can set alignment here, but still you can change it manually. 117 | 118 | let pio_container = document.getElementsByClassName("pio-container").item(0) 119 | 120 | pio_container.classList.remove("left", "right") 121 | pio_container.classList.add(pio_alignment) 122 | 123 | // app.resizeTo = document.getElementById("pio") 124 | } 125 | 126 | 127 | function _pio_initialize_pixi() { 128 | // Initialize html elements and pixi app. 129 | // Must run before pio init. 130 | 131 | _pio_initialize_container() 132 | 133 | app = new PIXI.Application({ 134 | view: document.getElementById("pio"), 135 | transparent: true, 136 | autoStart: true, 137 | }) 138 | 139 | pio_refresh_style() 140 | } 141 | 142 | 143 | // change alignment to left by modifying this value in other script. 144 | // Make sure to call `pio_refresh_style` to apply changes! 145 | let pio_alignment = "right" 146 | 147 | 148 | let app 149 | window.addEventListener("DOMContentLoaded", _pio_initialize_pixi) 150 | -------------------------------------------------------------------------------- /res/live2d/models/Ava/Ava.4096/texture_00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/models/Ava/Ava.4096/texture_00.png -------------------------------------------------------------------------------- /res/live2d/models/Ava/Ava.moc3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/models/Ava/Ava.moc3 -------------------------------------------------------------------------------- /res/live2d/models/Ava/Ava.model3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 3, 3 | "Bounds": { 4 | "Width": 9.772043, 5 | "Height": 11.08606, 6 | "CenterX": 0.1069689, 7 | "CenterY": -1.404058 8 | }, 9 | "FileReferences": { 10 | "Moc": "Ava.moc3", 11 | "Textures": [ 12 | "Ava.4096/texture_00.png" 13 | ], 14 | "Physics": "Ava.physics3.json", 15 | "PhysicsV2": { 16 | "File": "Ava.physics3.json" 17 | }, 18 | "Motions": { 19 | "Idle": [{ 20 | "Name": "待机", 21 | "File": "motions/Ava_idle.motion3.json" 22 | }], 23 | "Shake": [{ 24 | "Name": "晕", 25 | "File": "motions/Ava_shake01.motion3.json", 26 | "Text": "啊呜...", 27 | "TextDuration": 2000 28 | }, { 29 | "File": "motions/Ava_shake02.motion3.json" 30 | }], 31 | "Tap左手": [{ 32 | "Name": "吉他", 33 | "File": "motions/Ava_tap01.motion3.json", 34 | "Text": "可爱的鸽子鸽子~我喜欢你~", 35 | "TextDelay": 1200, 36 | "TextDuration": 5600 37 | }], 38 | "Tap右手": [{ 39 | "Name": "游戏", 40 | "File": "motions/Ava_tap02.motion3.json", 41 | "Text": "来陪我玩游戏!", 42 | "TextDelay": 600, 43 | "TextDuration": 2500 44 | }], 45 | "Tap腰": [{ 46 | "Name": "傲娇", 47 | "File": "motions/Ava_tap03.motion3.json", 48 | "Text": "哼,才不是傲娇大小姐", 49 | "TextDelay": 500, 50 | "TextDuration": 3000 51 | }], 52 | "Tap中间刘海": [{ 53 | "Name": "害羞", 54 | "File": "motions/Ava_tap04.motion3.json", 55 | "Text": "好...好兄弟之间喜欢很正常啦", 56 | "TextDelay": 1500, 57 | "TextDuration": 3000 58 | }, { 59 | "Name": "害羞2", 60 | "File": "motions/Ava_tap04.motion3.json", 61 | "Text": "也...也不是不可以", 62 | "TextDelay": 2000, 63 | "TextDuration": 3000 64 | }], 65 | "Tap嘴": [{ 66 | "Name": "傲娇", 67 | "File": "motions/Ava_tap03.motion3.json", 68 | "Text": "什么傲娇啦,我才没有", 69 | "TextDelay": 500, 70 | "TextDuration": 2200 71 | }], 72 | "Tap胸口项链": [{ 73 | "Name": "笑", 74 | "File": "motions/Ava_tap05.motion3.json" 75 | }], 76 | "Tap脖子": [{ 77 | "Name": "监督", 78 | "File": "motions/Ava_tap06.motion3.json", 79 | "Text": "嗯?老戳我干嘛,快去干正事啦 ", 80 | "TextDelay": 550, 81 | "TextDuration": 4000 82 | }], 83 | "Tap 右边头饰小花": [{ 84 | "Name": "懒羊羊", 85 | "File": "motions/Ava_tap07.motion3.json", 86 | "Text": "顶晚人...顶晚人在哪里...", 87 | "TextDelay": 800, 88 | "TextDuration": 6000 89 | }], 90 | "Tap右头饰": [{ 91 | "Name": "猫", 92 | "File": "motions/Ava_tap08.motion3.json", 93 | "Text": "neko panch!", 94 | "TextDelay": 500, 95 | "TextDuration": 2000 96 | }], 97 | "Tap右眼": [{ 98 | "Name": "惊讶", 99 | "File": "motions/Ava_tap09.motion3.json", 100 | "Text": "啊", 101 | "TextDelay": 200, 102 | "TextDuration": 1000 103 | }], 104 | "Tap左眼": [{ 105 | "Name": "墨镜", 106 | "File": "motions/Ava_tap10.motion3.json", 107 | "Text": "嗯哼~我超帅的", 108 | "TextDelay": 700, 109 | "TextDuration": 2000 110 | }], 111 | "Tap右马尾 ": [{ 112 | "Name": "水母", 113 | "File": "motions/Ava_tap11.motion3.json" 114 | }], 115 | "Tap左马尾": [{ 116 | "Name": "><", 117 | "File": "motions/Ava_shake02.motion3.json", 118 | "Text": "头发摸乱了啦~", 119 | "TextDelay": 500, 120 | "TextDuration": 2000 121 | }], 122 | "Tap右手臂": [{ 123 | "File": "motions/Ava_tap06.motion3.json", 124 | "Text": "嗯?老戳我干嘛,快去干正事啦 ", 125 | "TextDelay": 550, 126 | "TextDuration": 4000 127 | }], 128 | "Tap左中马尾": [{ 129 | "File": "motions/Ava_tap11.motion3.json" 130 | }] 131 | } 132 | }, 133 | "Controllers": { 134 | "ParamHit": {}, 135 | "ParamLoop": {}, 136 | "KeyTrigger": {}, 137 | "EyeBlink": { 138 | "MinInterval": 500, 139 | "MaxInterval": 6000, 140 | "Items": [{ 141 | "Id": "ParamEyeLOpen", 142 | "Min": 0.0, 143 | "Max": 1.0, 144 | "BlendMode": 2, 145 | "Input": 0 146 | }, { 147 | "Id": "ParamEyeROpen", 148 | "Min": 0.0, 149 | "Max": 1.0, 150 | "BlendMode": 2, 151 | "Input": 0 152 | }, { 153 | "Id": "Param7", 154 | "Min": 0.0, 155 | "Max": 1.0, 156 | "BlendMode": 2, 157 | "Input": 0 158 | }, { 159 | "Id": "Param8", 160 | "Min": 0.0, 161 | "Max": 1.0, 162 | "BlendMode": 2, 163 | "Input": 0 164 | }], 165 | "Enabled": true 166 | }, 167 | "LipSync": { 168 | "Gain": 5.0 169 | }, 170 | "MouseTracking": { 171 | "SmoothTime": 0.15, 172 | "Items": [{ 173 | "Id": "ParamAngleX", 174 | "Min": -30.0, 175 | "Max": 30.0, 176 | "DefaultValue": 0.0, 177 | "Weight": 0.359834284, 178 | "BlendMode": 1, 179 | "Input": 1 180 | }, { 181 | "Id": "ParamAngleY", 182 | "Min": -30.0, 183 | "Max": 30.0, 184 | "DefaultValue": 0.0, 185 | "Weight": 0.3398514, 186 | "BlendMode": 1, 187 | "Axis": 1, 188 | "Input": 2 189 | }, { 190 | "Id": "ParamAngleZ", 191 | "Min": -15.0, 192 | "Max": 15.0, 193 | "DefaultValue": 0.0, 194 | "Weight": 0.199971348, 195 | "BlendMode": 1, 196 | "Axis": 2, 197 | "Input": 1 198 | }, { 199 | "Id": "ParamBodyAngleX", 200 | "Min": -10.0, 201 | "Max": 10.0, 202 | "DefaultValue": 0.0, 203 | "Weight": 0.376962453, 204 | "BlendMode": 1, 205 | "Input": 1 206 | }, { 207 | "Id": "ParamBodyAngleZ", 208 | "Min": -10.0, 209 | "Max": 10.0, 210 | "DefaultValue": 0.0, 211 | "Weight": 0.365543664, 212 | "BlendMode": 1, 213 | "Axis": 2, 214 | "Input": 1 215 | }, { 216 | "Id": "Param46", 217 | "Min": -30.0, 218 | "Max": 30.0, 219 | "DefaultValue": 0.0, 220 | "Weight": 0.411218822, 221 | "BlendMode": 1, 222 | "Axis": 1, 223 | "Input": 2 224 | }, { 225 | "Id": "ParamEyeBallX", 226 | "Min": -1.0, 227 | "Max": 1.0, 228 | "DefaultValue": 0.0, 229 | "BlendMode": 1, 230 | "Input": 1 231 | }, { 232 | "Id": "ParamEyeBallY", 233 | "Min": -1.0, 234 | "Max": 1.0, 235 | "DefaultValue": 0.0, 236 | "BlendMode": 1, 237 | "Axis": 1, 238 | "Input": 2 239 | }], 240 | "Enabled": true 241 | }, 242 | "AutoBreath": { 243 | "Enabled": true 244 | }, 245 | "ExtraMotion": { 246 | "Enabled": true 247 | }, 248 | "Accelerometer": { 249 | "Enabled": true 250 | }, 251 | "Microphone": {}, 252 | "Transform": {}, 253 | "FaceTracking": { 254 | "Enabled": true 255 | }, 256 | "ParamValue": {}, 257 | "PartOpacity": { 258 | "Items": [{ 259 | "Name": "猫耳", 260 | "Ids": ["Part23", "weiba_Skinning"] 261 | }, { 262 | "Name": "墨镜", 263 | "Ids": ["Part26"] 264 | }], 265 | "Enabled": true 266 | }, 267 | "ArtmeshOpacity": {}, 268 | "ArtmeshColor": {}, 269 | "ArtmeshCulling": { 270 | "DefaultMode": 0 271 | }, 272 | "IntimacySystem": {} 273 | }, 274 | "HitAreas": [{ 275 | "Name": "左手", 276 | "Id": "ArtMesh2" 277 | }, { 278 | "Name": "右手", 279 | "Id": "ArtMesh87" 280 | }, { 281 | "Name": "腰", 282 | "Id": "yao" 283 | }, { 284 | "Name": "中间刘海", 285 | "Id": "ArtMesh26" 286 | }, { 287 | "Name": "嘴", 288 | "Id": "ArtMesh35" 289 | }, { 290 | "Name": "胸口项链", 291 | "Id": "ArtMesh45" 292 | }, { 293 | "Name": "脖子", 294 | "Id": "ArtMesh52" 295 | }, { 296 | "Name": " 右边头饰小花", 297 | "Id": "hua2" 298 | }, { 299 | "Name": "右头饰", 300 | "Id": "ArtMesh19" 301 | }, { 302 | "Name": "右眼", 303 | "Id": "qiu" 304 | }, { 305 | "Name": "左眼", 306 | "Id": "ArtMesh42" 307 | }, { 308 | "Name": "右马尾 ", 309 | "Id": "R8" 310 | }, { 311 | "Name": "左马尾", 312 | "Id": "L4" 313 | }, { 314 | "Name": "右手臂", 315 | "Id": "ArtMesh48" 316 | }, { 317 | "Name": "左中马尾", 318 | "Id": "L6" 319 | }], 320 | "Options": { 321 | "TexFixed": true 322 | } 323 | } -------------------------------------------------------------------------------- /res/live2d/models/Ava/motions/Ava_shake01.motion3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 3, 3 | "Meta": { 4 | "Duration": 3.6, 5 | "Fps": 30.0, 6 | "Loop": true, 7 | "AreBeziersRestricted": true, 8 | "CurveCount": 67, 9 | "TotalSegmentCount": 88, 10 | "TotalPointCount": 201, 11 | "UserDataCount": 0, 12 | "TotalUserDataSize": 0 13 | }, 14 | "Curves": [ 15 | { 16 | "Target": "Parameter", 17 | "Id": "ParamAngleX", 18 | "Segments": [ 19 | 0, 20 | 0, 21 | 1, 22 | 0.111, 23 | 0, 24 | 0.222, 25 | -1, 26 | 0.333, 27 | -1, 28 | 1, 29 | 0.444, 30 | -1, 31 | 0.556, 32 | 11, 33 | 0.667, 34 | 11, 35 | 1, 36 | 0.8, 37 | 11, 38 | 0.933, 39 | 5.553, 40 | 1.067, 41 | -1, 42 | 1, 43 | 1.222, 44 | -8.646, 45 | 1.378, 46 | -11, 47 | 1.533, 48 | -11, 49 | 1, 50 | 1.689, 51 | -11, 52 | 1.844, 53 | 2, 54 | 2, 55 | 2, 56 | 0, 57 | 3.6, 58 | 2 59 | ] 60 | }, 61 | { 62 | "Target": "Parameter", 63 | "Id": "ParamAngleY", 64 | "Segments": [ 65 | 0, 66 | -1, 67 | 1, 68 | 0.111, 69 | -1, 70 | 0.222, 71 | 9, 72 | 0.333, 73 | 9, 74 | 1, 75 | 0.444, 76 | 9, 77 | 0.556, 78 | 4.623, 79 | 0.667, 80 | -1, 81 | 1, 82 | 0.8, 83 | -7.747, 84 | 0.933, 85 | -10, 86 | 1.067, 87 | -10, 88 | 1, 89 | 1.222, 90 | -10, 91 | 1.378, 92 | -10.304, 93 | 1.533, 94 | -4, 95 | 1, 96 | 1.689, 97 | 2.304, 98 | 1.844, 99 | 30, 100 | 2, 101 | 30, 102 | 0, 103 | 3.6, 104 | 30 105 | ] 106 | }, 107 | { 108 | "Target": "Parameter", 109 | "Id": "ParamAngleZ", 110 | "Segments": [ 111 | 0, 112 | 0.101, 113 | 1, 114 | 0.211, 115 | 1.365, 116 | 0.422, 117 | 14, 118 | 0.633, 119 | 14, 120 | 1, 121 | 1.078, 122 | 14, 123 | 1.522, 124 | -15, 125 | 1.967, 126 | -15, 127 | 1, 128 | 2.511, 129 | -15, 130 | 3.056, 131 | 10, 132 | 3.6, 133 | 10 134 | ] 135 | }, 136 | { 137 | "Target": "Parameter", 138 | "Id": "ParamBodyAngleX", 139 | "Segments": [ 140 | 0, 141 | -2, 142 | 0, 143 | 3.6, 144 | -2 145 | ] 146 | }, 147 | { 148 | "Target": "Parameter", 149 | "Id": "ParamBodyAngleY", 150 | "Segments": [ 151 | 0, 152 | 0, 153 | 0, 154 | 3.6, 155 | 0 156 | ] 157 | }, 158 | { 159 | "Target": "Parameter", 160 | "Id": "ParamBodyAngleZ", 161 | "Segments": [ 162 | 0, 163 | 0, 164 | 1, 165 | 0.211, 166 | 0, 167 | 0.422, 168 | 10, 169 | 0.633, 170 | 10, 171 | 1, 172 | 1.078, 173 | 10, 174 | 1.522, 175 | -6, 176 | 1.967, 177 | -6, 178 | 1, 179 | 2.511, 180 | -6, 181 | 3.056, 182 | 2, 183 | 3.6, 184 | 2 185 | ] 186 | }, 187 | { 188 | "Target": "Parameter", 189 | "Id": "ParamCheek", 190 | "Segments": [ 191 | 0, 192 | 0, 193 | 0, 194 | 3.6, 195 | 0 196 | ] 197 | }, 198 | { 199 | "Target": "Parameter", 200 | "Id": "Param12", 201 | "Segments": [ 202 | 0, 203 | 0, 204 | 0, 205 | 3.6, 206 | 0 207 | ] 208 | }, 209 | { 210 | "Target": "Parameter", 211 | "Id": "ParamEyeLOpen", 212 | "Segments": [ 213 | 0, 214 | 1, 215 | 0, 216 | 3.6, 217 | 1 218 | ] 219 | }, 220 | { 221 | "Target": "Parameter", 222 | "Id": "ParamEyeLSmile", 223 | "Segments": [ 224 | 0, 225 | 0, 226 | 0, 227 | 3.6, 228 | 0 229 | ] 230 | }, 231 | { 232 | "Target": "Parameter", 233 | "Id": "ParamEyeROpen", 234 | "Segments": [ 235 | 0, 236 | 1, 237 | 0, 238 | 3.6, 239 | 1 240 | ] 241 | }, 242 | { 243 | "Target": "Parameter", 244 | "Id": "ParamEyeRSmile", 245 | "Segments": [ 246 | 0, 247 | 0, 248 | 0, 249 | 3.6, 250 | 0 251 | ] 252 | }, 253 | { 254 | "Target": "Parameter", 255 | "Id": "ParamEyeBallX", 256 | "Segments": [ 257 | 0, 258 | 0, 259 | 0, 260 | 3.6, 261 | 0 262 | ] 263 | }, 264 | { 265 | "Target": "Parameter", 266 | "Id": "ParamEyeBallY", 267 | "Segments": [ 268 | 0, 269 | 0, 270 | 0, 271 | 3.6, 272 | 0 273 | ] 274 | }, 275 | { 276 | "Target": "Parameter", 277 | "Id": "ParamBrowLX", 278 | "Segments": [ 279 | 0, 280 | 0, 281 | 0, 282 | 3.6, 283 | 0 284 | ] 285 | }, 286 | { 287 | "Target": "Parameter", 288 | "Id": "ParamBrowLY", 289 | "Segments": [ 290 | 0, 291 | 0, 292 | 0, 293 | 3.6, 294 | 0 295 | ] 296 | }, 297 | { 298 | "Target": "Parameter", 299 | "Id": "ParamBrowRX", 300 | "Segments": [ 301 | 0, 302 | 0, 303 | 0, 304 | 3.6, 305 | 0 306 | ] 307 | }, 308 | { 309 | "Target": "Parameter", 310 | "Id": "ParamBrowRY", 311 | "Segments": [ 312 | 0, 313 | 0, 314 | 0, 315 | 3.6, 316 | 0 317 | ] 318 | }, 319 | { 320 | "Target": "Parameter", 321 | "Id": "ParamBrowLAngle", 322 | "Segments": [ 323 | 0, 324 | -0.3, 325 | 0, 326 | 3.6, 327 | -0.3 328 | ] 329 | }, 330 | { 331 | "Target": "Parameter", 332 | "Id": "ParamBrowRAngle", 333 | "Segments": [ 334 | 0, 335 | -0.3, 336 | 0, 337 | 3.6, 338 | -0.3 339 | ] 340 | }, 341 | { 342 | "Target": "Parameter", 343 | "Id": "ParamBrowRForm", 344 | "Segments": [ 345 | 0, 346 | 0, 347 | 1, 348 | 0.067, 349 | 0, 350 | 0.133, 351 | -0.2, 352 | 0.2, 353 | -0.2, 354 | 0, 355 | 3.6, 356 | -0.2 357 | ] 358 | }, 359 | { 360 | "Target": "Parameter", 361 | "Id": "ParamBrowLForm", 362 | "Segments": [ 363 | 0, 364 | 0, 365 | 1, 366 | 0.067, 367 | 0, 368 | 0.133, 369 | -0.2, 370 | 0.2, 371 | -0.2, 372 | 0, 373 | 3.6, 374 | -0.2 375 | ] 376 | }, 377 | { 378 | "Target": "Parameter", 379 | "Id": "ParamMouthForm", 380 | "Segments": [ 381 | 0, 382 | -0.8, 383 | 1, 384 | 0.067, 385 | -0.8, 386 | 0.133, 387 | -1, 388 | 0.2, 389 | -1, 390 | 0, 391 | 3.6, 392 | -1 393 | ] 394 | }, 395 | { 396 | "Target": "Parameter", 397 | "Id": "ParamMouthOpenY", 398 | "Segments": [ 399 | 0, 400 | 0, 401 | 1, 402 | 0.067, 403 | 0, 404 | 0.133, 405 | 0.9, 406 | 0.2, 407 | 0.9, 408 | 0, 409 | 3.6, 410 | 0.9 411 | ] 412 | }, 413 | { 414 | "Target": "Parameter", 415 | "Id": "Param26", 416 | "Segments": [ 417 | 0, 418 | 0, 419 | 0, 420 | 3.6, 421 | 0 422 | ] 423 | }, 424 | { 425 | "Target": "Parameter", 426 | "Id": "Param27", 427 | "Segments": [ 428 | 0, 429 | 0, 430 | 0, 431 | 3.6, 432 | 0 433 | ] 434 | }, 435 | { 436 | "Target": "Parameter", 437 | "Id": "Param28", 438 | "Segments": [ 439 | 0, 440 | 0, 441 | 0, 442 | 3.6, 443 | 0 444 | ] 445 | }, 446 | { 447 | "Target": "Parameter", 448 | "Id": "Param29", 449 | "Segments": [ 450 | 0, 451 | 0, 452 | 0, 453 | 3.6, 454 | 0 455 | ] 456 | }, 457 | { 458 | "Target": "Parameter", 459 | "Id": "Param15", 460 | "Segments": [ 461 | 0, 462 | -30, 463 | 0, 464 | 0.033, 465 | -30, 466 | 1, 467 | 0.433, 468 | -30, 469 | 0.833, 470 | 30, 471 | 1.233, 472 | 30, 473 | 1, 474 | 1.678, 475 | 30, 476 | 2.122, 477 | -30, 478 | 2.567, 479 | -30, 480 | 1, 481 | 2.911, 482 | -30, 483 | 3.256, 484 | -0.217, 485 | 3.6, 486 | 17.382 487 | ] 488 | }, 489 | { 490 | "Target": "PartOpacity", 491 | "Id": "Part23", 492 | "Segments": [ 493 | 0, 494 | 0, 495 | 0, 496 | 3.6, 497 | 0 498 | ] 499 | }, 500 | { 501 | "Target": "PartOpacity", 502 | "Id": "weiba_Skinning", 503 | "Segments": [ 504 | 0, 505 | 0, 506 | 0, 507 | 3.6, 508 | 0 509 | ] 510 | }, 511 | { 512 | "Target": "PartOpacity", 513 | "Id": "neko", 514 | "Segments": [ 515 | 0, 516 | 0, 517 | 0, 518 | 3.6, 519 | 0 520 | ] 521 | }, 522 | { 523 | "Target": "PartOpacity", 524 | "Id": "game", 525 | "Segments": [ 526 | 0, 527 | 0, 528 | 0, 529 | 3.6, 530 | 0 531 | ] 532 | }, 533 | { 534 | "Target": "PartOpacity", 535 | "Id": "gitar", 536 | "Segments": [ 537 | 0, 538 | 0, 539 | 0, 540 | 3.6, 541 | 0 542 | ] 543 | }, 544 | { 545 | "Target": "PartOpacity", 546 | "Id": "Part26", 547 | "Segments": [ 548 | 0, 549 | 0, 550 | 0, 551 | 3.6, 552 | 0 553 | ] 554 | }, 555 | { 556 | "Target": "PartOpacity", 557 | "Id": "Part15", 558 | "Segments": [ 559 | 0, 560 | 1, 561 | 0, 562 | 3.6, 563 | 1 564 | ] 565 | }, 566 | { 567 | "Target": "PartOpacity", 568 | "Id": "Part6", 569 | "Segments": [ 570 | 0, 571 | 1, 572 | 0, 573 | 3.6, 574 | 1 575 | ] 576 | }, 577 | { 578 | "Target": "PartOpacity", 579 | "Id": "Part", 580 | "Segments": [ 581 | 0, 582 | 0, 583 | 0, 584 | 3.6, 585 | 0 586 | ] 587 | }, 588 | { 589 | "Target": "PartOpacity", 590 | "Id": "things", 591 | "Segments": [ 592 | 0, 593 | 0, 594 | 0, 595 | 3.6, 596 | 0 597 | ] 598 | }, 599 | { 600 | "Target": "PartOpacity", 601 | "Id": "Part11", 602 | "Segments": [ 603 | 0, 604 | 0, 605 | 0, 606 | 3.6, 607 | 0 608 | ] 609 | }, 610 | { 611 | "Target": "PartOpacity", 612 | "Id": "Part12", 613 | "Segments": [ 614 | 0, 615 | 0, 616 | 0, 617 | 3.6, 618 | 0 619 | ] 620 | }, 621 | { 622 | "Target": "PartOpacity", 623 | "Id": "Part13", 624 | "Segments": [ 625 | 0, 626 | 0, 627 | 0, 628 | 3.6, 629 | 0 630 | ] 631 | }, 632 | { 633 | "Target": "PartOpacity", 634 | "Id": "Part14", 635 | "Segments": [ 636 | 0, 637 | 0, 638 | 0, 639 | 3.6, 640 | 0 641 | ] 642 | }, 643 | { 644 | "Target": "PartOpacity", 645 | "Id": "Part16", 646 | "Segments": [ 647 | 0, 648 | 0, 649 | 0, 650 | 3.6, 651 | 0 652 | ] 653 | }, 654 | { 655 | "Target": "PartOpacity", 656 | "Id": "Part2", 657 | "Segments": [ 658 | 0, 659 | 1, 660 | 0, 661 | 3.6, 662 | 1 663 | ] 664 | }, 665 | { 666 | "Target": "PartOpacity", 667 | "Id": "Part3", 668 | "Segments": [ 669 | 0, 670 | 1, 671 | 0, 672 | 3.6, 673 | 1 674 | ] 675 | }, 676 | { 677 | "Target": "PartOpacity", 678 | "Id": "hair", 679 | "Segments": [ 680 | 0, 681 | 1, 682 | 0, 683 | 3.6, 684 | 1 685 | ] 686 | }, 687 | { 688 | "Target": "PartOpacity", 689 | "Id": "eyebrows", 690 | "Segments": [ 691 | 0, 692 | 1, 693 | 0, 694 | 3.6, 695 | 1 696 | ] 697 | }, 698 | { 699 | "Target": "PartOpacity", 700 | "Id": "Part4", 701 | "Segments": [ 702 | 0, 703 | 0, 704 | 0, 705 | 3.6, 706 | 0 707 | ] 708 | }, 709 | { 710 | "Target": "PartOpacity", 711 | "Id": "mouth", 712 | "Segments": [ 713 | 0, 714 | 1, 715 | 0, 716 | 3.6, 717 | 1 718 | ] 719 | }, 720 | { 721 | "Target": "PartOpacity", 722 | "Id": "Part5", 723 | "Segments": [ 724 | 0, 725 | 1, 726 | 0, 727 | 3.6, 728 | 1 729 | ] 730 | }, 731 | { 732 | "Target": "PartOpacity", 733 | "Id": "Part20", 734 | "Segments": [ 735 | 0, 736 | 0, 737 | 0, 738 | 3.6, 739 | 0 740 | ] 741 | }, 742 | { 743 | "Target": "PartOpacity", 744 | "Id": "Part19", 745 | "Segments": [ 746 | 0, 747 | 0, 748 | 0, 749 | 3.6, 750 | 0 751 | ] 752 | }, 753 | { 754 | "Target": "PartOpacity", 755 | "Id": "Part18", 756 | "Segments": [ 757 | 0, 758 | 1, 759 | 0, 760 | 3.6, 761 | 1 762 | ] 763 | }, 764 | { 765 | "Target": "PartOpacity", 766 | "Id": "Part17", 767 | "Segments": [ 768 | 0, 769 | 0, 770 | 0, 771 | 3.6, 772 | 0 773 | ] 774 | }, 775 | { 776 | "Target": "PartOpacity", 777 | "Id": "Part7", 778 | "Segments": [ 779 | 0, 780 | 0, 781 | 0, 782 | 3.6, 783 | 0 784 | ] 785 | }, 786 | { 787 | "Target": "PartOpacity", 788 | "Id": "Leye", 789 | "Segments": [ 790 | 0, 791 | 0, 792 | 0, 793 | 3.6, 794 | 0 795 | ] 796 | }, 797 | { 798 | "Target": "PartOpacity", 799 | "Id": "face", 800 | "Segments": [ 801 | 0, 802 | 1, 803 | 0, 804 | 3.6, 805 | 1 806 | ] 807 | }, 808 | { 809 | "Target": "PartOpacity", 810 | "Id": "Part8", 811 | "Segments": [ 812 | 0, 813 | 1, 814 | 0, 815 | 3.6, 816 | 1 817 | ] 818 | }, 819 | { 820 | "Target": "PartOpacity", 821 | "Id": "body", 822 | "Segments": [ 823 | 0, 824 | 1, 825 | 0, 826 | 3.6, 827 | 1 828 | ] 829 | }, 830 | { 831 | "Target": "PartOpacity", 832 | "Id": "Part25", 833 | "Segments": [ 834 | 0, 835 | 1, 836 | 0, 837 | 3.6, 838 | 1 839 | ] 840 | }, 841 | { 842 | "Target": "PartOpacity", 843 | "Id": "Part24", 844 | "Segments": [ 845 | 0, 846 | 1, 847 | 0, 848 | 3.6, 849 | 1 850 | ] 851 | }, 852 | { 853 | "Target": "PartOpacity", 854 | "Id": "Part22", 855 | "Segments": [ 856 | 0, 857 | 1, 858 | 0, 859 | 3.6, 860 | 1 861 | ] 862 | }, 863 | { 864 | "Target": "PartOpacity", 865 | "Id": "Part21", 866 | "Segments": [ 867 | 0, 868 | 1, 869 | 0, 870 | 3.6, 871 | 1 872 | ] 873 | }, 874 | { 875 | "Target": "PartOpacity", 876 | "Id": "Part9", 877 | "Segments": [ 878 | 0, 879 | 1, 880 | 0, 881 | 3.6, 882 | 1 883 | ] 884 | }, 885 | { 886 | "Target": "PartOpacity", 887 | "Id": "Part10", 888 | "Segments": [ 889 | 0, 890 | 1, 891 | 0, 892 | 3.6, 893 | 1 894 | ] 895 | }, 896 | { 897 | "Target": "PartOpacity", 898 | "Id": "PartSketch0", 899 | "Segments": [ 900 | 0, 901 | 1, 902 | 0, 903 | 3.6, 904 | 1 905 | ] 906 | } 907 | ] 908 | } -------------------------------------------------------------------------------- /res/live2d/models/Ava/motions/Ava_tap09.motion3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 3, 3 | "Meta": { 4 | "Duration": 2.4, 5 | "Fps": 30.0, 6 | "Loop": true, 7 | "AreBeziersRestricted": true, 8 | "CurveCount": 68, 9 | "TotalSegmentCount": 89, 10 | "TotalPointCount": 191, 11 | "UserDataCount": 0, 12 | "TotalUserDataSize": 0 13 | }, 14 | "Curves": [ 15 | { 16 | "Target": "Parameter", 17 | "Id": "ParamAngleX", 18 | "Segments": [ 19 | 0, 20 | 0, 21 | 1, 22 | 0.144, 23 | 0, 24 | 0.289, 25 | 1, 26 | 0.433, 27 | 1, 28 | 0, 29 | 2.4, 30 | 1 31 | ] 32 | }, 33 | { 34 | "Target": "Parameter", 35 | "Id": "ParamAngleY", 36 | "Segments": [ 37 | 0, 38 | -1, 39 | 1, 40 | 0.144, 41 | -1, 42 | 0.289, 43 | 20, 44 | 0.433, 45 | 20, 46 | 0, 47 | 2.4, 48 | 20 49 | ] 50 | }, 51 | { 52 | "Target": "Parameter", 53 | "Id": "ParamAngleZ", 54 | "Segments": [ 55 | 0, 56 | 0, 57 | 0, 58 | 2.4, 59 | 0 60 | ] 61 | }, 62 | { 63 | "Target": "Parameter", 64 | "Id": "ParamBodyAngleX", 65 | "Segments": [ 66 | 0, 67 | 0, 68 | 0, 69 | 2.4, 70 | 0 71 | ] 72 | }, 73 | { 74 | "Target": "Parameter", 75 | "Id": "ParamBodyAngleY", 76 | "Segments": [ 77 | 0, 78 | 0, 79 | 1, 80 | 0.144, 81 | 0, 82 | 0.289, 83 | 10, 84 | 0.433, 85 | 10, 86 | 0, 87 | 2.4, 88 | 10 89 | ] 90 | }, 91 | { 92 | "Target": "Parameter", 93 | "Id": "ParamBodyAngleZ", 94 | "Segments": [ 95 | 0, 96 | 0, 97 | 0, 98 | 2.4, 99 | 0 100 | ] 101 | }, 102 | { 103 | "Target": "Parameter", 104 | "Id": "ParamCheek", 105 | "Segments": [ 106 | 0, 107 | 0, 108 | 0, 109 | 2.4, 110 | 0 111 | ] 112 | }, 113 | { 114 | "Target": "Parameter", 115 | "Id": "Param12", 116 | "Segments": [ 117 | 0, 118 | 0, 119 | 0, 120 | 2.4, 121 | 0 122 | ] 123 | }, 124 | { 125 | "Target": "Parameter", 126 | "Id": "ParamEyeLOpen", 127 | "Segments": [ 128 | 0, 129 | 0.944, 130 | 1, 131 | 0.144, 132 | 0.971, 133 | 0.289, 134 | 1, 135 | 0.433, 136 | 1, 137 | 1, 138 | 0.7, 139 | 1, 140 | 0.967, 141 | 1, 142 | 1.233, 143 | 1, 144 | 1, 145 | 1.278, 146 | 1, 147 | 1.322, 148 | 0, 149 | 1.367, 150 | 0, 151 | 1, 152 | 1.411, 153 | 0, 154 | 1.456, 155 | 1, 156 | 1.5, 157 | 1, 158 | 0, 159 | 2.4, 160 | 1 161 | ] 162 | }, 163 | { 164 | "Target": "Parameter", 165 | "Id": "ParamEyeLSmile", 166 | "Segments": [ 167 | 0, 168 | 0, 169 | 0, 170 | 2.4, 171 | 0 172 | ] 173 | }, 174 | { 175 | "Target": "Parameter", 176 | "Id": "ParamEyeROpen", 177 | "Segments": [ 178 | 0, 179 | 0.944, 180 | 1, 181 | 0.144, 182 | 0.971, 183 | 0.289, 184 | 1, 185 | 0.433, 186 | 1, 187 | 1, 188 | 0.7, 189 | 1, 190 | 0.967, 191 | 1, 192 | 1.233, 193 | 1, 194 | 1, 195 | 1.278, 196 | 1, 197 | 1.322, 198 | 0, 199 | 1.367, 200 | 0, 201 | 1, 202 | 1.411, 203 | 0, 204 | 1.456, 205 | 1, 206 | 1.5, 207 | 1, 208 | 0, 209 | 2.4, 210 | 1 211 | ] 212 | }, 213 | { 214 | "Target": "Parameter", 215 | "Id": "ParamEyeRSmile", 216 | "Segments": [ 217 | 0, 218 | 0, 219 | 0, 220 | 2.4, 221 | 0 222 | ] 223 | }, 224 | { 225 | "Target": "Parameter", 226 | "Id": "ParamEyeBallX", 227 | "Segments": [ 228 | 0, 229 | 0, 230 | 0, 231 | 2.4, 232 | 0 233 | ] 234 | }, 235 | { 236 | "Target": "Parameter", 237 | "Id": "ParamEyeBallY", 238 | "Segments": [ 239 | 0, 240 | 0, 241 | 0, 242 | 2.4, 243 | 0 244 | ] 245 | }, 246 | { 247 | "Target": "Parameter", 248 | "Id": "ParamBrowLX", 249 | "Segments": [ 250 | 0, 251 | 0, 252 | 0, 253 | 2.4, 254 | 0 255 | ] 256 | }, 257 | { 258 | "Target": "Parameter", 259 | "Id": "ParamBrowLY", 260 | "Segments": [ 261 | 0, 262 | 0, 263 | 1, 264 | 0.156, 265 | 0, 266 | 0.311, 267 | 0.5, 268 | 0.467, 269 | 0.5, 270 | 0, 271 | 2.4, 272 | 0.5 273 | ] 274 | }, 275 | { 276 | "Target": "Parameter", 277 | "Id": "ParamBrowRX", 278 | "Segments": [ 279 | 0, 280 | 0, 281 | 0, 282 | 2.4, 283 | 0 284 | ] 285 | }, 286 | { 287 | "Target": "Parameter", 288 | "Id": "ParamBrowRY", 289 | "Segments": [ 290 | 0, 291 | 0, 292 | 1, 293 | 0.156, 294 | 0, 295 | 0.311, 296 | 0.5, 297 | 0.467, 298 | 0.5, 299 | 0, 300 | 2.4, 301 | 0.5 302 | ] 303 | }, 304 | { 305 | "Target": "Parameter", 306 | "Id": "ParamBrowLAngle", 307 | "Segments": [ 308 | 0, 309 | -0.3, 310 | 0, 311 | 2.4, 312 | -0.3 313 | ] 314 | }, 315 | { 316 | "Target": "Parameter", 317 | "Id": "ParamBrowRAngle", 318 | "Segments": [ 319 | 0, 320 | -0.3, 321 | 0, 322 | 2.4, 323 | -0.3 324 | ] 325 | }, 326 | { 327 | "Target": "Parameter", 328 | "Id": "ParamBrowRForm", 329 | "Segments": [ 330 | 0, 331 | 0, 332 | 0, 333 | 2.4, 334 | 0 335 | ] 336 | }, 337 | { 338 | "Target": "Parameter", 339 | "Id": "ParamBrowLForm", 340 | "Segments": [ 341 | 0, 342 | 0, 343 | 0, 344 | 2.4, 345 | 0 346 | ] 347 | }, 348 | { 349 | "Target": "Parameter", 350 | "Id": "ParamMouthForm", 351 | "Segments": [ 352 | 0, 353 | -0.8, 354 | 1, 355 | 0.144, 356 | -0.8, 357 | 0.289, 358 | -0.5, 359 | 0.433, 360 | -0.5, 361 | 0, 362 | 2.4, 363 | -0.5 364 | ] 365 | }, 366 | { 367 | "Target": "Parameter", 368 | "Id": "ParamMouthOpenY", 369 | "Segments": [ 370 | 0, 371 | 0, 372 | 1, 373 | 0.144, 374 | 0, 375 | 0.289, 376 | 0.6, 377 | 0.433, 378 | 0.6, 379 | 0, 380 | 2.4, 381 | 0.6 382 | ] 383 | }, 384 | { 385 | "Target": "Parameter", 386 | "Id": "Param26", 387 | "Segments": [ 388 | 0, 389 | 0, 390 | 0, 391 | 2.4, 392 | 0 393 | ] 394 | }, 395 | { 396 | "Target": "Parameter", 397 | "Id": "Param27", 398 | "Segments": [ 399 | 0, 400 | 0, 401 | 0, 402 | 2.4, 403 | 0 404 | ] 405 | }, 406 | { 407 | "Target": "Parameter", 408 | "Id": "Param28", 409 | "Segments": [ 410 | 0, 411 | 0, 412 | 0, 413 | 2.4, 414 | 0 415 | ] 416 | }, 417 | { 418 | "Target": "Parameter", 419 | "Id": "Param29", 420 | "Segments": [ 421 | 0, 422 | 0, 423 | 0, 424 | 2.4, 425 | 0 426 | ] 427 | }, 428 | { 429 | "Target": "Parameter", 430 | "Id": "Param24", 431 | "Segments": [ 432 | 0, 433 | 30, 434 | 1, 435 | 0.089, 436 | 30, 437 | 0.178, 438 | -8, 439 | 0.267, 440 | -8, 441 | 0, 442 | 2.4, 443 | -8 444 | ] 445 | }, 446 | { 447 | "Target": "Parameter", 448 | "Id": "Param17", 449 | "Segments": [ 450 | 0, 451 | -22, 452 | 0, 453 | 0.267, 454 | -22, 455 | 1, 456 | 0.3, 457 | -22, 458 | 0.333, 459 | 30, 460 | 0.367, 461 | 30, 462 | 0, 463 | 2.4, 464 | 30 465 | ] 466 | }, 467 | { 468 | "Target": "PartOpacity", 469 | "Id": "Part23", 470 | "Segments": [ 471 | 0, 472 | 0, 473 | 0, 474 | 2.4, 475 | 0 476 | ] 477 | }, 478 | { 479 | "Target": "PartOpacity", 480 | "Id": "weiba_Skinning", 481 | "Segments": [ 482 | 0, 483 | 0, 484 | 0, 485 | 2.4, 486 | 0 487 | ] 488 | }, 489 | { 490 | "Target": "PartOpacity", 491 | "Id": "neko", 492 | "Segments": [ 493 | 0, 494 | 0, 495 | 0, 496 | 2.4, 497 | 0 498 | ] 499 | }, 500 | { 501 | "Target": "PartOpacity", 502 | "Id": "game", 503 | "Segments": [ 504 | 0, 505 | 0, 506 | 0, 507 | 2.4, 508 | 0 509 | ] 510 | }, 511 | { 512 | "Target": "PartOpacity", 513 | "Id": "gitar", 514 | "Segments": [ 515 | 0, 516 | 0, 517 | 0, 518 | 2.4, 519 | 0 520 | ] 521 | }, 522 | { 523 | "Target": "PartOpacity", 524 | "Id": "Part26", 525 | "Segments": [ 526 | 0, 527 | 0, 528 | 0, 529 | 2.4, 530 | 0 531 | ] 532 | }, 533 | { 534 | "Target": "PartOpacity", 535 | "Id": "Part15", 536 | "Segments": [ 537 | 0, 538 | 1, 539 | 0, 540 | 2.4, 541 | 1 542 | ] 543 | }, 544 | { 545 | "Target": "PartOpacity", 546 | "Id": "Part6", 547 | "Segments": [ 548 | 0, 549 | 1, 550 | 0, 551 | 2.4, 552 | 1 553 | ] 554 | }, 555 | { 556 | "Target": "PartOpacity", 557 | "Id": "Part", 558 | "Segments": [ 559 | 0, 560 | 0, 561 | 0, 562 | 2.4, 563 | 0 564 | ] 565 | }, 566 | { 567 | "Target": "PartOpacity", 568 | "Id": "things", 569 | "Segments": [ 570 | 0, 571 | 0, 572 | 2, 573 | 0.3, 574 | 1, 575 | 0, 576 | 2.4, 577 | 1 578 | ] 579 | }, 580 | { 581 | "Target": "PartOpacity", 582 | "Id": "Part11", 583 | "Segments": [ 584 | 0, 585 | 0, 586 | 0, 587 | 2.4, 588 | 0 589 | ] 590 | }, 591 | { 592 | "Target": "PartOpacity", 593 | "Id": "Part12", 594 | "Segments": [ 595 | 0, 596 | 0, 597 | 0, 598 | 2.4, 599 | 0 600 | ] 601 | }, 602 | { 603 | "Target": "PartOpacity", 604 | "Id": "Part13", 605 | "Segments": [ 606 | 0, 607 | 0, 608 | 0, 609 | 2.4, 610 | 0 611 | ] 612 | }, 613 | { 614 | "Target": "PartOpacity", 615 | "Id": "Part14", 616 | "Segments": [ 617 | 0, 618 | 0, 619 | 2, 620 | 0.3, 621 | 0, 622 | 0, 623 | 2.4, 624 | 0 625 | ] 626 | }, 627 | { 628 | "Target": "PartOpacity", 629 | "Id": "Part16", 630 | "Segments": [ 631 | 0, 632 | 0, 633 | 2, 634 | 0.3, 635 | 1, 636 | 0, 637 | 2.4, 638 | 1 639 | ] 640 | }, 641 | { 642 | "Target": "PartOpacity", 643 | "Id": "Part2", 644 | "Segments": [ 645 | 0, 646 | 1, 647 | 0, 648 | 2.4, 649 | 1 650 | ] 651 | }, 652 | { 653 | "Target": "PartOpacity", 654 | "Id": "Part3", 655 | "Segments": [ 656 | 0, 657 | 1, 658 | 0, 659 | 2.4, 660 | 1 661 | ] 662 | }, 663 | { 664 | "Target": "PartOpacity", 665 | "Id": "hair", 666 | "Segments": [ 667 | 0, 668 | 1, 669 | 0, 670 | 2.4, 671 | 1 672 | ] 673 | }, 674 | { 675 | "Target": "PartOpacity", 676 | "Id": "eyebrows", 677 | "Segments": [ 678 | 0, 679 | 1, 680 | 0, 681 | 2.4, 682 | 1 683 | ] 684 | }, 685 | { 686 | "Target": "PartOpacity", 687 | "Id": "Part4", 688 | "Segments": [ 689 | 0, 690 | 0, 691 | 0, 692 | 2.4, 693 | 0 694 | ] 695 | }, 696 | { 697 | "Target": "PartOpacity", 698 | "Id": "mouth", 699 | "Segments": [ 700 | 0, 701 | 1, 702 | 0, 703 | 2.4, 704 | 1 705 | ] 706 | }, 707 | { 708 | "Target": "PartOpacity", 709 | "Id": "Part5", 710 | "Segments": [ 711 | 0, 712 | 0, 713 | 0, 714 | 2.4, 715 | 0 716 | ] 717 | }, 718 | { 719 | "Target": "PartOpacity", 720 | "Id": "Part20", 721 | "Segments": [ 722 | 0, 723 | 0, 724 | 0, 725 | 2.4, 726 | 0 727 | ] 728 | }, 729 | { 730 | "Target": "PartOpacity", 731 | "Id": "Part19", 732 | "Segments": [ 733 | 0, 734 | 0, 735 | 0, 736 | 2.4, 737 | 0 738 | ] 739 | }, 740 | { 741 | "Target": "PartOpacity", 742 | "Id": "Part18", 743 | "Segments": [ 744 | 0, 745 | 0, 746 | 0, 747 | 2.4, 748 | 0 749 | ] 750 | }, 751 | { 752 | "Target": "PartOpacity", 753 | "Id": "Part17", 754 | "Segments": [ 755 | 0, 756 | 0, 757 | 0, 758 | 2.4, 759 | 0 760 | ] 761 | }, 762 | { 763 | "Target": "PartOpacity", 764 | "Id": "Part7", 765 | "Segments": [ 766 | 0, 767 | 1, 768 | 0, 769 | 2.4, 770 | 1 771 | ] 772 | }, 773 | { 774 | "Target": "PartOpacity", 775 | "Id": "Leye", 776 | "Segments": [ 777 | 0, 778 | 1, 779 | 0, 780 | 2.4, 781 | 1 782 | ] 783 | }, 784 | { 785 | "Target": "PartOpacity", 786 | "Id": "face", 787 | "Segments": [ 788 | 0, 789 | 1, 790 | 0, 791 | 2.4, 792 | 1 793 | ] 794 | }, 795 | { 796 | "Target": "PartOpacity", 797 | "Id": "Part8", 798 | "Segments": [ 799 | 0, 800 | 1, 801 | 0, 802 | 2.4, 803 | 1 804 | ] 805 | }, 806 | { 807 | "Target": "PartOpacity", 808 | "Id": "body", 809 | "Segments": [ 810 | 0, 811 | 1, 812 | 0, 813 | 2.4, 814 | 1 815 | ] 816 | }, 817 | { 818 | "Target": "PartOpacity", 819 | "Id": "Part25", 820 | "Segments": [ 821 | 0, 822 | 1, 823 | 0, 824 | 2.4, 825 | 1 826 | ] 827 | }, 828 | { 829 | "Target": "PartOpacity", 830 | "Id": "Part24", 831 | "Segments": [ 832 | 0, 833 | 1, 834 | 0, 835 | 2.4, 836 | 1 837 | ] 838 | }, 839 | { 840 | "Target": "PartOpacity", 841 | "Id": "Part22", 842 | "Segments": [ 843 | 0, 844 | 1, 845 | 0, 846 | 2.4, 847 | 1 848 | ] 849 | }, 850 | { 851 | "Target": "PartOpacity", 852 | "Id": "Part21", 853 | "Segments": [ 854 | 0, 855 | 1, 856 | 0, 857 | 2.4, 858 | 1 859 | ] 860 | }, 861 | { 862 | "Target": "PartOpacity", 863 | "Id": "Part9", 864 | "Segments": [ 865 | 0, 866 | 1, 867 | 0, 868 | 2.4, 869 | 1 870 | ] 871 | }, 872 | { 873 | "Target": "PartOpacity", 874 | "Id": "Part10", 875 | "Segments": [ 876 | 0, 877 | 1, 878 | 0, 879 | 2.4, 880 | 1 881 | ] 882 | }, 883 | { 884 | "Target": "PartOpacity", 885 | "Id": "PartSketch0", 886 | "Segments": [ 887 | 0, 888 | 1, 889 | 0, 890 | 2.4, 891 | 1 892 | ] 893 | } 894 | ] 895 | } -------------------------------------------------------------------------------- /res/live2d/models/Ava/raw.ex.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "STM_1_0", 3 | "name": "向晚BY木果", 4 | "id": "1620044467713", 5 | "encrypt": "true", 6 | "version": "1.0", 7 | "list": [{ 8 | "id": "", 9 | "character": "character", 10 | "avatar": "4a301072dec6b6a49050e5b294cd7983", 11 | "costume": [{ 12 | "name": "costume", 13 | "path": "f01cf984f3e6783ccc8e88e0c8aff5cc.bin3" 14 | }] 15 | }] 16 | } -------------------------------------------------------------------------------- /res/live2d/models/Ava/raw.model3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 3, 3 | "Bounds": { 4 | "Width": 9.772043, 5 | "Height": 11.08606, 6 | "CenterX": 0.1069689, 7 | "CenterY": -1.404058 8 | }, 9 | "FileReferences": { 10 | "Moc": "d5586be2b6f3c2d44034440a93f66115.bin3", 11 | "Textures": ["b0078e0cbfe20363c423f01873780c94.bin3"], 12 | "Physics": "09c3193669d8c580df3cea6922677818.bin3", 13 | "PhysicsV2": { 14 | "File": "09c3193669d8c580df3cea6922677818.bin3" 15 | }, 16 | "Motions": { 17 | "Idle": [{ 18 | "Name": "待机", 19 | "File": "930ccd3afc12a516e72bb864916c1e16.bin3" 20 | }], 21 | "Shake": [{ 22 | "Name": "晕", 23 | "File": "45d49cbd99e34340f4e2a08e3aec9646.bin3", 24 | "Text": "啊呜...", 25 | "TextDuration": 2000 26 | }, { 27 | "File": "b77bfecb6a5dee8382906a34f3917255.bin3" 28 | }], 29 | "Tap左手": [{ 30 | "Name": "吉他", 31 | "File": "4c70766cf8b2070eaa3f7b384cc266b9.bin3", 32 | "Text": "可爱的鸽子鸽子~我喜欢你~", 33 | "TextDelay": 1200, 34 | "TextDuration": 5600 35 | }], 36 | "Tap右手": [{ 37 | "Name": "游戏", 38 | "File": "0f54599feff96877de0dbfb649caad58.bin3", 39 | "Text": "来陪我玩游戏!", 40 | "TextDelay": 600, 41 | "TextDuration": 2500 42 | }], 43 | "Tap腰": [{ 44 | "Name": "傲娇", 45 | "File": "e2f024f08042e3ab1d03377bd19a0419.bin3", 46 | "Text": "哼,才不是傲娇大小姐", 47 | "TextDelay": 500, 48 | "TextDuration": 3000 49 | }], 50 | "Tap中间刘海": [{ 51 | "Name": "害羞", 52 | "File": "e7e47270b0c9f7f1d6448b944392e0a0.bin3", 53 | "Text": "好...好兄弟之间喜欢很正常啦", 54 | "TextDelay": 1500, 55 | "TextDuration": 3000 56 | }, { 57 | "Name": "害羞2", 58 | "File": "e7e47270b0c9f7f1d6448b944392e0a0.bin3", 59 | "Text": "也...也不是不可以", 60 | "TextDelay": 2000, 61 | "TextDuration": 3000 62 | }], 63 | "Tap嘴": [{ 64 | "Name": "傲娇", 65 | "File": "e2f024f08042e3ab1d03377bd19a0419.bin3", 66 | "Text": "什么傲娇啦,我才没有", 67 | "TextDelay": 500, 68 | "TextDuration": 2200 69 | }], 70 | "Tap胸口项链": [{ 71 | "Name": "笑", 72 | "File": "5afa7a7ca7dc29f17325dcb8af964a35.bin3" 73 | }], 74 | "Tap脖子": [{ 75 | "Name": "监督", 76 | "File": "7e263ff839def59c49d337048df5ce84.bin3", 77 | "Text": "嗯?老戳我干嘛,快去干正事啦 ", 78 | "TextDelay": 550, 79 | "TextDuration": 4000 80 | }], 81 | "Tap 右边头饰小花": [{ 82 | "Name": "懒羊羊", 83 | "File": "0db0bd8ff7847014772caad0ae790ebf.bin3", 84 | "Text": "顶晚人...顶晚人在哪里...", 85 | "TextDelay": 800, 86 | "TextDuration": 6000 87 | }], 88 | "Tap右头饰": [{ 89 | "Name": "猫", 90 | "File": "19c910845c10e04474236a7cb8f482c8.bin3", 91 | "Text": "neko panch!", 92 | "TextDelay": 500, 93 | "TextDuration": 2000 94 | }], 95 | "Tap右眼": [{ 96 | "Name": "惊讶", 97 | "File": "d18b62e12feb89b0a7f603b0eb9efd30.bin3", 98 | "Text": "啊", 99 | "TextDelay": 200, 100 | "TextDuration": 1000 101 | }], 102 | "Tap左眼": [{ 103 | "Name": "墨镜", 104 | "File": "23e132e412ad2cb5d1ecbcc8f256b3b0.bin3", 105 | "Text": "嗯哼~我超帅的", 106 | "TextDelay": 700, 107 | "TextDuration": 2000 108 | }], 109 | "Tap右马尾 ": [{ 110 | "Name": "水母", 111 | "File": "583ba01a373b1abf564bf4963e3ab433.bin3" 112 | }], 113 | "Tap左马尾": [{ 114 | "Name": "><", 115 | "File": "b77bfecb6a5dee8382906a34f3917255.bin3", 116 | "Text": "头发摸乱了啦~", 117 | "TextDelay": 500, 118 | "TextDuration": 2000 119 | }], 120 | "Tap右手臂": [{ 121 | "File": "7e263ff839def59c49d337048df5ce84.bin3", 122 | "Text": "嗯?老戳我干嘛,快去干正事啦 ", 123 | "TextDelay": 550, 124 | "TextDuration": 4000 125 | }], 126 | "Tap左中马尾": [{ 127 | "File": "583ba01a373b1abf564bf4963e3ab433.bin3" 128 | }] 129 | } 130 | }, 131 | "Controllers": { 132 | "ParamHit": {}, 133 | "ParamLoop": {}, 134 | "KeyTrigger": {}, 135 | "EyeBlink": { 136 | "MinInterval": 500, 137 | "MaxInterval": 6000, 138 | "Items": [{ 139 | "Id": "ParamEyeLOpen", 140 | "Min": 0.0, 141 | "Max": 1.0, 142 | "BlendMode": 2, 143 | "Input": 0 144 | }, { 145 | "Id": "ParamEyeROpen", 146 | "Min": 0.0, 147 | "Max": 1.0, 148 | "BlendMode": 2, 149 | "Input": 0 150 | }, { 151 | "Id": "Param7", 152 | "Min": 0.0, 153 | "Max": 1.0, 154 | "BlendMode": 2, 155 | "Input": 0 156 | }, { 157 | "Id": "Param8", 158 | "Min": 0.0, 159 | "Max": 1.0, 160 | "BlendMode": 2, 161 | "Input": 0 162 | }], 163 | "Enabled": true 164 | }, 165 | "LipSync": { 166 | "Gain": 5.0 167 | }, 168 | "MouseTracking": { 169 | "SmoothTime": 0.15, 170 | "Items": [{ 171 | "Id": "ParamAngleX", 172 | "Min": -30.0, 173 | "Max": 30.0, 174 | "DefaultValue": 0.0, 175 | "Weight": 0.359834284, 176 | "BlendMode": 1, 177 | "Input": 1 178 | }, { 179 | "Id": "ParamAngleY", 180 | "Min": -30.0, 181 | "Max": 30.0, 182 | "DefaultValue": 0.0, 183 | "Weight": 0.3398514, 184 | "BlendMode": 1, 185 | "Axis": 1, 186 | "Input": 2 187 | }, { 188 | "Id": "ParamAngleZ", 189 | "Min": -15.0, 190 | "Max": 15.0, 191 | "DefaultValue": 0.0, 192 | "Weight": 0.199971348, 193 | "BlendMode": 1, 194 | "Axis": 2, 195 | "Input": 1 196 | }, { 197 | "Id": "ParamBodyAngleX", 198 | "Min": -10.0, 199 | "Max": 10.0, 200 | "DefaultValue": 0.0, 201 | "Weight": 0.376962453, 202 | "BlendMode": 1, 203 | "Input": 1 204 | }, { 205 | "Id": "ParamBodyAngleZ", 206 | "Min": -10.0, 207 | "Max": 10.0, 208 | "DefaultValue": 0.0, 209 | "Weight": 0.365543664, 210 | "BlendMode": 1, 211 | "Axis": 2, 212 | "Input": 1 213 | }, { 214 | "Id": "Param46", 215 | "Min": -30.0, 216 | "Max": 30.0, 217 | "DefaultValue": 0.0, 218 | "Weight": 0.411218822, 219 | "BlendMode": 1, 220 | "Axis": 1, 221 | "Input": 2 222 | }, { 223 | "Id": "ParamEyeBallX", 224 | "Min": -1.0, 225 | "Max": 1.0, 226 | "DefaultValue": 0.0, 227 | "BlendMode": 1, 228 | "Input": 1 229 | }, { 230 | "Id": "ParamEyeBallY", 231 | "Min": -1.0, 232 | "Max": 1.0, 233 | "DefaultValue": 0.0, 234 | "BlendMode": 1, 235 | "Axis": 1, 236 | "Input": 2 237 | }], 238 | "Enabled": true 239 | }, 240 | "AutoBreath": { 241 | "Enabled": true 242 | }, 243 | "ExtraMotion": { 244 | "Enabled": true 245 | }, 246 | "Accelerometer": { 247 | "Enabled": true 248 | }, 249 | "Microphone": {}, 250 | "Transform": {}, 251 | "FaceTracking": { 252 | "Enabled": true 253 | }, 254 | "ParamValue": {}, 255 | "PartOpacity": { 256 | "Items": [{ 257 | "Name": "猫耳", 258 | "Ids": ["Part23", "weiba_Skinning"] 259 | }, { 260 | "Name": "墨镜", 261 | "Ids": ["Part26"] 262 | }], 263 | "Enabled": true 264 | }, 265 | "ArtmeshOpacity": {}, 266 | "ArtmeshColor": {}, 267 | "ArtmeshCulling": { 268 | "DefaultMode": 0 269 | }, 270 | "IntimacySystem": {} 271 | }, 272 | "HitAreas": [{ 273 | "Name": "左手", 274 | "Id": "ArtMesh2" 275 | }, { 276 | "Name": "右手", 277 | "Id": "ArtMesh87" 278 | }, { 279 | "Name": "腰", 280 | "Id": "yao" 281 | }, { 282 | "Name": "中间刘海", 283 | "Id": "ArtMesh26" 284 | }, { 285 | "Name": "嘴", 286 | "Id": "ArtMesh35" 287 | }, { 288 | "Name": "胸口项链", 289 | "Id": "ArtMesh45" 290 | }, { 291 | "Name": "脖子", 292 | "Id": "ArtMesh52" 293 | }, { 294 | "Name": " 右边头饰小花", 295 | "Id": "hua2" 296 | }, { 297 | "Name": "右头饰", 298 | "Id": "ArtMesh19" 299 | }, { 300 | "Name": "右眼", 301 | "Id": "qiu" 302 | }, { 303 | "Name": "左眼", 304 | "Id": "ArtMesh42" 305 | }, { 306 | "Name": "右马尾 ", 307 | "Id": "R8" 308 | }, { 309 | "Name": "左马尾", 310 | "Id": "L4" 311 | }, { 312 | "Name": "右手臂", 313 | "Id": "ArtMesh48" 314 | }, { 315 | "Name": "左中马尾", 316 | "Id": "L6" 317 | }], 318 | "Options": { 319 | "TexFixed": true 320 | } 321 | } -------------------------------------------------------------------------------- /res/live2d/models/Ava/raw.preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/models/Ava/raw.preview.png -------------------------------------------------------------------------------- /res/live2d/models/Diana/Diana.4096/texture_00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/models/Diana/Diana.4096/texture_00.png -------------------------------------------------------------------------------- /res/live2d/models/Diana/Diana.moc3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/models/Diana/Diana.moc3 -------------------------------------------------------------------------------- /res/live2d/models/Diana/Diana.model3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 3, 3 | "FileReferences": { 4 | "Moc": "Diana.moc3", 5 | "Textures": [ 6 | "Diana.4096/texture_00.png" 7 | ], 8 | "Physics": "Diana.physics3.json", 9 | "PhysicsV2": { 10 | "File": "Diana.physics3.json" 11 | }, 12 | "Motions": { 13 | "Idle": [{ 14 | "File": "motions/Diana_idle.motion3.json" 15 | }], 16 | "Tap生气 -领结": [{ 17 | "File": "motions/Diana_tap01.motion3.json", 18 | "Text": "嘉心糖屁用没有", 19 | "TextDelay": 2000, 20 | "TextDuration": 3000 21 | }], 22 | "Tap= = 左蝴蝶结": [{ 23 | "File": "motions/Diana_tap02.motion3.json", 24 | "Text": "有人急了,但我不说是谁~", 25 | "TextDelay": 1000, 26 | "TextDuration": 4000 27 | }], 28 | "Tap笑- 脸": [{ 29 | "File": "motions/Diana_tap03.motion3.json", 30 | "Text": "hi!嘉心糖", 31 | "TextDelay": 2200, 32 | "TextDuration": 2300 33 | }], 34 | "Tap哭 -眼角": [{ 35 | "File": "motions/Diana_tap04.motion3.json", 36 | "Text": "呜呜...呜呜呜....", 37 | "TextDelay": 3200, 38 | "TextDuration": 4000 39 | }], 40 | "Shake": [{ 41 | "File": "motions/Diana_tap05.motion3.json", 42 | "Text": "别摇啦!", 43 | "TextDelay": 1000, 44 | "TextDuration": 2000 45 | }], 46 | "Tap害羞-中间刘海": [{ 47 | "File": "motions/Diana_tap06.motion3.json", 48 | "Text": "想然然了没有呀~", 49 | "TextDelay": 1500, 50 | "TextDuration": 3000 51 | }], 52 | "Tap抱阿草-左手": [{ 53 | "File": "motions/Diana_tap07.motion3.json", 54 | "Text": "阿草好软呀~", 55 | "TextDelay": 3000, 56 | "TextDuration": 2500 57 | }], 58 | "Tap摇头- 身体": [{ 59 | "File": "motions/Diana_tap05.motion3.json", 60 | "Text": "不要再戳啦!好痒!", 61 | "TextDelay": 800, 62 | "TextDuration": 2500 63 | }], 64 | "Tap耳朵-发卡": [{ 65 | "File": "motions/Diana_tap08.motion3.json", 66 | "Text": "嗷呜~~~", 67 | "TextDelay": 1500, 68 | "TextDuration": 3000 69 | }], 70 | "Tap打瞌睡- 呆毛": [{ 71 | "File": "motions/Diana_tap09.motion3.json", 72 | "Text": "啊", 73 | "TextDelay": 7500, 74 | "TextDuration": 800 75 | }], 76 | "Leave": [{ 77 | "File": "motions/Diana_tap09.motion3.json", 78 | "Text": "zzZ。。。", 79 | "TextDelay": 4000, 80 | "TextDuration": 4000 81 | }], 82 | "Tap左头发": [{ 83 | "File": "motions/Diana_tap10.motion3.json" 84 | }], 85 | "Tap右头发": [{ 86 | "File": "motions/Diana_tap11.motion3.json", 87 | "Text": "哇!好吃的!", 88 | "TextDelay": 500, 89 | "TextDuration": 3000 90 | }] 91 | } 92 | }, 93 | "Controllers": { 94 | "ParamHit": {}, 95 | "ParamLoop": {}, 96 | "KeyTrigger": {}, 97 | "EyeBlink": { 98 | "MinInterval": 500, 99 | "MaxInterval": 6000, 100 | "Enabled": true 101 | }, 102 | "LipSync": { 103 | "Gain": 5.0 104 | }, 105 | "MouseTracking": { 106 | "SmoothTime": 0.15, 107 | "Items": [{ 108 | "Id": "ParamBodyAngleX", 109 | "Min": -10.0, 110 | "Max": 10.0, 111 | "DefaultValue": 0.0, 112 | "Weight": 0.76343286, 113 | "BlendMode": 1, 114 | "Input": 1 115 | }, { 116 | "Id": "ParamAngleX", 117 | "Min": -30.0, 118 | "Max": 30.0, 119 | "DefaultValue": 0.0, 120 | "Weight": 0.798328757, 121 | "BlendMode": 1, 122 | "Input": 1 123 | }, { 124 | "Id": "ParamBodyAngleZ", 125 | "Min": -10.0, 126 | "Max": 10.0, 127 | "DefaultValue": 0.0, 128 | "Weight": 0.6260679, 129 | "BlendMode": 1, 130 | "Input": 1 131 | }, { 132 | "Id": "ParamBodyAngleY", 133 | "Min": -10.0, 134 | "Max": 10.0, 135 | "DefaultValue": 0.0, 136 | "Weight": 0.8907613, 137 | "BlendMode": 1, 138 | "Axis": 1, 139 | "Input": 2 140 | }, { 141 | "Id": "ParamAngleY", 142 | "Min": -30.0, 143 | "Max": 30.0, 144 | "DefaultValue": 0.0, 145 | "Weight": 0.7521123, 146 | "BlendMode": 1, 147 | "Axis": 1, 148 | "Input": 2 149 | }], 150 | "Enabled": true 151 | }, 152 | "AutoBreath": { 153 | "Enabled": true 154 | }, 155 | "ExtraMotion": { 156 | "Enabled": true 157 | }, 158 | "Accelerometer": { 159 | "Enabled": true 160 | }, 161 | "Microphone": {}, 162 | "Transform": {}, 163 | "FaceTracking": { 164 | "Enabled": true 165 | }, 166 | "ParamValue": {}, 167 | "PartOpacity": {}, 168 | "ArtmeshOpacity": {}, 169 | "ArtmeshColor": {}, 170 | "ArtmeshCulling": { 171 | "DefaultMode": 0 172 | }, 173 | "IntimacySystem": {} 174 | }, 175 | "HitAreas": [{ 176 | "Name": "= = 左蝴蝶结", 177 | "Id": "ArtMesh15" 178 | }, { 179 | "Name": "笑- 脸", 180 | "Id": "ArtMesh51" 181 | }, { 182 | "Name": "哭 -眼角", 183 | "Id": "ArtMesh48" 184 | }, { 185 | "Name": "生气 -领结", 186 | "Id": "ArtMesh56" 187 | }, { 188 | "Name": "害羞-中间刘海", 189 | "Id": "ArtMesh10" 190 | }, { 191 | "Name": "抱阿草-左手", 192 | "Id": "L4" 193 | }, { 194 | "Name": "打瞌睡- 呆毛", 195 | "Id": "ArtMesh9" 196 | }, { 197 | "Name": "耳朵-发卡", 198 | "Id": "L3" 199 | }, { 200 | "Name": "摇头- 身体", 201 | "Id": "jiaran" 202 | }, { 203 | "Name": "左头发", 204 | "Id": "L5" 205 | }, { 206 | "Name": "右头发", 207 | "Id": "R5" 208 | }], 209 | "Options": { 210 | "TexFixed": true 211 | } 212 | } -------------------------------------------------------------------------------- /res/live2d/models/Diana/audio/jiaxintang-nouse.aac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/models/Diana/audio/jiaxintang-nouse.aac -------------------------------------------------------------------------------- /res/live2d/models/Diana/motions/Diana_idle.motion3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 3, 3 | "Meta": { 4 | "Duration": 7.667, 5 | "Fps": 30.0, 6 | "Loop": true, 7 | "AreBeziersRestricted": true, 8 | "CurveCount": 48, 9 | "TotalSegmentCount": 48, 10 | "TotalPointCount": 96, 11 | "UserDataCount": 0, 12 | "TotalUserDataSize": 0 13 | }, 14 | "Curves": [ 15 | { 16 | "Target": "Parameter", 17 | "Id": "Param2", 18 | "Segments": [ 19 | 0, 20 | -30, 21 | 0, 22 | 7.667, 23 | -30 24 | ] 25 | }, 26 | { 27 | "Target": "Parameter", 28 | "Id": "Param35", 29 | "Segments": [ 30 | 0, 31 | -30, 32 | 0, 33 | 7.667, 34 | -30 35 | ] 36 | }, 37 | { 38 | "Target": "Parameter", 39 | "Id": "Param3", 40 | "Segments": [ 41 | 0, 42 | -30, 43 | 0, 44 | 7.667, 45 | -30 46 | ] 47 | }, 48 | { 49 | "Target": "Parameter", 50 | "Id": "Param4", 51 | "Segments": [ 52 | 0, 53 | -30, 54 | 0, 55 | 7.667, 56 | -30 57 | ] 58 | }, 59 | { 60 | "Target": "Parameter", 61 | "Id": "Param5", 62 | "Segments": [ 63 | 0, 64 | -30, 65 | 0, 66 | 7.667, 67 | -30 68 | ] 69 | }, 70 | { 71 | "Target": "Parameter", 72 | "Id": "Param41", 73 | "Segments": [ 74 | 0, 75 | -30, 76 | 0, 77 | 7.667, 78 | -30 79 | ] 80 | }, 81 | { 82 | "Target": "Parameter", 83 | "Id": "Param46", 84 | "Segments": [ 85 | 0, 86 | -30, 87 | 0, 88 | 7.667, 89 | -30 90 | ] 91 | }, 92 | { 93 | "Target": "Parameter", 94 | "Id": "Param45", 95 | "Segments": [ 96 | 0, 97 | -30, 98 | 0, 99 | 7.667, 100 | -30 101 | ] 102 | }, 103 | { 104 | "Target": "Parameter", 105 | "Id": "Param", 106 | "Segments": [ 107 | 0, 108 | -30, 109 | 0, 110 | 7.667, 111 | -30 112 | ] 113 | }, 114 | { 115 | "Target": "Parameter", 116 | "Id": "Param8", 117 | "Segments": [ 118 | 0, 119 | -30, 120 | 0, 121 | 7.667, 122 | -30 123 | ] 124 | }, 125 | { 126 | "Target": "Parameter", 127 | "Id": "Param9", 128 | "Segments": [ 129 | 0, 130 | -30, 131 | 0, 132 | 7.667, 133 | -30 134 | ] 135 | }, 136 | { 137 | "Target": "Parameter", 138 | "Id": "Param10", 139 | "Segments": [ 140 | 0, 141 | -30, 142 | 0, 143 | 7.667, 144 | -30 145 | ] 146 | }, 147 | { 148 | "Target": "Parameter", 149 | "Id": "Param6", 150 | "Segments": [ 151 | 0, 152 | -29, 153 | 0, 154 | 7.667, 155 | -29 156 | ] 157 | }, 158 | { 159 | "Target": "Parameter", 160 | "Id": "Param7", 161 | "Segments": [ 162 | 0, 163 | -30, 164 | 0, 165 | 7.667, 166 | -30 167 | ] 168 | }, 169 | { 170 | "Target": "Parameter", 171 | "Id": "ParamBodyAngleX", 172 | "Segments": [ 173 | 0, 174 | 0, 175 | 0, 176 | 7.667, 177 | 0 178 | ] 179 | }, 180 | { 181 | "Target": "Parameter", 182 | "Id": "ParamBodyAngleY", 183 | "Segments": [ 184 | 0, 185 | 0, 186 | 0, 187 | 7.667, 188 | 0 189 | ] 190 | }, 191 | { 192 | "Target": "Parameter", 193 | "Id": "ParamBodyAngleZ", 194 | "Segments": [ 195 | 0, 196 | 0, 197 | 0, 198 | 7.667, 199 | 0 200 | ] 201 | }, 202 | { 203 | "Target": "Parameter", 204 | "Id": "ParamAngleX", 205 | "Segments": [ 206 | 0, 207 | 0, 208 | 0, 209 | 7.667, 210 | 0 211 | ] 212 | }, 213 | { 214 | "Target": "Parameter", 215 | "Id": "ParamAngleY", 216 | "Segments": [ 217 | 0, 218 | 0, 219 | 0, 220 | 7.667, 221 | 0 222 | ] 223 | }, 224 | { 225 | "Target": "Parameter", 226 | "Id": "ParamAngleZ", 227 | "Segments": [ 228 | 0, 229 | 0, 230 | 0, 231 | 7.667, 232 | 0 233 | ] 234 | }, 235 | { 236 | "Target": "Parameter", 237 | "Id": "ParamEyeLOpen", 238 | "Segments": [ 239 | 0, 240 | 1, 241 | 0, 242 | 7.667, 243 | 1 244 | ] 245 | }, 246 | { 247 | "Target": "Parameter", 248 | "Id": "ParamEyeLSmile", 249 | "Segments": [ 250 | 0, 251 | 0, 252 | 0, 253 | 7.667, 254 | 0 255 | ] 256 | }, 257 | { 258 | "Target": "Parameter", 259 | "Id": "ParamEyeROpen", 260 | "Segments": [ 261 | 0, 262 | 1, 263 | 0, 264 | 7.667, 265 | 1 266 | ] 267 | }, 268 | { 269 | "Target": "Parameter", 270 | "Id": "ParamEyeRSmile", 271 | "Segments": [ 272 | 0, 273 | 0, 274 | 0, 275 | 7.667, 276 | 0 277 | ] 278 | }, 279 | { 280 | "Target": "Parameter", 281 | "Id": "ParamEyeBallX", 282 | "Segments": [ 283 | 0, 284 | 0, 285 | 0, 286 | 7.667, 287 | 0 288 | ] 289 | }, 290 | { 291 | "Target": "Parameter", 292 | "Id": "ParamEyeBallY", 293 | "Segments": [ 294 | 0, 295 | 0, 296 | 0, 297 | 7.667, 298 | 0 299 | ] 300 | }, 301 | { 302 | "Target": "Parameter", 303 | "Id": "ParamBrowLY", 304 | "Segments": [ 305 | 0, 306 | 0, 307 | 0, 308 | 7.667, 309 | 0 310 | ] 311 | }, 312 | { 313 | "Target": "Parameter", 314 | "Id": "ParamBrowRY", 315 | "Segments": [ 316 | 0, 317 | 0, 318 | 0, 319 | 7.667, 320 | 0 321 | ] 322 | }, 323 | { 324 | "Target": "Parameter", 325 | "Id": "ParamBrowLX", 326 | "Segments": [ 327 | 0, 328 | 0, 329 | 0, 330 | 7.667, 331 | 0 332 | ] 333 | }, 334 | { 335 | "Target": "Parameter", 336 | "Id": "ParamBrowRX", 337 | "Segments": [ 338 | 0, 339 | 0, 340 | 0, 341 | 7.667, 342 | 0 343 | ] 344 | }, 345 | { 346 | "Target": "Parameter", 347 | "Id": "ParamBrowLAngle", 348 | "Segments": [ 349 | 0, 350 | 0, 351 | 0, 352 | 7.667, 353 | 0 354 | ] 355 | }, 356 | { 357 | "Target": "Parameter", 358 | "Id": "ParamBrowRAngle", 359 | "Segments": [ 360 | 0, 361 | 0, 362 | 0, 363 | 7.667, 364 | 0 365 | ] 366 | }, 367 | { 368 | "Target": "Parameter", 369 | "Id": "ParamBrowRForm", 370 | "Segments": [ 371 | 0, 372 | 0, 373 | 0, 374 | 7.667, 375 | 0 376 | ] 377 | }, 378 | { 379 | "Target": "Parameter", 380 | "Id": "ParamBrowLForm", 381 | "Segments": [ 382 | 0, 383 | 0, 384 | 0, 385 | 7.667, 386 | 0 387 | ] 388 | }, 389 | { 390 | "Target": "Parameter", 391 | "Id": "ParamMouthForm", 392 | "Segments": [ 393 | 0, 394 | 0.1, 395 | 0, 396 | 7.667, 397 | 0.1 398 | ] 399 | }, 400 | { 401 | "Target": "Parameter", 402 | "Id": "ParamMouthOpenY", 403 | "Segments": [ 404 | 0, 405 | 0, 406 | 0, 407 | 7.667, 408 | 0 409 | ] 410 | }, 411 | { 412 | "Target": "Parameter", 413 | "Id": "Param47", 414 | "Segments": [ 415 | 0, 416 | -1, 417 | 0, 418 | 7.667, 419 | -1 420 | ] 421 | }, 422 | { 423 | "Target": "Parameter", 424 | "Id": "ParamCheek", 425 | "Segments": [ 426 | 0, 427 | 0, 428 | 0, 429 | 7.667, 430 | 0 431 | ] 432 | }, 433 | { 434 | "Target": "Parameter", 435 | "Id": "Param48", 436 | "Segments": [ 437 | 0, 438 | -30, 439 | 0, 440 | 7.667, 441 | -30 442 | ] 443 | }, 444 | { 445 | "Target": "Parameter", 446 | "Id": "Param49", 447 | "Segments": [ 448 | 0, 449 | -30, 450 | 0, 451 | 7.667, 452 | -30 453 | ] 454 | }, 455 | { 456 | "Target": "Parameter", 457 | "Id": "Param29", 458 | "Segments": [ 459 | 0, 460 | -30, 461 | 0, 462 | 7.667, 463 | -30 464 | ] 465 | }, 466 | { 467 | "Target": "Parameter", 468 | "Id": "Param30", 469 | "Segments": [ 470 | 0, 471 | 0, 472 | 0, 473 | 7.667, 474 | 0 475 | ] 476 | }, 477 | { 478 | "Target": "Parameter", 479 | "Id": "Param37", 480 | "Segments": [ 481 | 0, 482 | -30, 483 | 0, 484 | 7.667, 485 | -30 486 | ] 487 | }, 488 | { 489 | "Target": "Parameter", 490 | "Id": "Param32", 491 | "Segments": [ 492 | 0, 493 | -30, 494 | 0, 495 | 7.667, 496 | -30 497 | ] 498 | }, 499 | { 500 | "Target": "Parameter", 501 | "Id": "Param36", 502 | "Segments": [ 503 | 0, 504 | 0, 505 | 0, 506 | 7.667, 507 | 0 508 | ] 509 | }, 510 | { 511 | "Target": "Parameter", 512 | "Id": "Param38", 513 | "Segments": [ 514 | 0, 515 | -30, 516 | 0, 517 | 7.667, 518 | -30 519 | ] 520 | }, 521 | { 522 | "Target": "Parameter", 523 | "Id": "Param39", 524 | "Segments": [ 525 | 0, 526 | -30, 527 | 0, 528 | 7.667, 529 | -30 530 | ] 531 | }, 532 | { 533 | "Target": "Parameter", 534 | "Id": "Param12", 535 | "Segments": [ 536 | 0, 537 | -30, 538 | 0, 539 | 7.667, 540 | -30 541 | ] 542 | } 543 | ] 544 | } -------------------------------------------------------------------------------- /res/live2d/models/Diana/motions/Diana_tap06.motion3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 3, 3 | "Meta": { 4 | "Duration": 6.667, 5 | "Fps": 30.0, 6 | "Loop": true, 7 | "AreBeziersRestricted": true, 8 | "CurveCount": 25, 9 | "TotalSegmentCount": 120, 10 | "TotalPointCount": 319, 11 | "UserDataCount": 0, 12 | "TotalUserDataSize": 0 13 | }, 14 | "Curves": [ 15 | { 16 | "Target": "Parameter", 17 | "Id": "Param3", 18 | "Segments": [ 19 | 0, 20 | -30, 21 | 0, 22 | 1.933, 23 | -30, 24 | 1, 25 | 2.444, 26 | -30, 27 | 2.956, 28 | 30, 29 | 3.467, 30 | 30, 31 | 1, 32 | 3.956, 33 | 30, 34 | 4.444, 35 | -30, 36 | 4.933, 37 | -30, 38 | 1, 39 | 5.356, 40 | -30, 41 | 5.778, 42 | 10, 43 | 6.2, 44 | 10, 45 | 0, 46 | 6.667, 47 | 10 48 | ] 49 | }, 50 | { 51 | "Target": "Parameter", 52 | "Id": "Param4", 53 | "Segments": [ 54 | 0, 55 | -30, 56 | 0, 57 | 6.667, 58 | -30 59 | ] 60 | }, 61 | { 62 | "Target": "Parameter", 63 | "Id": "Param5", 64 | "Segments": [ 65 | 0, 66 | -30, 67 | 0, 68 | 6.667, 69 | -30 70 | ] 71 | }, 72 | { 73 | "Target": "Parameter", 74 | "Id": "ParamBodyAngleX", 75 | "Segments": [ 76 | 0, 77 | 0, 78 | 1, 79 | 0.333, 80 | 0, 81 | 0.667, 82 | -2, 83 | 1, 84 | -2, 85 | 1, 86 | 1.267, 87 | -2, 88 | 1.533, 89 | -0.247, 90 | 1.8, 91 | 4, 92 | 1, 93 | 2.033, 94 | 7.716, 95 | 2.267, 96 | 10, 97 | 2.5, 98 | 10, 99 | 1, 100 | 2.711, 101 | 10, 102 | 2.922, 103 | 3, 104 | 3.133, 105 | 3, 106 | 1, 107 | 3.378, 108 | 3, 109 | 3.622, 110 | 8, 111 | 3.867, 112 | 8, 113 | 1, 114 | 4.111, 115 | 8, 116 | 4.356, 117 | -1, 118 | 4.6, 119 | -1, 120 | 1, 121 | 5.078, 122 | -1, 123 | 5.556, 124 | 2, 125 | 6.033, 126 | 2, 127 | 0, 128 | 6.667, 129 | 2 130 | ] 131 | }, 132 | { 133 | "Target": "Parameter", 134 | "Id": "ParamBodyAngleY", 135 | "Segments": [ 136 | 0, 137 | 0, 138 | 1, 139 | 0.333, 140 | 0, 141 | 0.667, 142 | 1, 143 | 1, 144 | 1, 145 | 1, 146 | 1.267, 147 | 1, 148 | 1.533, 149 | -4.759, 150 | 1.8, 151 | -5, 152 | 1, 153 | 2.733, 154 | -5.845, 155 | 3.667, 156 | -6, 157 | 4.6, 158 | -6, 159 | 0, 160 | 6.667, 161 | -6 162 | ] 163 | }, 164 | { 165 | "Target": "Parameter", 166 | "Id": "ParamBodyAngleZ", 167 | "Segments": [ 168 | 0, 169 | 0, 170 | 1, 171 | 0.333, 172 | 0, 173 | 0.667, 174 | -1, 175 | 1, 176 | -1, 177 | 1, 178 | 1.267, 179 | -1, 180 | 1.533, 181 | 7, 182 | 1.8, 183 | 7, 184 | 1, 185 | 2.733, 186 | 7, 187 | 3.667, 188 | 5, 189 | 4.6, 190 | 5, 191 | 1, 192 | 5.078, 193 | 5, 194 | 5.556, 195 | 8, 196 | 6.033, 197 | 8, 198 | 0, 199 | 6.667, 200 | 8 201 | ] 202 | }, 203 | { 204 | "Target": "Parameter", 205 | "Id": "ParamAngleX", 206 | "Segments": [ 207 | 0, 208 | 0, 209 | 1, 210 | 0.333, 211 | 0, 212 | 0.667, 213 | -0.078, 214 | 1, 215 | 2, 216 | 1, 217 | 1.267, 218 | 3.662, 219 | 1.533, 220 | 11, 221 | 1.8, 222 | 11, 223 | 1, 224 | 2.733, 225 | 11, 226 | 3.667, 227 | -6, 228 | 4.6, 229 | -6, 230 | 1, 231 | 5.078, 232 | -6, 233 | 5.556, 234 | 2, 235 | 6.033, 236 | 2, 237 | 0, 238 | 6.667, 239 | 2 240 | ] 241 | }, 242 | { 243 | "Target": "Parameter", 244 | "Id": "ParamAngleY", 245 | "Segments": [ 246 | 0, 247 | 1, 248 | 1, 249 | 0.333, 250 | 1, 251 | 0.667, 252 | 0.162, 253 | 1, 254 | -6, 255 | 1, 256 | 1.267, 257 | -10.929, 258 | 1.533, 259 | -19, 260 | 1.8, 261 | -19, 262 | 1, 263 | 2.733, 264 | -19, 265 | 3.667, 266 | -18.745, 267 | 4.6, 268 | -15, 269 | 1, 270 | 5.078, 271 | -13.083, 272 | 5.556, 273 | 0, 274 | 6.033, 275 | 0, 276 | 0, 277 | 6.667, 278 | 0 279 | ] 280 | }, 281 | { 282 | "Target": "Parameter", 283 | "Id": "ParamAngleZ", 284 | "Segments": [ 285 | 0, 286 | 0, 287 | 1, 288 | 0.6, 289 | 0, 290 | 1.2, 291 | 19, 292 | 1.8, 293 | 19, 294 | 1, 295 | 2.733, 296 | 19, 297 | 3.667, 298 | -25, 299 | 4.6, 300 | -25, 301 | 1, 302 | 5.078, 303 | -25, 304 | 5.556, 305 | -4, 306 | 6.033, 307 | -4, 308 | 0, 309 | 6.667, 310 | -4 311 | ] 312 | }, 313 | { 314 | "Target": "Parameter", 315 | "Id": "ParamEyeLOpen", 316 | "Segments": [ 317 | 0, 318 | 1, 319 | 0, 320 | 0.5, 321 | 1, 322 | 1, 323 | 0.544, 324 | 1, 325 | 0.589, 326 | 0, 327 | 0.633, 328 | 0, 329 | 1, 330 | 0.678, 331 | 0, 332 | 0.722, 333 | 1, 334 | 0.767, 335 | 1, 336 | 1, 337 | 0.811, 338 | 1, 339 | 0.856, 340 | 0, 341 | 0.9, 342 | 0, 343 | 1, 344 | 0.944, 345 | 0, 346 | 0.989, 347 | 1, 348 | 1.033, 349 | 1, 350 | 1, 351 | 1.333, 352 | 1, 353 | 1.633, 354 | 1, 355 | 1.933, 356 | 1, 357 | 1, 358 | 2.044, 359 | 1, 360 | 2.156, 361 | 0, 362 | 2.267, 363 | 0, 364 | 1, 365 | 2.589, 366 | 0, 367 | 2.911, 368 | 0, 369 | 3.233, 370 | 0, 371 | 1, 372 | 3.389, 373 | 0, 374 | 3.544, 375 | 1, 376 | 3.7, 377 | 1, 378 | 1, 379 | 4.078, 380 | 1, 381 | 4.456, 382 | 1, 383 | 4.833, 384 | 1, 385 | 1, 386 | 4.878, 387 | 1, 388 | 4.922, 389 | 0, 390 | 4.967, 391 | 0, 392 | 1, 393 | 5.011, 394 | 0, 395 | 5.056, 396 | 1, 397 | 5.1, 398 | 1, 399 | 1, 400 | 5.144, 401 | 1, 402 | 5.189, 403 | 0, 404 | 5.233, 405 | 0, 406 | 1, 407 | 5.278, 408 | 0, 409 | 5.322, 410 | 1, 411 | 5.367, 412 | 1, 413 | 0, 414 | 6.667, 415 | 1 416 | ] 417 | }, 418 | { 419 | "Target": "Parameter", 420 | "Id": "ParamEyeROpen", 421 | "Segments": [ 422 | 0, 423 | 1, 424 | 0, 425 | 0.5, 426 | 1, 427 | 1, 428 | 0.544, 429 | 1, 430 | 0.589, 431 | 0, 432 | 0.633, 433 | 0, 434 | 1, 435 | 0.678, 436 | 0, 437 | 0.722, 438 | 1, 439 | 0.767, 440 | 1, 441 | 1, 442 | 0.811, 443 | 1, 444 | 0.856, 445 | 0, 446 | 0.9, 447 | 0, 448 | 1, 449 | 0.944, 450 | 0, 451 | 0.989, 452 | 1, 453 | 1.033, 454 | 1, 455 | 1, 456 | 1.333, 457 | 1, 458 | 1.633, 459 | 1, 460 | 1.933, 461 | 1, 462 | 1, 463 | 2.044, 464 | 1, 465 | 2.156, 466 | 0, 467 | 2.267, 468 | 0, 469 | 1, 470 | 2.589, 471 | 0, 472 | 2.911, 473 | 0, 474 | 3.233, 475 | 0, 476 | 1, 477 | 3.389, 478 | 0, 479 | 3.544, 480 | 1, 481 | 3.7, 482 | 1, 483 | 1, 484 | 4.078, 485 | 1, 486 | 4.456, 487 | 1, 488 | 4.833, 489 | 1, 490 | 1, 491 | 4.878, 492 | 1, 493 | 4.922, 494 | 0, 495 | 4.967, 496 | 0, 497 | 1, 498 | 5.011, 499 | 0, 500 | 5.056, 501 | 1, 502 | 5.1, 503 | 1, 504 | 1, 505 | 5.144, 506 | 1, 507 | 5.189, 508 | 0, 509 | 5.233, 510 | 0, 511 | 1, 512 | 5.278, 513 | 0, 514 | 5.322, 515 | 1, 516 | 5.367, 517 | 1, 518 | 0, 519 | 6.667, 520 | 1 521 | ] 522 | }, 523 | { 524 | "Target": "Parameter", 525 | "Id": "ParamEyeBallX", 526 | "Segments": [ 527 | 0, 528 | 0, 529 | 0, 530 | 1.033, 531 | 0, 532 | 1, 533 | 1.3, 534 | 0, 535 | 1.567, 536 | -1, 537 | 1.833, 538 | -1, 539 | 0, 540 | 6.667, 541 | -1 542 | ] 543 | }, 544 | { 545 | "Target": "Parameter", 546 | "Id": "ParamEyeBallY", 547 | "Segments": [ 548 | 0, 549 | -0.1, 550 | 0, 551 | 1.033, 552 | -0.1, 553 | 1, 554 | 1.3, 555 | -0.1, 556 | 1.567, 557 | 1, 558 | 1.833, 559 | 1, 560 | 0, 561 | 6.667, 562 | 1 563 | ] 564 | }, 565 | { 566 | "Target": "Parameter", 567 | "Id": "ParamBrowLY", 568 | "Segments": [ 569 | 0, 570 | 0, 571 | 0, 572 | 6.667, 573 | 0 574 | ] 575 | }, 576 | { 577 | "Target": "Parameter", 578 | "Id": "ParamBrowRY", 579 | "Segments": [ 580 | 0, 581 | 0, 582 | 0, 583 | 6.667, 584 | 0 585 | ] 586 | }, 587 | { 588 | "Target": "Parameter", 589 | "Id": "ParamBrowLX", 590 | "Segments": [ 591 | 0, 592 | 0, 593 | 0, 594 | 6.667, 595 | 0 596 | ] 597 | }, 598 | { 599 | "Target": "Parameter", 600 | "Id": "ParamBrowRX", 601 | "Segments": [ 602 | 0, 603 | 0, 604 | 0, 605 | 6.667, 606 | 0 607 | ] 608 | }, 609 | { 610 | "Target": "Parameter", 611 | "Id": "ParamBrowLAngle", 612 | "Segments": [ 613 | 0, 614 | 0.1, 615 | 1, 616 | 0.611, 617 | 0.1, 618 | 1.222, 619 | 0.4, 620 | 1.833, 621 | 0.4, 622 | 0, 623 | 6.667, 624 | 0.4 625 | ] 626 | }, 627 | { 628 | "Target": "Parameter", 629 | "Id": "ParamBrowRAngle", 630 | "Segments": [ 631 | 0, 632 | 0, 633 | 1, 634 | 0.611, 635 | 0, 636 | 1.222, 637 | 0.4, 638 | 1.833, 639 | 0.4, 640 | 0, 641 | 6.667, 642 | 0.4 643 | ] 644 | }, 645 | { 646 | "Target": "Parameter", 647 | "Id": "ParamBrowRForm", 648 | "Segments": [ 649 | 0, 650 | 0, 651 | 1, 652 | 0.611, 653 | 0, 654 | 1.222, 655 | -0.6, 656 | 1.833, 657 | -0.6, 658 | 0, 659 | 6.667, 660 | -0.6 661 | ] 662 | }, 663 | { 664 | "Target": "Parameter", 665 | "Id": "ParamBrowLForm", 666 | "Segments": [ 667 | 0, 668 | 0, 669 | 1, 670 | 0.611, 671 | 0, 672 | 1.222, 673 | -0.4, 674 | 1.833, 675 | -0.4, 676 | 0, 677 | 6.667, 678 | -0.4 679 | ] 680 | }, 681 | { 682 | "Target": "Parameter", 683 | "Id": "ParamMouthForm", 684 | "Segments": [ 685 | 0, 686 | 0.1, 687 | 0, 688 | 1.267, 689 | 0.1, 690 | 1, 691 | 1.389, 692 | 0.1, 693 | 1.511, 694 | -0.5, 695 | 1.633, 696 | -0.5, 697 | 1, 698 | 1.656, 699 | -0.5, 700 | 1.678, 701 | -0.047, 702 | 1.7, 703 | 0, 704 | 1, 705 | 1.744, 706 | 0.095, 707 | 1.789, 708 | 0.1, 709 | 1.833, 710 | 0.1, 711 | 1, 712 | 1.9, 713 | 0.1, 714 | 1.967, 715 | -0.3, 716 | 2.033, 717 | -0.3, 718 | 1, 719 | 2.1, 720 | -0.3, 721 | 2.167, 722 | 0.4, 723 | 2.233, 724 | 0.4, 725 | 1, 726 | 2.322, 727 | 0.4, 728 | 2.411, 729 | 0, 730 | 2.5, 731 | 0, 732 | 1, 733 | 2.578, 734 | 0, 735 | 2.656, 736 | 0.1, 737 | 2.733, 738 | 0.1, 739 | 1, 740 | 2.811, 741 | 0.1, 742 | 2.889, 743 | 0, 744 | 2.967, 745 | 0, 746 | 1, 747 | 3.056, 748 | 0, 749 | 3.144, 750 | 0.2, 751 | 3.233, 752 | 0.2, 753 | 1, 754 | 3.311, 755 | 0.2, 756 | 3.389, 757 | 0.196, 758 | 3.467, 759 | 0.1, 760 | 1, 761 | 3.578, 762 | -0.038, 763 | 3.689, 764 | -0.2, 765 | 3.8, 766 | -0.2, 767 | 1, 768 | 4.389, 769 | -0.2, 770 | 4.978, 771 | 0.3, 772 | 5.567, 773 | 0.3, 774 | 0, 775 | 6.667, 776 | 0.3 777 | ] 778 | }, 779 | { 780 | "Target": "Parameter", 781 | "Id": "ParamMouthOpenY", 782 | "Segments": [ 783 | 0, 784 | 0, 785 | 0, 786 | 1.267, 787 | 0, 788 | 1, 789 | 1.389, 790 | 0, 791 | 1.511, 792 | 0.7, 793 | 1.633, 794 | 0.7, 795 | 1, 796 | 1.656, 797 | 0.7, 798 | 1.678, 799 | 0, 800 | 1.7, 801 | 0, 802 | 1, 803 | 1.744, 804 | 0, 805 | 1.789, 806 | 0.7, 807 | 1.833, 808 | 0.7, 809 | 1, 810 | 1.9, 811 | 0.7, 812 | 1.967, 813 | 0.707, 814 | 2.033, 815 | 0.6, 816 | 1, 817 | 2.1, 818 | 0.493, 819 | 2.167, 820 | 0.2, 821 | 2.233, 822 | 0.2, 823 | 1, 824 | 2.322, 825 | 0.2, 826 | 2.411, 827 | 0.6, 828 | 2.5, 829 | 0.6, 830 | 1, 831 | 2.578, 832 | 0.6, 833 | 2.656, 834 | 0.4, 835 | 2.733, 836 | 0.4, 837 | 1, 838 | 2.811, 839 | 0.4, 840 | 2.889, 841 | 0.6, 842 | 2.967, 843 | 0.6, 844 | 1, 845 | 3.056, 846 | 0.6, 847 | 3.144, 848 | 0.4, 849 | 3.233, 850 | 0.4, 851 | 1, 852 | 3.311, 853 | 0.4, 854 | 3.389, 855 | 0.5, 856 | 3.467, 857 | 0.5, 858 | 1, 859 | 3.578, 860 | 0.5, 861 | 3.689, 862 | 0, 863 | 3.8, 864 | 0, 865 | 1, 866 | 4.389, 867 | 0, 868 | 4.978, 869 | 0, 870 | 5.567, 871 | 0, 872 | 0, 873 | 6.667, 874 | 0 875 | ] 876 | }, 877 | { 878 | "Target": "Parameter", 879 | "Id": "ParamCheek", 880 | "Segments": [ 881 | 0, 882 | 0, 883 | 0, 884 | 1.067, 885 | 0, 886 | 1, 887 | 1.333, 888 | 0, 889 | 1.6, 890 | 1, 891 | 1.867, 892 | 1, 893 | 0, 894 | 6.667, 895 | 1 896 | ] 897 | }, 898 | { 899 | "Target": "Parameter", 900 | "Id": "Param30", 901 | "Segments": [ 902 | 0, 903 | 0, 904 | 1, 905 | 0.322, 906 | 0, 907 | 0.644, 908 | -16, 909 | 0.967, 910 | -16, 911 | 1, 912 | 1.3, 913 | -16, 914 | 1.633, 915 | 28, 916 | 1.967, 917 | 28, 918 | 0, 919 | 6.667, 920 | 28 921 | ] 922 | } 923 | ] 924 | } -------------------------------------------------------------------------------- /res/live2d/models/Diana/motions/Diana_tap10.motion3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 3, 3 | "Meta": { 4 | "Duration": 4.4, 5 | "Fps": 30.0, 6 | "Loop": true, 7 | "AreBeziersRestricted": true, 8 | "CurveCount": 9, 9 | "TotalSegmentCount": 43, 10 | "TotalPointCount": 102, 11 | "UserDataCount": 0, 12 | "TotalUserDataSize": 0 13 | }, 14 | "Curves": [ 15 | { 16 | "Target": "Parameter", 17 | "Id": "Param2", 18 | "Segments": [ 19 | 0, 20 | -30, 21 | 0, 22 | 1.1, 23 | -30, 24 | 1, 25 | 1.3, 26 | -30, 27 | 1.5, 28 | 30, 29 | 1.7, 30 | 30, 31 | 1, 32 | 2.389, 33 | 30, 34 | 3.078, 35 | 30, 36 | 3.767, 37 | 30, 38 | 1, 39 | 3.9, 40 | 30, 41 | 4.033, 42 | -30, 43 | 4.167, 44 | -30, 45 | 0, 46 | 4.4, 47 | -30 48 | ] 49 | }, 50 | { 51 | "Target": "Parameter", 52 | "Id": "ParamAngleX", 53 | "Segments": [ 54 | 0, 55 | 0, 56 | 0, 57 | 1.1, 58 | 0, 59 | 1, 60 | 1.333, 61 | 0, 62 | 1.567, 63 | -1, 64 | 1.8, 65 | -1, 66 | 1, 67 | 2.567, 68 | -1, 69 | 3.333, 70 | 0, 71 | 4.1, 72 | 0, 73 | 0, 74 | 4.4, 75 | 0 76 | ] 77 | }, 78 | { 79 | "Target": "Parameter", 80 | "Id": "ParamAngleY", 81 | "Segments": [ 82 | 0, 83 | 0, 84 | 0, 85 | 1.1, 86 | 0, 87 | 1, 88 | 1.333, 89 | 0, 90 | 1.567, 91 | 4, 92 | 1.8, 93 | 4, 94 | 1, 95 | 2.567, 96 | 4, 97 | 3.333, 98 | 0, 99 | 4.1, 100 | 0, 101 | 0, 102 | 4.4, 103 | 0 104 | ] 105 | }, 106 | { 107 | "Target": "Parameter", 108 | "Id": "ParamEyeLOpen", 109 | "Segments": [ 110 | 0, 111 | 1, 112 | 0, 113 | 1.1, 114 | 1, 115 | 1, 116 | 1.333, 117 | 1, 118 | 1.567, 119 | 0, 120 | 1.8, 121 | 0, 122 | 1, 123 | 2.467, 124 | 0, 125 | 3.133, 126 | 0, 127 | 3.8, 128 | 0, 129 | 1, 130 | 3.944, 131 | 0, 132 | 4.089, 133 | 1, 134 | 4.233, 135 | 1, 136 | 0, 137 | 4.4, 138 | 1 139 | ] 140 | }, 141 | { 142 | "Target": "Parameter", 143 | "Id": "ParamEyeLSmile", 144 | "Segments": [ 145 | 0, 146 | 0, 147 | 0, 148 | 1.1, 149 | 0, 150 | 1, 151 | 1.333, 152 | 0, 153 | 1.567, 154 | 1, 155 | 1.8, 156 | 1, 157 | 1, 158 | 2.467, 159 | 1, 160 | 3.133, 161 | 1, 162 | 3.8, 163 | 1, 164 | 1, 165 | 3.944, 166 | 1, 167 | 4.089, 168 | 0, 169 | 4.233, 170 | 0, 171 | 0, 172 | 4.4, 173 | 0 174 | ] 175 | }, 176 | { 177 | "Target": "Parameter", 178 | "Id": "ParamEyeROpen", 179 | "Segments": [ 180 | 0, 181 | 1, 182 | 0, 183 | 1.1, 184 | 1, 185 | 1, 186 | 1.333, 187 | 1, 188 | 1.567, 189 | 0, 190 | 1.8, 191 | 0, 192 | 1, 193 | 2.467, 194 | 0, 195 | 3.133, 196 | 0, 197 | 3.8, 198 | 0, 199 | 1, 200 | 3.944, 201 | 0, 202 | 4.089, 203 | 1, 204 | 4.233, 205 | 1, 206 | 0, 207 | 4.4, 208 | 1 209 | ] 210 | }, 211 | { 212 | "Target": "Parameter", 213 | "Id": "ParamEyeRSmile", 214 | "Segments": [ 215 | 0, 216 | 0, 217 | 0, 218 | 1.1, 219 | 0, 220 | 1, 221 | 1.333, 222 | 0, 223 | 1.567, 224 | 1, 225 | 1.8, 226 | 1, 227 | 1, 228 | 2.467, 229 | 1, 230 | 3.133, 231 | 1, 232 | 3.8, 233 | 1, 234 | 1, 235 | 3.944, 236 | 1, 237 | 4.089, 238 | 0, 239 | 4.233, 240 | 0, 241 | 0, 242 | 4.4, 243 | 0 244 | ] 245 | }, 246 | { 247 | "Target": "Parameter", 248 | "Id": "ParamMouthForm", 249 | "Segments": [ 250 | 0, 251 | -0.2, 252 | 0, 253 | 1.1, 254 | -0.2, 255 | 1, 256 | 1.311, 257 | -0.2, 258 | 1.522, 259 | 0.3, 260 | 1.733, 261 | 0.3, 262 | 1, 263 | 2.444, 264 | 0.3, 265 | 3.156, 266 | 0.3, 267 | 3.867, 268 | 0.3, 269 | 1, 270 | 4.022, 271 | 0.3, 272 | 4.178, 273 | -0.2, 274 | 4.333, 275 | -0.2, 276 | 0, 277 | 4.4, 278 | -0.2 279 | ] 280 | }, 281 | { 282 | "Target": "Parameter", 283 | "Id": "ParamMouthOpenY", 284 | "Segments": [ 285 | 0, 286 | 0, 287 | 0, 288 | 1.1, 289 | 0, 290 | 1, 291 | 1.311, 292 | 0, 293 | 1.522, 294 | 1, 295 | 1.733, 296 | 1, 297 | 1, 298 | 2.444, 299 | 1, 300 | 3.156, 301 | 1, 302 | 3.867, 303 | 1, 304 | 1, 305 | 4.022, 306 | 1, 307 | 4.178, 308 | 0, 309 | 4.333, 310 | 0, 311 | 0, 312 | 4.4, 313 | 0 314 | ] 315 | } 316 | ] 317 | } -------------------------------------------------------------------------------- /res/live2d/models/Diana/raw.ex.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "STM_1_0", 3 | "name": "嘉然BY木果", 4 | "id": "1618880670036", 5 | "encrypt": "true", 6 | "version": "1.0", 7 | "list": [{ 8 | "id": "", 9 | "character": "character", 10 | "avatar": "4a301072dec6b6a49050e5b294cd7983", 11 | "costume": [{ 12 | "name": "costume", 13 | "path": "39561a673b6fe68918affd77d3ad8ae2.bin3" 14 | }] 15 | }] 16 | } -------------------------------------------------------------------------------- /res/live2d/models/Diana/raw.model3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Version": 3, 3 | "FileReferences": { 4 | "Moc": "8c4420bd232902f08f41b59bbc36462f.bin3", 5 | "Textures": ["4df2dbd71a468fc2f91b62afcb63f994.bin3"], 6 | "Physics": "2b5fa038da3354fd73a58456408f27e9.bin3", 7 | "PhysicsV2": { 8 | "File": "2b5fa038da3354fd73a58456408f27e9.bin3" 9 | }, 10 | "Motions": { 11 | "Idle": [{ 12 | "File": "8251a6de2a03ea12eaf8c1f879d759b9.bin3" 13 | }], 14 | "Tap生气 -领结": [{ 15 | "File": "18624d01175dda6605c3eafa341bac02.bin3", 16 | "Text": "嘉心糖屁用没有", 17 | "TextDelay": 2000, 18 | "TextDuration": 3000 19 | }], 20 | "Tap= = 左蝴蝶结": [{ 21 | "File": "be67f42e9c965290406d52b64fb878bd.bin3", 22 | "Text": "有人急了,但我不说是谁~", 23 | "TextDelay": 1000, 24 | "TextDuration": 4000 25 | }], 26 | "Tap笑- 脸": [{ 27 | "File": "d1cf83c4f56a2d02a8f0a3ae2f46028f.bin3", 28 | "Text": "hi!嘉心糖", 29 | "TextDelay": 2200, 30 | "TextDuration": 2300 31 | }], 32 | "Tap哭 -眼角": [{ 33 | "File": "721720d60a83a9f4b7f2b1065b49d6c8.bin3", 34 | "Text": "呜呜...呜呜呜....", 35 | "TextDelay": 3200, 36 | "TextDuration": 4000 37 | }], 38 | "Shake": [{ 39 | "File": "a475c108ed9162233c132446a237c700.bin3", 40 | "Text": "别摇啦!", 41 | "TextDelay": 1000, 42 | "TextDuration": 2000 43 | }], 44 | "Tap害羞-中间刘海": [{ 45 | "File": "f6123a070d9897ef1e6475e740b13e08.bin3", 46 | "Text": "想然然了没有呀~", 47 | "TextDelay": 1500, 48 | "TextDuration": 3000 49 | }], 50 | "Tap抱阿草-左手": [{ 51 | "File": "e31f07da7854f78c21a271ada7416412.bin3", 52 | "Text": "阿草好软呀~", 53 | "TextDelay": 3000, 54 | "TextDuration": 2500 55 | }], 56 | "Tap摇头- 身体": [{ 57 | "File": "a475c108ed9162233c132446a237c700.bin3", 58 | "Text": "不要再戳啦!好痒!", 59 | "TextDelay": 800, 60 | "TextDuration": 2500 61 | }], 62 | "Tap耳朵-发卡": [{ 63 | "File": "fa1918fc04af73a1a08aaac6e2556fbb.bin3", 64 | "Text": "嗷呜~~~", 65 | "TextDelay": 1500, 66 | "TextDuration": 3000 67 | }], 68 | "Tap打瞌睡- 呆毛": [{ 69 | "File": "d9be6b6f1b3bc23ef6539025acedd923.bin3", 70 | "Text": "啊", 71 | "TextDelay": 7500, 72 | "TextDuration": 800 73 | }], 74 | "Leave": [{ 75 | "File": "d9be6b6f1b3bc23ef6539025acedd923.bin3", 76 | "Text": "zzZ。。。", 77 | "TextDelay": 4000, 78 | "TextDuration": 4000 79 | }], 80 | "Tap左头发": [{ 81 | "File": "ec36cfef1f589764902d770d0cca2e9e.bin3" 82 | }], 83 | "Tap右头发": [{ 84 | "File": "0aeecad899bb18f93a519617dfe76f26.bin3", 85 | "Text": "哇!好吃的!", 86 | "TextDelay": 500, 87 | "TextDuration": 3000 88 | }] 89 | } 90 | }, 91 | "Controllers": { 92 | "ParamHit": {}, 93 | "ParamLoop": {}, 94 | "KeyTrigger": {}, 95 | "EyeBlink": { 96 | "MinInterval": 500, 97 | "MaxInterval": 6000, 98 | "Enabled": true 99 | }, 100 | "LipSync": { 101 | "Gain": 5.0 102 | }, 103 | "MouseTracking": { 104 | "SmoothTime": 0.15, 105 | "Items": [{ 106 | "Id": "ParamBodyAngleX", 107 | "Min": -10.0, 108 | "Max": 10.0, 109 | "DefaultValue": 0.0, 110 | "Weight": 0.76343286, 111 | "BlendMode": 1, 112 | "Input": 1 113 | }, { 114 | "Id": "ParamAngleX", 115 | "Min": -30.0, 116 | "Max": 30.0, 117 | "DefaultValue": 0.0, 118 | "Weight": 0.798328757, 119 | "BlendMode": 1, 120 | "Input": 1 121 | }, { 122 | "Id": "ParamBodyAngleZ", 123 | "Min": -10.0, 124 | "Max": 10.0, 125 | "DefaultValue": 0.0, 126 | "Weight": 0.6260679, 127 | "BlendMode": 1, 128 | "Input": 1 129 | }, { 130 | "Id": "ParamBodyAngleY", 131 | "Min": -10.0, 132 | "Max": 10.0, 133 | "DefaultValue": 0.0, 134 | "Weight": 0.8907613, 135 | "BlendMode": 1, 136 | "Axis": 1, 137 | "Input": 2 138 | }, { 139 | "Id": "ParamAngleY", 140 | "Min": -30.0, 141 | "Max": 30.0, 142 | "DefaultValue": 0.0, 143 | "Weight": 0.7521123, 144 | "BlendMode": 1, 145 | "Axis": 1, 146 | "Input": 2 147 | }], 148 | "Enabled": true 149 | }, 150 | "AutoBreath": { 151 | "Enabled": true 152 | }, 153 | "ExtraMotion": { 154 | "Enabled": true 155 | }, 156 | "Accelerometer": { 157 | "Enabled": true 158 | }, 159 | "Microphone": {}, 160 | "Transform": {}, 161 | "FaceTracking": { 162 | "Enabled": true 163 | }, 164 | "ParamValue": {}, 165 | "PartOpacity": {}, 166 | "ArtmeshOpacity": {}, 167 | "ArtmeshColor": {}, 168 | "ArtmeshCulling": { 169 | "DefaultMode": 0 170 | }, 171 | "IntimacySystem": {} 172 | }, 173 | "HitAreas": [{ 174 | "Name": "= = 左蝴蝶结", 175 | "Id": "ArtMesh15" 176 | }, { 177 | "Name": "笑- 脸", 178 | "Id": "ArtMesh51" 179 | }, { 180 | "Name": "哭 -眼角", 181 | "Id": "ArtMesh48" 182 | }, { 183 | "Name": "生气 -领结", 184 | "Id": "ArtMesh56" 185 | }, { 186 | "Name": "害羞-中间刘海", 187 | "Id": "ArtMesh10" 188 | }, { 189 | "Name": "抱阿草-左手", 190 | "Id": "L4" 191 | }, { 192 | "Name": "打瞌睡- 呆毛", 193 | "Id": "ArtMesh9" 194 | }, { 195 | "Name": "耳朵-发卡", 196 | "Id": "L3" 197 | }, { 198 | "Name": "摇头- 身体", 199 | "Id": "jiaran" 200 | }, { 201 | "Name": "左头发", 202 | "Id": "L5" 203 | }, { 204 | "Name": "右头发", 205 | "Id": "R5" 206 | }], 207 | "Options": { 208 | "TexFixed": true 209 | } 210 | } -------------------------------------------------------------------------------- /res/live2d/models/Diana/raw.preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheSecondAkari/vscode-live2d/1e7a4fc4e610ec0e76ee6035e25fc572d048eb85/res/live2d/models/Diana/raw.preview.png -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | // The module 'vscode' contains the VS Code extensibility API 2 | // Import the module and reference it with the alias vscode in your code below 3 | import * as vscode from 'vscode'; 4 | import {activateLive2d} from './live2dView'; 5 | import {activateModify} from './live2dModify' 6 | 7 | // this method is called when your extension is activated 8 | // your extension is activated the very first time the command is executed 9 | export function activate(context: vscode.ExtensionContext) { 10 | 11 | // 注册live2d webView 12 | activateLive2d(context); 13 | 14 | // 注册修改文件操作 15 | activateModify(context); 16 | 17 | } 18 | 19 | // this method is called when your extension is deactivated 20 | export function deactivate() {} 21 | -------------------------------------------------------------------------------- /src/live2dModify/Dom.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import * as path from 'path'; 3 | import * as fs from 'fs'; 4 | import FileType from './FileType'; 5 | import vsHelp from './vsHelp'; 6 | import getNewContent from './getJs'; 7 | import { 8 | Uri, 9 | window, 10 | InputBoxOptions, 11 | commands, 12 | env, 13 | } from 'vscode'; 14 | 15 | export class Dom { 16 | //当前用户配置 17 | private config: any; 18 | //配置名称 19 | private configName: string; 20 | //要修改的文件路径 21 | private filePath: string; 22 | //插件版本号 23 | private version: string; 24 | //插件名称 25 | private extName: string; 26 | 27 | 28 | //初始化参数 29 | public constructor( 30 | configName: string, 31 | filePath: string, 32 | version: string, 33 | extName: string, 34 | ) { 35 | this.configName = configName; 36 | this.filePath = filePath; 37 | this.version = version; 38 | this.extName = extName; 39 | 40 | this.config = vscode.workspace.getConfiguration(this.configName); 41 | let firstload = this.checkFirstload(); // 是否初次加载插件 42 | let fileType = this.getFileType(); // 文件目前状态 43 | // 如果是第一次加载插件,或者旧版本 44 | if (firstload || fileType === FileType.isOld) { 45 | this.generateResources(); 46 | } 47 | } 48 | 49 | /** 50 | * 生成资源文件到特定目录--live2d的内容,增加 js 文件处理代码 51 | * 52 | * @public 53 | * @param {boolean} [notice] 是否需要结果通知 54 | * @returns {void} 55 | */ 56 | public generateResources(notice?: boolean): void { 57 | try { 58 | const base = env.appRoot; 59 | copy(path.join(__dirname, '../../res/'), path.join(base,'out', 'vs', 'code', 'electron-sandbox', 'workbench')); 60 | this.install(true); 61 | notice && vsHelp.showInfo('资源文件配置成功'); 62 | } catch (e) { 63 | notice && vsHelp.showInfo('资源文件配置出错:' + e.toString()); 64 | } 65 | } 66 | 67 | /** 68 | * 移除该插件所有依赖 69 | * 70 | * @public 71 | * @param {boolean} [notice] 是否需要结果通知 72 | * @returns {void} 73 | */ 74 | public removeResources(notice?: boolean): void { 75 | try { 76 | const base = env.appRoot; 77 | removeFiles(path.join(base,'out', 'vs', 'code', 'electron-sandbox', 'workbench', 'live2d')); 78 | this.uninstall(); 79 | notice && vsHelp.showInfoRestart('资源文件移除成功'); 80 | } catch (e) { 81 | notice && vsHelp.showInfo('资源文件移除出错:' + e.toString()); 82 | } 83 | } 84 | 85 | /** 86 | * 安装插件,hack 87 | * 88 | * @private 89 | * @param {boolean} [refresh] 需要更新 90 | * @returns {void} 91 | */ 92 | public install(refresh?: boolean): void { 93 | 94 | let lastConfig = this.config; // 之前的配置 95 | let config = vscode.workspace.getConfiguration(this.configName); // 当前用户配置 96 | 97 | 98 | // 1.如果配置文件改变到时候,当前插件配置没有改变,则返回 99 | if (!refresh && JSON.stringify(lastConfig) === JSON.stringify(config)) { 100 | return; 101 | } 102 | 103 | // 之后操作有两种:1.初次加载 2.配置文件改变 104 | 105 | // 2.两次配置均为,未启动插件 106 | if (!lastConfig.enabled && !config.enabled) { 107 | return; 108 | } 109 | 110 | // 3.保存当前配置 111 | this.config = config; // 更新配置 112 | 113 | // 4.如果关闭插件 114 | if (!config.enabled) { 115 | this.uninstall(); 116 | vsHelp.showInfoRestart(this.extName + '已关闭插件,请重新启动!'); 117 | return; 118 | } 119 | 120 | // 5.hack 样式 121 | 122 | // 自定义的样式内容 123 | let content = getNewContent(config, this.extName, this.version).replace(/\s*$/, ''); // 去除末尾空白 124 | 125 | // 添加代码到文件中,并尝试删除原来已经添加的 126 | let newContent = this.getContent(); 127 | newContent = this.clearJSContent(newContent); 128 | newContent += content; 129 | 130 | this.saveContent(newContent); 131 | vsHelp.showInfoRestart(this.extName + ' 已更新配置,请重新启动!'); 132 | 133 | } 134 | 135 | 136 | /** 137 | * 获取文件内容 138 | * @var mixed 139 | */ 140 | private getContent(): string { 141 | return fs.readFileSync(this.filePath, 'utf-8'); 142 | } 143 | 144 | /** 145 | * 设置文件内容 146 | * 147 | * @private 148 | * @param {string} content 149 | */ 150 | private saveContent(content: string): void { 151 | fs.writeFileSync(this.filePath, content, 'utf-8'); 152 | } 153 | 154 | /** 155 | * 清理已经添加的代码 156 | * 157 | * @private 158 | * @param {string} content 159 | * @returns {string} 160 | */ 161 | private clearJSContent(content: string): string { 162 | var re = new RegExp("\\/\\*ext-" + this.extName + "-start\\*\\/[\\s\\S]*?\\/\\*ext-" + this.extName + "-end\\*" + "\\/", "g"); 163 | content = content.replace(re, ''); 164 | content = content.replace(/\s*$/, ''); 165 | content += '\n' 166 | return content; 167 | } 168 | 169 | /** 170 | * 卸载 171 | * 172 | * @private 173 | */ 174 | private uninstall(): boolean { 175 | try { 176 | let content = this.getContent(); 177 | content = this.clearJSContent(content); 178 | this.saveContent(content); 179 | return true; 180 | } 181 | catch (ex) { 182 | return false; 183 | } 184 | } 185 | 186 | /** 187 | * 检测是否初次加载,并在初次加载的时候提示用户 188 | * 189 | * @private 190 | * @returns {boolean} 是否初次加载 191 | */ 192 | private checkFirstload(): boolean { 193 | const configPath = path.join(__dirname, '../../res/live2d/config.json'); 194 | let info: { firstload: boolean } = JSON.parse(fs.readFileSync(configPath, 'utf-8')); 195 | 196 | if (info.firstload) { 197 | // 提示 198 | vsHelp.showInfo('插件: ' + this.extName + '已启动! '); 199 | // 标识插件已启动过 200 | info.firstload = false; 201 | fs.writeFileSync(configPath, JSON.stringify(info, null, ' '), 'utf-8'); 202 | 203 | return true; 204 | } 205 | 206 | return false; 207 | } 208 | 209 | /** 210 | * 获取文件状态 211 | * 212 | * @private 213 | * @returns {FileType} 214 | */ 215 | private getFileType(): FileType { 216 | let jsContent = this.getContent(); 217 | // 未 hack 过 218 | let ifUnInstall: boolean = !~jsContent.indexOf(`ext.${this.extName}.ver`); 219 | 220 | if (ifUnInstall) { 221 | return FileType.empty; 222 | } 223 | 224 | // hack 过的旧版本 225 | let version = jsContent.match(new RegExp(`ext\\.${this.extName}\\.ver\\.(\\d+\\.\\d+\\.\\d+)`)); 226 | 227 | if (version && this.version > version[1]) { 228 | return FileType.isOld; 229 | } 230 | 231 | // hack 过的新版本 232 | return FileType.isNew; 233 | } 234 | 235 | } 236 | 237 | function copy(src: string, dst: string) { 238 | let paths = fs.readdirSync(src); //同步读取当前目录 239 | paths.forEach(function (path) { 240 | var _src = src + '/' + path; 241 | var _dst = dst + '/' + path; 242 | fs.stat(_src, function (err, stats) { 243 | //stats 该对象 包含文件属性 244 | if (err) { throw err; } 245 | if (stats.isFile()) { 246 | //如果是个文件则拷贝 247 | let readable = fs.createReadStream(_src); //创建读取流 248 | let writable = fs.createWriteStream(_dst); //创建写入流 249 | readable.pipe(writable); 250 | } 251 | else if (stats.isDirectory()) { 252 | //是目录则 递归 253 | checkDirectory(_src, _dst, copy); 254 | } 255 | }); 256 | }); 257 | } 258 | 259 | function checkDirectory(src: string, dst: string, callback?: Function) { 260 | fs.access(dst, fs.constants.F_OK, (err) => { 261 | if (err) { 262 | fs.mkdirSync(dst); 263 | callback && callback(src, dst); 264 | } 265 | else { 266 | callback && callback(src, dst); 267 | } 268 | }); 269 | } 270 | 271 | /** 272 | * 删除文件内容 273 | * 274 | * @private 275 | * @param {string} path 276 | */ 277 | function removeFiles(path: string) { 278 | var files = []; 279 | if (fs.existsSync(path)) { 280 | files = fs.readdirSync(path); 281 | files.forEach(function (file, index) { 282 | var curPath = path + "/" + file; 283 | if (fs.statSync(curPath).isDirectory()) { // recurse 284 | removeFiles(curPath); 285 | } else { // delete file 286 | fs.unlinkSync(curPath); 287 | } 288 | }); 289 | fs.rmdirSync(path); 290 | } 291 | } -------------------------------------------------------------------------------- /src/live2dModify/FileType.ts: -------------------------------------------------------------------------------- 1 | enum FileType { 2 | /** 3 | * 未修改的文件 4 | */ 5 | empty, 6 | /** 7 | * hack 过的旧版本文件 8 | */ 9 | isOld, 10 | /** 11 | * hack 过的新版本的文件 12 | */ 13 | isNew 14 | } 15 | 16 | export default FileType; -------------------------------------------------------------------------------- /src/live2dModify/Main.ts: -------------------------------------------------------------------------------- 1 | 2 | import * as vscode from 'vscode'; 3 | import * as path from 'path'; 4 | import version from './version'; 5 | import { Dom } from './Dom'; 6 | import { 7 | Uri, 8 | window, 9 | InputBoxOptions, 10 | commands, 11 | env, 12 | } from 'vscode'; 13 | 14 | 15 | export class Main { 16 | static Instance?: Dom; 17 | 18 | public static watch(): vscode.Disposable { 19 | const base = env.appRoot; 20 | const filePath = path.join(base,'out','vs', 'code', 'electron-sandbox', 'workbench', 'workbench.js'); 21 | const configName = 'vscode-live2d-asoul'; 22 | const extName = "TheSecondAkari-vscode-live2d"; 23 | let DomApi = new Dom(configName, filePath, version, extName); 24 | Main.Instance = DomApi; 25 | return vscode.workspace.onDidChangeConfiguration(() => DomApi.install()); 26 | } 27 | } -------------------------------------------------------------------------------- /src/live2dModify/getJs.ts: -------------------------------------------------------------------------------- 1 | export default function (config: any, extName: string, version: string): string { 2 | return ` 3 | /*ext-${extName}-start*/ 4 | /*ext.${extName}.ver.${version}*/ 5 | class Live2d { 6 | live2dWrapper = undefined; // live2d html最外层节点div 7 | live2dIframe = undefined; // live2d 的具体 iframe页面 8 | anchorCore = 'br'; // live2d div 定位依赖,初始默认为右下角, 一共有四个情况: tl,tr,bl,br 9 | KEY = 'live2d-asoul-config'; // 用于localstorage存储信息的key 10 | 11 | constructor() { 12 | // 添加postmessage事件监听 13 | const receiveMessage = (event) => { 14 | const origin = event.origin || event.originalEvent.origin; 15 | if (origin !== "vscode-webview://webviewview-vscode-live2d-live2dview" && !origin.startsWith('vscode-webview://')) 16 | return; 17 | const { type, data } = event?.data || {}; 18 | if(type) 19 | switch (type) { 20 | case 'live2d-asoul-openAutoLodash': 21 | this.saveConfig({ autoLodash: true }); 22 | break; 23 | case 'live2d-asoul-closeAutoLodash': 24 | this.saveConfig({ autoLodash: false }); 25 | break; 26 | case 'live2d-asoul-lodash': 27 | this.createLive2d(); 28 | break; 29 | case 'live2d-asoul-close': 30 | this.deleteLive2d(); 31 | break; 32 | case 'live2d-asoul-setAnchor': 33 | this.anchor = data; 34 | break; 35 | case 'live2d-asoul-resetPosition': 36 | this.resetPosition(); 37 | break; 38 | case 'live2d-asoul-saveCurrentConfig': 39 | this.saveCurrentConfig(); 40 | break; 41 | case 'live2d-asoul-saveBackground': 42 | this.saveBackground(); 43 | break; 44 | case 'live2d-asoul-loadBackground': 45 | this.loadBackground(); 46 | break; 47 | case 'live2d-asoul-openBackgroundSetTime': 48 | this.openBackgroundSetTime(data); 49 | break; 50 | case 'live2d-asoul-closeBackgroundSetTime': 51 | this.closeBackgroundSetTime(); 52 | break; 53 | case 'live2d-asoul-modifyBackgroundConfig': 54 | this.modifyBackgroundConfig(data); 55 | break; 56 | case 'live2d-asoul-downloadBackground': 57 | event.source.postMessage({type: 'live2d-asoul-initDownloadBackground', data: this.live2dIframe?.contentWindow?.currentImgs }, origin); 58 | break; 59 | default: 60 | break; 61 | } 62 | } 63 | window.addEventListener('message', receiveMessage, false); 64 | 65 | // 从localstorage中获取配置信息,进行对应处理 66 | const config = this.getConfig(); 67 | if (config.autoLodash === true) 68 | this.createLive2d(); 69 | this.anchor = config.anchor; 70 | } 71 | 72 | get anchor() { 73 | return this.anchorCore; 74 | } 75 | 76 | set anchor(value) { 77 | if (['tl', 'tr', 'bl', 'br'].includes(value)) { 78 | this.anchorCore = value; 79 | this.saveConfig({anchor: value}); 80 | this.resetLocationDependency(this.live2dWrapper, value); // 恢复目标定位依赖 81 | } 82 | } 83 | 84 | // 会进行校验,最多只允许创建一个 85 | createLive2d = () => { 86 | // if (document.getElementById('live2d-wrapper')) 87 | // return; 88 | if (this.live2dWrapper) { 89 | document.body.appendChild(this.live2dWrapper); 90 | return; 91 | } 92 | this.live2dWrapper = document.createElement('div'); 93 | this.live2dWrapper.id = 'live2d-wrapper'; 94 | Object.assign(this.live2dWrapper.style, this.getConfig().style); 95 | // 显示iframe, live2d 96 | const iframe = this.initIframe(); 97 | if (!iframe) 98 | return; 99 | this.live2dIframe = iframe; 100 | this.live2dWrapper.appendChild(iframe); 101 | // 控制按钮 102 | const controlBar = this.initControlBar(this.live2dWrapper); 103 | controlBar && this.live2dWrapper.appendChild(controlBar); 104 | this.addWrapperStyle(); 105 | document.body.appendChild(this.live2dWrapper); 106 | } 107 | 108 | // 只是将 live2dWrapper 整个节点从body移除,依旧存在内存中,因为还存在事件的引用 109 | deleteLive2d = () => { 110 | if (this.live2dWrapper) { 111 | this.live2dWrapper.remove(); 112 | // this.live2dWrapper = undefined; 113 | } 114 | } 115 | 116 | // 外壳wrapper基础样式 117 | addWrapperStyle = () => { 118 | let styleNode = document.createElement('style'); 119 | let styleContent = \` 120 | div#live2d-wrapper { 121 | width: 280px; 122 | height: 300px; 123 | position: fixed; 124 | bottom: 50px; 125 | right: 50px; 126 | z-index: 100; 127 | } 128 | .live2d-wrapper-controller-wrapper { 129 | pointer-events:auto; 130 | position: absolute; 131 | right: 1px; 132 | top: 2px; 133 | display:flex; 134 | opacity: 0; 135 | transition: all 0.2s; 136 | } 137 | div#live2d-wrapper:hover .live2d-wrapper-controller-wrapper { 138 | opacity: 1; 139 | } 140 | .live2d-wrapper-controller-icon { 141 | width:16px; 142 | height:16px; 143 | cursor: pointer; 144 | transition: all 0.3s; 145 | } 146 | .live2d-wrapper-controller-icon:hover { 147 | width:20px; 148 | height:20px; 149 | } 150 | .live2d-wrapper-controller-corner { 151 | width: 10px; 152 | height: 10px; 153 | background-color: #faa; 154 | position: absolute; 155 | } 156 | \`; 157 | styleNode.appendChild(document.createTextNode(styleContent)) 158 | document.head.appendChild(styleNode); 159 | } 160 | 161 | // iframe, 初始化具体live2d的页面 162 | initIframe = () => { 163 | const str = window.location.href; 164 | if (!str.includes('workbench.html')) 165 | return 166 | const iframe = document.createElement('iframe'); 167 | iframe.style.cssText = 'width:100%; height:100%; border:0;'; 168 | iframe.src = str.replace('workbench.html', 'live2d/index.html'); 169 | return iframe; 170 | } 171 | 172 | // 控制图标,三个图标 调整大小,点击穿透,拖拽位置 173 | initControlBar = (container) => { 174 | const controlEles = document.createElement('div'); 175 | controlEles.classList.add("live2d-wrapper-controller-wrapper"); 176 | 177 | const borderIconDiv = document.createElement('div'); 178 | borderIconDiv.title = '调整大小'; 179 | const borderIcon = document.createElement('img'); 180 | borderIcon.src = './live2d/assets/border.png'; 181 | borderIcon.classList.add("live2d-wrapper-controller-icon"); 182 | borderIcon.addEventListener('click', (() => { 183 | let hasBorder = false; 184 | let corners; 185 | return () => { 186 | hasBorder = !hasBorder; 187 | if (hasBorder) 188 | corners = this.addBorderCorner(container, corners); 189 | else 190 | corners.forEach(ele => ele.remove()); 191 | // container.style.border = hasBorder ? 'solid 4px white' : '0'; 192 | } 193 | })()); 194 | borderIconDiv.appendChild(borderIcon); 195 | controlEles.appendChild(borderIconDiv); 196 | 197 | const penetrateIconDiv = document.createElement('div'); 198 | penetrateIconDiv.title = '是否允许点击穿透'; 199 | penetrateIconDiv.style.cssText = 'margin: 0 6px;'; 200 | const penetrateIcon = document.createElement('img'); 201 | penetrateIcon.src = './live2d/assets/pierce.png'; 202 | penetrateIcon.classList.add("live2d-wrapper-controller-icon"); 203 | penetrateIcon.addEventListener('click', (() => { 204 | let isPenetrate = false; 205 | return () => { 206 | isPenetrate = !isPenetrate; 207 | controlEles.style.opacity = isPenetrate ? '1' : ''; 208 | container.style.pointerEvents = isPenetrate ? 'none' : 'auto'; 209 | } 210 | })()); 211 | penetrateIconDiv.appendChild(penetrateIcon); 212 | controlEles.appendChild(penetrateIconDiv); 213 | 214 | const dragIconDiv = document.createElement('div'); 215 | dragIconDiv.title = '鼠标按住拖拽移动'; 216 | const dragIcon = document.createElement('img'); 217 | dragIcon.src = './live2d/assets/pin.png'; 218 | dragIcon.classList.add("live2d-wrapper-controller-icon"); 219 | document.addEventListener("mousedown", e => { 220 | // 这里过滤掉非目标元素 221 | if (e.target !== dragIcon) { 222 | return; 223 | } 224 | const disx = e.pageX - container.offsetLeft;//获取鼠标相对元素距离 225 | const disy = e.pageY - container.offsetTop; 226 | 227 | // 防止鼠标移动到iframe上,使得鼠标移动事件丢失 228 | const iframe = container.getElementsByTagName('iframe')[0]; 229 | iframe && (iframe.style.pointerEvents = 'none'); 230 | 231 | const handleMove = (event) => { 232 | container.style.left = event.pageX - disx + 'px'; 233 | container.style.top = event.pageY - disy + 'px'; 234 | }; 235 | const tempMouseUp = () => { 236 | iframe && (iframe.style.pointerEvents = 'inherit'); 237 | this.resetLocationDependency(container, this.anchor); // 恢复目标定位依赖 238 | document.removeEventListener("mousemove", handleMove); 239 | document.removeEventListener("mouseup", tempMouseUp); 240 | } 241 | document.addEventListener("mousemove", handleMove); 242 | document.addEventListener("mouseup", tempMouseUp); 243 | e.preventDefault();//阻止浏览器的默认事件 244 | }); 245 | dragIconDiv.appendChild(dragIcon); 246 | controlEles.appendChild(dragIconDiv); 247 | 248 | return controlEles; 249 | } 250 | 251 | // 初始化4个角落点,用于后续拖拽缩放大小 252 | initCorner = () => { 253 | // 来4个元素 254 | const eles = Array.from({ length: 4 }).map(() => 255 | document.createElement("div") 256 | ); 257 | eles.forEach(x => x.classList.add("live2d-wrapper-controller-corner")); 258 | // 分别在topleft、topright、bottomleft、bottomright位置 259 | const [tl, tr, bl, br] = eles; 260 | 261 | // 每一个角都移动半个身位 262 | Object.assign(tl.style, { 263 | top: "-5px", 264 | left: "-5px", 265 | cursor: "nw-resize" 266 | }); 267 | Object.assign(tr.style, { 268 | top: "-5px", 269 | cursor: "ne-resize", 270 | right: "-5px" 271 | }); 272 | Object.assign(bl.style, { 273 | bottom: "-5px", 274 | cursor: "sw-resize", 275 | left: "-5px" 276 | }); 277 | Object.assign(br.style, { 278 | bottom: "-5px", 279 | cursor: "se-resize", 280 | right: "-5px" 281 | }); 282 | return { eles }; 283 | } 284 | 285 | // 给4个角落点挂载事件 286 | drag = (ele, container, type) => { 287 | if (!type) 288 | return; 289 | document.addEventListener("mousedown", e => { 290 | // 这里过滤掉非目标元素 291 | if (e.target !== ele) { 292 | return; 293 | } 294 | 295 | const { width, height } = container.getBoundingClientRect(); 296 | 297 | // 固定container元素,以使不同定位角可以拉动, 因为是对角拖拽,所以需要用对角定位 298 | const antiType = (type[0] == 't' ? 'b' : 't') + (type[1] == 'l' ? 'r' : 'l'); 299 | this.resetLocationDependency(container, antiType); 300 | 301 | // 防止鼠标移动到iframe上,使得鼠标移动事件丢失 302 | const iframe = container.getElementsByTagName('iframe')[0]; 303 | iframe && (iframe.style.pointerEvents = 'none'); 304 | 305 | const disx = e.pageX;//获取鼠标相对元素距离 306 | const disy = e.pageY; 307 | 308 | let factorWidth = (type === 'tl' || type === 'bl') ? -1 : 1; 309 | let factorHeight = (type === 'tl' || type === 'tr') ? -1 : 1; 310 | const Live2dResize = (event) => { 311 | const newWidth = width + (event.pageX - disx) * factorWidth; 312 | const newHeight = height + (event.pageY - disy) * factorHeight; 313 | // 最小宽高 314 | if (newWidth >= 75) 315 | container.style.width = newWidth + 'px'; 316 | if (newHeight >= 75) 317 | container.style.height = newHeight + 'px'; 318 | }; 319 | 320 | const tempMouseUp = () => { 321 | iframe && (iframe.style.pointerEvents = 'inherit'); 322 | this.resetLocationDependency(container, this.anchor); // 恢复目标定位依赖 323 | document.removeEventListener("mousemove", Live2dResize); 324 | document.removeEventListener("mouseup", tempMouseUp); 325 | } 326 | document.addEventListener("mousemove", Live2dResize); 327 | document.addEventListener("mouseup", tempMouseUp); 328 | e.preventDefault();//阻止浏览器的默认事件 329 | }); 330 | } 331 | 332 | addBorderCorner = (target, corners) => { 333 | if (!target) 334 | return; 335 | // 获取四个角——eles 336 | if (!corners) { 337 | const { eles } = this.initCorner(); 338 | const [tl, tr, bl, br] = eles; 339 | target.appendChild(tl); 340 | this.drag(tl, target, 'tl'); 341 | target.appendChild(tr); 342 | this.drag(tr, target, 'tr'); 343 | target.appendChild(bl); 344 | this.drag(bl, target, 'bl'); 345 | target.appendChild(br); 346 | this.drag(br, target, 'br'); 347 | return eles; 348 | } 349 | else { 350 | corners.forEach(ele => target.appendChild(ele)); 351 | return corners; 352 | } 353 | } 354 | 355 | // 重置元素对于某个角落的定位, target目标元素 , type定位角落 356 | resetLocationDependency = (target, type) => { 357 | if (target && type) { 358 | const { top, bottom, left, right } = target.getBoundingClientRect(); 359 | 360 | const pageWidth = document.documentElement.clientWidth; 361 | const pageHeight = document.documentElement.clientHeight; 362 | 363 | if (type === 'tl') { 364 | target.style.top = top + 'px'; 365 | target.style.left = left + 'px'; 366 | target.style.right = ''; 367 | target.style.bottom = ''; 368 | } 369 | else if (type === 'tr') { 370 | target.style.top = top + 'px'; 371 | target.style.left = ''; 372 | target.style.right = pageWidth - right + 'px'; 373 | target.style.bottom = ''; 374 | } 375 | else if (type === 'bl') { 376 | target.style.top = ''; 377 | target.style.left = left + 'px'; 378 | target.style.right = ''; 379 | target.style.bottom = pageHeight - bottom + 'px'; 380 | 381 | } 382 | else if (type === 'br') { 383 | target.style.top = ''; 384 | target.style.left = ''; 385 | target.style.right = pageWidth - right + 'px'; 386 | target.style.bottom = pageHeight - bottom + 'px'; 387 | } 388 | } 389 | } 390 | 391 | resetPosition = () => { 392 | if (this.live2dWrapper) { 393 | const style = this.live2dWrapper.style; 394 | style.top = ''; 395 | style.right = ''; 396 | style.bottom = ''; 397 | style.left = ''; 398 | style.width = ''; 399 | style.height = ''; 400 | } 401 | } 402 | 403 | saveCurrentConfig = () => { 404 | if (this.live2dWrapper) { 405 | const { top, right, bottom, left, width, height } = this.live2dWrapper.style; 406 | const style = { top, right, bottom, left, width, height }; 407 | this.saveConfig({ style }) 408 | } 409 | } 410 | 411 | saveConfig = (newData) => { 412 | const str = localStorage.getItem(this.KEY); 413 | const data = str ? JSON.parse(str) : { autoLodash: false, anchor: 'br', style: {} }; 414 | localStorage.setItem(this.KEY, JSON.stringify({ ...data, ...newData })); 415 | } 416 | 417 | getConfig = () => { 418 | const str = localStorage.getItem(this.KEY); 419 | return str ? JSON.parse(str) : { autoLodash: false, anchor: 'br', style: {} }; 420 | } 421 | 422 | saveBackground = () => { 423 | const fn = this.live2dIframe?.contentWindow?.saveBackground; 424 | fn && fn(); 425 | } 426 | 427 | loadBackground = () => { 428 | const fn = this.live2dIframe?.contentWindow?.loadBackground; 429 | fn && fn(); 430 | } 431 | 432 | openBackgroundSetTime = (time) => { 433 | const fn = this.live2dIframe?.contentWindow?.openBackgroundSetTime; 434 | fn && fn(time); 435 | } 436 | 437 | closeBackgroundSetTime = () => { 438 | const fn = this.live2dIframe?.contentWindow?.closeBackgroundSetTime; 439 | fn && fn(); 440 | } 441 | 442 | modifyBackgroundConfig = (config) => { 443 | const fn = this.live2dIframe?.contentWindow?.modifyBackgroundConfig; 444 | fn && fn(config); 445 | } 446 | } 447 | 448 | let live2dInstance = new Live2d(); 449 | 450 | /*ext-${extName}-end*/ 451 | `; 452 | } -------------------------------------------------------------------------------- /src/live2dModify/index.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | import { Main } from './Main'; 3 | 4 | export function activateModify(context: vscode.ExtensionContext) { 5 | context.subscriptions.push(Main.watch()); 6 | } 7 | 8 | export function deactivateModify() { } -------------------------------------------------------------------------------- /src/live2dModify/uninstall.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as fs from 'fs'; 3 | import { 4 | Uri, 5 | window, 6 | InputBoxOptions, 7 | commands, 8 | env, 9 | } from 'vscode'; 10 | 11 | const base = process.cwd(); 12 | // 文件路径 13 | const filePath = path.join(base, 'resources', 'app', 'out', 'vs', 'code', 'electron-sandbox', 'workbench', 'workbench.js'); 14 | const extName = "vscode-live2d"; 15 | 16 | 17 | //执行清理 18 | main(); 19 | 20 | //清理内容 21 | function main() { 22 | try { 23 | let content = getContent(); 24 | const base = env.appRoot; 25 | content = clearCssContent(content); 26 | saveContent(content); 27 | removeFiles(path.join(base,'out', 'vs', 'code', 'electron-sandbox', 'workbench', 'live2d')); 28 | return true; 29 | } 30 | catch (ex) { 31 | return false; 32 | } 33 | } 34 | 35 | 36 | /** 37 | * 获取文件内容 38 | * @var mixed 39 | */ 40 | function getContent(): string { 41 | return fs.readFileSync(filePath, 'utf-8'); 42 | } 43 | 44 | 45 | /** 46 | * 清理已经添加的代码 47 | * 48 | * @private 49 | * @param {string} content 50 | * @returns {string} 51 | */ 52 | function clearCssContent(content: string): string { 53 | var re = new RegExp("\\/\\*ext-" + extName + "-start\\*\\/[\\s\\S]*?\\/\\*ext-" + extName + "-end\\*" + "\\/", "g"); 54 | content = content.replace(re, ''); 55 | content = content.replace(/\s*$/, ''); 56 | content += '\n'; 57 | return content; 58 | } 59 | 60 | 61 | /** 62 | * 设置文件内容 63 | * 64 | * @private 65 | * @param {string} content 66 | */ 67 | function saveContent(content: string): void { 68 | fs.writeFileSync(filePath, content, 'utf-8'); 69 | } 70 | 71 | 72 | /** 73 | * 删除文件内容 74 | * 75 | * @private 76 | * @param {string} path 77 | */ 78 | function removeFiles(path: string) { 79 | var files = []; 80 | if (fs.existsSync(path)) { 81 | files = fs.readdirSync(path); 82 | files.forEach(function (file, index) { 83 | var curPath = path + "/" + file; 84 | if (fs.statSync(curPath).isDirectory()) { // recurse 85 | removeFiles(curPath); 86 | } else { // delete file 87 | fs.unlinkSync(curPath); 88 | } 89 | }); 90 | fs.rmdirSync(path); 91 | } 92 | } -------------------------------------------------------------------------------- /src/live2dModify/version.ts: -------------------------------------------------------------------------------- 1 | export default '0.1.12'; -------------------------------------------------------------------------------- /src/live2dModify/vsHelp.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from 'vscode'; 2 | 3 | const vsHelp = { 4 | /** 5 | * 展示信息提示框 6 | * 7 | * @param {string} content 提示内容 8 | * @returns {Thenable} 9 | */ 10 | showInfo(content: string): Thenable { 11 | return vscode.window.showInformationMessage(content); 12 | }, 13 | 14 | /** 15 | * 提示信息并重启 16 | * 17 | * @param {any} content 提示内容 18 | * @returns {Thenable} 19 | */ 20 | showInfoRestart(content: any): Thenable { 21 | return vscode.window.showInformationMessage(content, { title: "重新加载" }) 22 | .then(function (item) { 23 | if (!item) { return; } 24 | vscode.commands.executeCommand('workbench.action.reloadWindow'); 25 | }); 26 | } 27 | }; 28 | 29 | export default vsHelp; -------------------------------------------------------------------------------- /src/live2dView/index.ts: -------------------------------------------------------------------------------- 1 | import * as vscode from "vscode"; 2 | import { Main } from "../live2dModify/Main"; 3 | 4 | export function activateLive2d(context: vscode.ExtensionContext) { 5 | const provider = new Live2dViewProvider(context.extensionUri); 6 | 7 | context.subscriptions.push( 8 | vscode.window.registerWebviewViewProvider( 9 | Live2dViewProvider.viewType, 10 | provider 11 | ) 12 | ); 13 | } 14 | 15 | class Live2dViewProvider implements vscode.WebviewViewProvider { 16 | public static readonly viewType = "vscode-live2d.live2dView"; 17 | 18 | private _view?: vscode.WebviewView; 19 | 20 | constructor(private readonly _extensionUri: vscode.Uri) {} 21 | 22 | public resolveWebviewView( 23 | webviewView: vscode.WebviewView, 24 | context: vscode.WebviewViewResolveContext, 25 | _token: vscode.CancellationToken 26 | ) { 27 | this._view = webviewView; 28 | 29 | webviewView.webview.options = { 30 | // Allow scripts in the webview 31 | enableScripts: true, 32 | localResourceRoots: [this._extensionUri], 33 | }; 34 | 35 | webviewView.webview.html = this._getHtmlForWebview(webviewView.webview); 36 | 37 | webviewView.webview.onDidReceiveMessage((data) => { 38 | switch (data.type) { 39 | case "generateResources": 40 | Main.Instance && Main.Instance.generateResources(); 41 | break; 42 | case "removeResources": 43 | Main.Instance && Main.Instance.removeResources(true); 44 | break; 45 | } 46 | }); 47 | } 48 | 49 | private _getHtmlForWebview(webview: vscode.Webview) { 50 | // Get the local path to main script run in the webview, then convert it to a uri we can use in the webview. 51 | const scriptUri = webview.asWebviewUri( 52 | vscode.Uri.joinPath(this._extensionUri, "media", "main.js") 53 | ); 54 | 55 | // Do the same for the stylesheet. 56 | const styleVSCodeUri = webview.asWebviewUri( 57 | vscode.Uri.joinPath(this._extensionUri, "media", "vscode.css") 58 | ); 59 | const styleMainUri = webview.asWebviewUri( 60 | vscode.Uri.joinPath(this._extensionUri, "media", "main.css") 61 | ); 62 | 63 | // Use a nonce to only allow a specific script to be run. 64 | const nonce = getNonce(); 65 | 66 | return ` 67 | 68 | 69 | 70 | 71 | 72 | Live 2d 73 | 74 | 75 |
76 |
基本操作:
77 |
78 | 79 | 80 |
81 |
82 | 88 | 89 |
90 | 91 |
92 |
配置信息:
93 |
自启动:
94 |
95 | 96 | 97 |
98 | 102 |
定位依赖:
103 |
104 | 105 | 106 | 107 | 108 |
109 |
插件依赖文件:
110 |
111 | 117 | 123 |
124 | 125 |
背景图相关功能失效
126 |
因为获取图片的接口没了
127 |
背景图:(需要先启动live2d人物)
128 |
129 | 130 | 131 |
132 |
定时切换(分钟):
133 |
134 | 135 | 136 | 137 |
138 |
背景图配置:(会默认使用最近配置)
139 |
140 |
不透明度:
141 | 142 |
143 |
144 |
适配样式:
145 | 150 |
151 |
152 | 153 | 154 |
155 | 156 |
157 |
测试功能:
158 |
下载当前背景图(勿短时间内多次点击):
159 |
160 | 161 | 162 |
163 |
164 |
165 | 166 | 167 | 168 | `; 169 | } 170 | } 171 | 172 | function getNonce() { 173 | let text = ""; 174 | const possible = 175 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 176 | for (let i = 0; i < 32; i++) { 177 | text += possible.charAt(Math.floor(Math.random() * possible.length)); 178 | } 179 | return text; 180 | } 181 | 182 | // 183 | -------------------------------------------------------------------------------- /src/test/runTest.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | 3 | import { runTests } from '@vscode/test-electron'; 4 | 5 | async function main() { 6 | try { 7 | // The folder containing the Extension Manifest package.json 8 | // Passed to `--extensionDevelopmentPath` 9 | const extensionDevelopmentPath = path.resolve(__dirname, '../../'); 10 | 11 | // The path to test runner 12 | // Passed to --extensionTestsPath 13 | const extensionTestsPath = path.resolve(__dirname, './suite/index'); 14 | 15 | // Download VS Code, unzip it and run the integration test 16 | await runTests({ extensionDevelopmentPath, extensionTestsPath }); 17 | } catch (err) { 18 | console.error('Failed to run tests'); 19 | process.exit(1); 20 | } 21 | } 22 | 23 | main(); 24 | -------------------------------------------------------------------------------- /src/test/suite/extension.test.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | 3 | // You can import and use all API from the 'vscode' module 4 | // as well as import your extension to test it 5 | import * as vscode from 'vscode'; 6 | // import * as myExtension from '../../extension'; 7 | 8 | suite('Extension Test Suite', () => { 9 | vscode.window.showInformationMessage('Start all tests.'); 10 | 11 | test('Sample test', () => { 12 | assert.strictEqual(-1, [1, 2, 3].indexOf(5)); 13 | assert.strictEqual(-1, [1, 2, 3].indexOf(0)); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /src/test/suite/index.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path'; 2 | import * as Mocha from 'mocha'; 3 | import * as glob from 'glob'; 4 | 5 | export function run(): Promise { 6 | // Create the mocha test 7 | const mocha = new Mocha({ 8 | ui: 'tdd', 9 | color: true 10 | }); 11 | 12 | const testsRoot = path.resolve(__dirname, '..'); 13 | 14 | return new Promise((c, e) => { 15 | glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { 16 | if (err) { 17 | return e(err); 18 | } 19 | 20 | // Add files to the test suite 21 | files.forEach(f => mocha.addFile(path.resolve(testsRoot, f))); 22 | 23 | try { 24 | // Run the mocha test 25 | mocha.run(failures => { 26 | if (failures > 0) { 27 | e(new Error(`${failures} tests failed.`)); 28 | } else { 29 | c(); 30 | } 31 | }); 32 | } catch (err) { 33 | console.error(err); 34 | e(err); 35 | } 36 | }); 37 | }); 38 | } 39 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "ES2020", 5 | "outDir": "out", 6 | "lib": [ 7 | "ES2020" 8 | ], 9 | "sourceMap": true, 10 | "rootDir": "src", 11 | "strict": false /* enable all strict type-checking options */ 12 | /* Additional Checks */ 13 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 14 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 15 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 16 | }, 17 | "exclude": [ 18 | "node_modules", 19 | ".vscode-test" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /vsc-extension-quickstart.md: -------------------------------------------------------------------------------- 1 | # Welcome to your VS Code Extension 2 | 3 | ## What's in the folder 4 | 5 | * This folder contains all of the files necessary for your extension. 6 | * `package.json` - this is the manifest file in which you declare your extension and command. 7 | * The sample plugin registers a command and defines its title and command name. With this information VS Code can show the command in the command palette. It doesn’t yet need to load the plugin. 8 | * `src/extension.ts` - this is the main file where you will provide the implementation of your command. 9 | * The file exports one function, `activate`, which is called the very first time your extension is activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`. 10 | * We pass the function containing the implementation of the command as the second parameter to `registerCommand`. 11 | 12 | ## Get up and running straight away 13 | 14 | * Press `F5` to open a new window with your extension loaded. 15 | * Run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`. 16 | * Set breakpoints in your code inside `src/extension.ts` to debug your extension. 17 | * Find output from your extension in the debug console. 18 | 19 | ## Make changes 20 | 21 | * You can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`. 22 | * You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes. 23 | 24 | 25 | ## Explore the API 26 | 27 | * You can open the full set of our API when you open the file `node_modules/@types/vscode/index.d.ts`. 28 | 29 | ## Run tests 30 | 31 | * Open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Extension Tests`. 32 | * Press `F5` to run the tests in a new window with your extension loaded. 33 | * See the output of the test result in the debug console. 34 | * Make changes to `src/test/suite/extension.test.ts` or create new test files inside the `test/suite` folder. 35 | * The provided test runner will only consider files matching the name pattern `**.test.ts`. 36 | * You can create folders inside the `test` folder to structure your tests any way you want. 37 | 38 | ## Go further 39 | 40 | * Reduce the extension size and improve the startup time by [bundling your extension](https://code.visualstudio.com/api/working-with-extensions/bundling-extension). 41 | * [Publish your extension](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) on the VSCode extension marketplace. 42 | * Automate builds by setting up [Continuous Integration](https://code.visualstudio.com/api/working-with-extensions/continuous-integration). 43 | --------------------------------------------------------------------------------