├── .commitlintrc
├── .github
└── workflows
│ └── release.yml
├── .gitignore
├── .release-it.ts
├── .vscode
├── extensions.json
└── settings.json
├── Cargo.lock
├── Cargo.toml
├── LICENSE
├── README.md
├── eslint.config.ts
├── index.html
├── package.json
├── patches
└── pixi-live2d-display.patch
├── pnpm-lock.yaml
├── public
├── images
│ ├── backgrounds
│ │ ├── keyboard.png
│ │ └── standard.png
│ └── logo.png
├── js
│ ├── live2d.min.js
│ └── live2dcubismcore.min.js
└── models
│ ├── keyboard
│ ├── cat.model3.json
│ ├── demomodel2.1024
│ │ ├── texture_00.png
│ │ ├── texture_01.png
│ │ └── texture_02.png
│ ├── demomodel2.cdi3.json
│ ├── demomodel2.moc3
│ ├── exp_1.exp3.json
│ ├── exp_2.exp3.json
│ ├── live2d_expression0.exp3.json
│ ├── live2d_expression1.exp3.json
│ ├── live2d_expression2.exp3.json
│ ├── live2d_motion1.flac
│ ├── live2d_motion1.motion3.json
│ └── live2d_motion2.motion3.json
│ └── standard
│ ├── cat.model3.json
│ ├── demomodel.1024
│ ├── texture_00.png
│ ├── texture_01.png
│ └── texture_02.png
│ ├── demomodel.cdi3.json
│ ├── demomodel.moc3
│ ├── exp_1.exp3.json
│ ├── exp_2.exp3.json
│ ├── live2d_expression0.exp3.json
│ ├── live2d_expression1.exp3.json
│ ├── live2d_expression2.exp3.json
│ ├── live2d_motion1.flac
│ ├── live2d_motion1.motion3.json
│ └── live2d_motion2.motion3.json
├── scripts
├── buildIcon.ts
└── release.ts
├── src-tauri
├── .gitignore
├── BongoCat.desktop
├── Cargo.lock
├── Cargo.toml
├── assets
│ ├── logo-mac.png
│ ├── logo.png
│ └── tray.png
├── build.rs
├── capabilities
│ └── default.json
├── src
│ ├── core
│ │ ├── device.rs
│ │ ├── mod.rs
│ │ ├── prevent_default.rs
│ │ └── setup
│ │ │ ├── linux.rs
│ │ │ ├── macos.rs
│ │ │ ├── mod.rs
│ │ │ └── windows.rs
│ ├── lib.rs
│ ├── main.rs
│ └── plugins
│ │ └── window
│ │ ├── Cargo.toml
│ │ ├── build.rs
│ │ ├── permissions
│ │ └── default.toml
│ │ └── src
│ │ ├── commands
│ │ ├── macos.rs
│ │ ├── mod.rs
│ │ └── not_macos.rs
│ │ └── lib.rs
├── tauri.conf.json
├── tauri.linux.conf.json
├── tauri.macos.conf.json
└── tauri.windows.conf.json
├── src
├── App.vue
├── assets
│ ├── css
│ │ └── global.scss
│ └── images
│ │ └── keys
│ │ ├── Alt.png
│ │ ├── AltGr.png
│ │ ├── BackQuote.png
│ │ ├── Backspace.png
│ │ ├── CapsLock.png
│ │ ├── Control.png
│ │ ├── ControlLeft.png
│ │ ├── ControlRight.png
│ │ ├── Delete.png
│ │ ├── DownArrow.png
│ │ ├── Escape.png
│ │ ├── Fn.png
│ │ ├── KeyA.png
│ │ ├── KeyB.png
│ │ ├── KeyC.png
│ │ ├── KeyD.png
│ │ ├── KeyE.png
│ │ ├── KeyF.png
│ │ ├── KeyG.png
│ │ ├── KeyH.png
│ │ ├── KeyI.png
│ │ ├── KeyJ.png
│ │ ├── KeyK.png
│ │ ├── KeyL.png
│ │ ├── KeyM.png
│ │ ├── KeyN.png
│ │ ├── KeyO.png
│ │ ├── KeyP.png
│ │ ├── KeyQ.png
│ │ ├── KeyR.png
│ │ ├── KeyS.png
│ │ ├── KeyT.png
│ │ ├── KeyU.png
│ │ ├── KeyV.png
│ │ ├── KeyW.png
│ │ ├── KeyX.png
│ │ ├── KeyY.png
│ │ ├── KeyZ.png
│ │ ├── LeftArrow.png
│ │ ├── Meta.png
│ │ ├── Num0.png
│ │ ├── Num1.png
│ │ ├── Num2.png
│ │ ├── Num3.png
│ │ ├── Num4.png
│ │ ├── Num5.png
│ │ ├── Num6.png
│ │ ├── Num7.png
│ │ ├── Num8.png
│ │ ├── Num9.png
│ │ ├── Return.png
│ │ ├── RightArrow.png
│ │ ├── Shift.png
│ │ ├── ShiftLeft.png
│ │ ├── ShiftRight.png
│ │ ├── Slash.png
│ │ ├── Space.png
│ │ ├── Tab.png
│ │ └── UpArrow.png
├── components
│ ├── pro-list-item
│ │ └── index.vue
│ ├── pro-list
│ │ └── index.vue
│ └── update-app
│ │ └── index.vue
├── composables
│ ├── useDevice.ts
│ ├── useModel.ts
│ ├── useTauriListen.ts
│ ├── useThemeVars.ts
│ ├── useTray.ts
│ └── useWindowState.ts
├── constants
│ └── index.ts
├── layouts
│ └── preference
│ │ └── index.vue
├── main.ts
├── pages
│ ├── about
│ │ └── index.vue
│ ├── cat
│ │ └── index.vue
│ ├── general
│ │ └── index.vue
│ ├── main
│ │ └── index.vue
│ └── model
│ │ └── index.vue
├── plugins
│ └── window.ts
├── router
│ └── index.ts
├── stores
│ ├── app.ts
│ ├── cat.ts
│ ├── general.ts
│ └── model.ts
├── utils
│ ├── live2d.ts
│ ├── monitor.ts
│ ├── platform.ts
│ └── tauri.ts
└── vite-env.d.ts
├── static
└── demo.gif
├── tsconfig.json
├── tsconfig.node.json
├── uno.config.ts
└── vite.config.ts
/.commitlintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@commitlint/config-conventional"
3 | }
4 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release CI
2 |
3 | on:
4 | push:
5 | tags:
6 | - 'v*'
7 | workflow_dispatch:
8 |
9 | jobs:
10 | create-release:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v4
14 | with:
15 | fetch-depth: 0
16 | - name: Set output
17 | id: vars
18 | run: echo "tag=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT
19 |
20 | - name: Setup node
21 | uses: actions/setup-node@v4
22 | with:
23 | node-version: 20
24 |
25 | - name: Generate changelog
26 | id: create_release
27 | run: npx changelogithub --draft --name ${{ steps.vars.outputs.tag }}
28 | env:
29 | GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
30 |
31 | build-app:
32 | needs: create-release
33 | permissions:
34 | contents: write
35 | strategy:
36 | fail-fast: false
37 | matrix:
38 | include:
39 | - platform: macos-latest
40 | target: aarch64-apple-darwin
41 | - platform: macos-latest
42 | target: x86_64-apple-darwin
43 |
44 | - platform: windows-latest
45 | target: x86_64-pc-windows-msvc
46 | - platform: windows-latest
47 | target: i686-pc-windows-msvc
48 | - platform: windows-latest
49 | target: aarch64-pc-windows-msvc
50 |
51 | - platform: ubuntu-22.04
52 | target: x86_64-unknown-linux-gnu
53 |
54 | runs-on: ${{ matrix.platform }}
55 | steps:
56 | - name: Checkout repository
57 | uses: actions/checkout@v4
58 | - name: Setup node
59 | uses: actions/setup-node@v4
60 | with:
61 | node-version: 20
62 | - uses: pnpm/action-setup@v3
63 | with:
64 | version: latest
65 |
66 | - name: Install rust target
67 | run: rustup target add ${{ matrix.target }}
68 |
69 | - name: Install dependencies (ubuntu only)
70 | if: matrix.platform == 'ubuntu-22.04'
71 | run: |
72 | sudo apt-get update
73 | sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
74 |
75 | - name: Install Rust stable
76 | uses: dtolnay/rust-toolchain@stable
77 |
78 | - name: Rust cache
79 | uses: swatinem/rust-cache@v2
80 | with:
81 | workspaces: target
82 |
83 | - name: Sync node version and setup cache
84 | uses: actions/setup-node@v4
85 | with:
86 | node-version: 20
87 | cache: pnpm
88 |
89 | - name: Install app dependencies and build web
90 | run: pnpm install --frozen-lockfile
91 |
92 | - name: Build the app
93 | uses: tauri-apps/tauri-action@v0
94 | env:
95 | CI: false
96 | PLATFORM: ${{ matrix.platform }}
97 | GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
98 | TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
99 | TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
100 | with:
101 | tagName: ${{ github.ref_name }}
102 | releaseName: BongoCat ${{ needs.create-release.outputs.APP_VERSION }}
103 | releaseBody: ''
104 | releaseDraft: true
105 | prerelease: false
106 | args: --target ${{ matrix.target }}
107 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 | target
15 |
16 | # Editor directories and files
17 | .idea
18 | .DS_Store
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/.release-it.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-template-curly-in-string */
2 | import type { Config } from 'release-it'
3 |
4 | export default {
5 | git: {
6 | commitMessage: 'v${version}',
7 | tagName: 'v${version}',
8 | },
9 | npm: {
10 | publish: false,
11 | },
12 | hooks: {
13 | 'after:bump': 'tsx scripts/release.ts',
14 | },
15 | } satisfies Config
16 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "tauri-apps.tauri-vscode",
4 | "rust-lang.rust-analyzer",
5 | "antfu.unocss",
6 | "dbaeumer.vscode-eslint"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | // Disable the default formatter, use eslint instead
3 | "prettier.enable": false,
4 |
5 | // Auto fix
6 | "editor.codeActionsOnSave": {
7 | "source.fixAll.eslint": "explicit",
8 | "source.organizeImports": "never"
9 | },
10 |
11 | // Silent the stylistic rules in you IDE, but still auto fix them
12 | "eslint.rules.customizations": [
13 | { "rule": "style/*", "severity": "off", "fixable": true },
14 | { "rule": "format/*", "severity": "off", "fixable": true },
15 | { "rule": "*-indent", "severity": "off", "fixable": true },
16 | { "rule": "*-spacing", "severity": "off", "fixable": true },
17 | { "rule": "*-spaces", "severity": "off", "fixable": true },
18 | { "rule": "*-order", "severity": "off", "fixable": true },
19 | { "rule": "*-dangle", "severity": "off", "fixable": true },
20 | { "rule": "*-newline", "severity": "off", "fixable": true },
21 | { "rule": "*quotes", "severity": "off", "fixable": true },
22 | { "rule": "*semi", "severity": "off", "fixable": true }
23 | ],
24 |
25 | // Enable eslint for all supported languages
26 | "eslint.validate": [
27 | "javascript",
28 | "javascriptreact",
29 | "typescript",
30 | "typescriptreact",
31 | "vue",
32 | "html",
33 | "markdown",
34 | "json",
35 | "json5",
36 | "jsonc",
37 | "yaml",
38 | "toml",
39 | "xml",
40 | "gql",
41 | "graphql",
42 | "astro",
43 | "svelte",
44 | "css",
45 | "less",
46 | "scss",
47 | "pcss",
48 | "postcss"
49 | ]
50 | }
51 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | resolver = "2"
3 | members = [ "src-tauri" ]
4 |
5 | [workspace.dependencies]
6 | tauri = "2"
7 | serde = "1"
8 | serde_json = "1"
9 | fs_extra = "1"
10 | tauri-plugin = { version = "2", features = [ "build" ] }
11 | tauri-nspanel = { git = "https://github.com/ahkohd/tauri-nspanel", branch = "v2" }
12 | tauri-plugin-custom-window = { path = "./src-tauri/src/plugins/window" }
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 ayangweb
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
43 |
44 | ## 灵感来源
45 |
46 | 本项目灵感来源于 [MMmmmoko](https://github.com/MMmmmoko) 大佬的 [Bongo Cat Mver](https://github.com/MMmmmoko/Bongo-Cat-Mver)。由于原项目仅支持 Windows,作为一名深度 macOS 用户,我希望在自己的设备上也能使用这款可爱的 Bongo Cat,因此决定开发一个适配 macOS 的版本。
47 |
48 | 此外,得益于 Tauri 框架强大的跨平台能力,本项目不仅支持 macOS,还可在 Windows 和 Linux 上运行,让更多用户都能与这只可爱的猫咪互动!
49 |
50 | 
51 |
52 | ## 下载
53 |
54 | 请前往 [Releases](https://github.com/ayangweb/BongoCat/releases) 页面,下载最新版本。
55 |
56 | ### macOS
57 |
58 | - Apple Silicon:下载 `BongoCat_aarch64.dmg`
59 | - Intel Chip:下载 `BongoCat_x64.dmg`
60 |
61 | ### Windows
62 |
63 | - 64 位系统:下载 `BongoCat_x64.exe`
64 | - 32 位系统:下载 `BongoCat_x86.exe`
65 | - ARM64 架构:下载 `BongoCat_arm64.exe`
66 |
67 | ### Linux (X11)
68 |
69 | - Debian / Ubuntu:下载 `BongoCat_amd64.deb`
70 | - Fedora / RHEL:下载 `BongoCat_x86_64.rpm`
71 | - 通用版本:下载 `BongoCat_amd64.AppImage`
72 |
73 | ## 历史星标
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/eslint.config.ts:
--------------------------------------------------------------------------------
1 | import antfu from '@antfu/eslint-config'
2 |
3 | export default antfu({
4 | formatters: true,
5 | unocss: true,
6 | rules: {
7 | 'antfu/if-newline': 'off',
8 | 'style/brace-style': ['error', '1tbs'],
9 | 'ts/no-use-before-define': 'off',
10 | 'unused-imports/no-unused-imports': 'error',
11 | 'perfectionist/sort-imports': 'off',
12 | 'import/order': [
13 | 'error',
14 | {
15 | 'newlines-between': 'always',
16 | 'groups': ['type', 'builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object'],
17 | 'alphabetize': {
18 | order: 'asc',
19 | caseInsensitive: true,
20 | },
21 | },
22 | ],
23 | 'vue/attributes-order': ['error', { alphabetical: true }],
24 | },
25 | ignores: ['**/*.toml'],
26 | })
27 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | BongoCat
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bongo-cat",
3 | "type": "module",
4 | "version": "0.2.1",
5 | "private": true,
6 | "author": {
7 | "name": "ayangweb",
8 | "email": "ayangweb@foxmail.com"
9 | },
10 | "scripts": {
11 | "dev": "run-s build:icon dev:vite",
12 | "build": "run-s build:*",
13 | "dev:vite": "vite",
14 | "build:vite": "vite build",
15 | "build:icon": "tsx scripts/buildIcon.ts",
16 | "preview": "vite preview",
17 | "tauri": "tauri",
18 | "lint": "eslint --fix src",
19 | "preinstall": "npx only-allow pnpm",
20 | "prepare": "simple-git-hooks",
21 | "release": "release-it"
22 | },
23 | "dependencies": {
24 | "@tauri-apps/api": "^2.5.0",
25 | "@tauri-apps/plugin-log": "~2.3.1",
26 | "@tauri-apps/plugin-opener": "~2.2.6",
27 | "@tauri-apps/plugin-os": "^2.2.1",
28 | "@tauri-apps/plugin-process": "^2.2.1",
29 | "@tauri-apps/plugin-updater": "~2.7.1",
30 | "@tauri-store/pinia": "^3.3.0",
31 | "@vueuse/core": "^13.1.0",
32 | "ant-design-vue": "^4.2.6",
33 | "dayjs": "^1.11.13",
34 | "is-url": "^1.2.4",
35 | "pinia": "^3.0.2",
36 | "pixi-live2d-display": "^0.4.0",
37 | "pixi.js": "^6.5.10",
38 | "radash": "^12.1.0",
39 | "vue": "^3.5.13",
40 | "vue-markdown-render": "^2.2.1",
41 | "vue-router": "^4.5.0"
42 | },
43 | "devDependencies": {
44 | "@antfu/eslint-config": "^4.12.0",
45 | "@commitlint/cli": "^19.8.0",
46 | "@commitlint/config-conventional": "^19.8.0",
47 | "@iconify-json/solar": "^1.2.2",
48 | "@tauri-apps/cli": "^2.5.0",
49 | "@types/is-url": "^1.2.32",
50 | "@types/node": "^22.14.1",
51 | "@unocss/eslint-plugin": "^66.0.0",
52 | "@vitejs/plugin-vue": "^5.2.3",
53 | "eslint": "^9.25.1",
54 | "eslint-plugin-format": "^1.0.1",
55 | "lint-staged": "^15.5.1",
56 | "npm-run-all": "^4.1.5",
57 | "release-it": "^18.1.2",
58 | "sass": "^1.87.0",
59 | "simple-git-hooks": "^2.12.1",
60 | "tsx": "^4.19.3",
61 | "typescript": "~5.6.3",
62 | "unocss": "66.1.0-beta.7",
63 | "vite": "^6.3.2"
64 | },
65 | "pnpm": {
66 | "patchedDependencies": {
67 | "pixi-live2d-display": "patches/pixi-live2d-display.patch"
68 | }
69 | },
70 | "simple-git-hooks": {
71 | "commit-msg": "npx --no-install commitlint -e",
72 | "pre-commit": "npx lint-staged"
73 | },
74 | "lint-staged": {
75 | "*": "eslint --fix"
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/patches/pixi-live2d-display.patch:
--------------------------------------------------------------------------------
1 | diff --git a/core/README.md b/core/README.md
2 | deleted file mode 100644
3 | index ad383747237ee1a22ce39d01fbc7e77ac94b8e47..0000000000000000000000000000000000000000
4 | diff --git a/core/live2d.d.ts b/core/live2d.d.ts
5 | deleted file mode 100644
6 | index 0283512ed1c9ea01d7dd1b67b76d660237b453e8..0000000000000000000000000000000000000000
7 | diff --git a/cubism/.vscode/extensions.json b/cubism/.vscode/extensions.json
8 | deleted file mode 100644
9 | index fda5ad57b9567b939382ba15fb1d3b9f1fecf77e..0000000000000000000000000000000000000000
10 | diff --git a/cubism/.vscode/tasks.json b/cubism/.vscode/tasks.json
11 | deleted file mode 100644
12 | index 7cd3fffed85da69d5af154f63480bce8766a038f..0000000000000000000000000000000000000000
13 | diff --git a/types/index.d.ts b/types/index.d.ts
14 | index dff08ce9cdd9adefd15841a750c556fc3203c750..51bae2d4d8d5cd25c3b9219d96e91dc4c96bb95c 100644
15 | --- a/types/index.d.ts
16 | +++ b/types/index.d.ts
17 | @@ -1154,7 +1154,7 @@ export declare abstract class InternalModel extends EventEmitter {
18 | /**
19 | * The managed Live2D core model.
20 | */
21 | - abstract readonly coreModel: object;
22 | + abstract readonly coreModel: CubismModel;
23 | abstract readonly settings: ModelSettings;
24 | focusController: FocusController;
25 | abstract motionManager: MotionManager;
26 |
--------------------------------------------------------------------------------
/public/images/backgrounds/keyboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/public/images/backgrounds/keyboard.png
--------------------------------------------------------------------------------
/public/images/backgrounds/standard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/public/images/backgrounds/standard.png
--------------------------------------------------------------------------------
/public/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/public/images/logo.png
--------------------------------------------------------------------------------
/public/models/keyboard/cat.model3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Version": 3,
3 | "FileReferences": {
4 | "Moc": "demomodel2.moc3",
5 | "Textures": [
6 | "demomodel2.1024/texture_00.png",
7 | "demomodel2.1024/texture_01.png",
8 | "demomodel2.1024/texture_02.png"
9 | ],
10 | "DisplayInfo": "demomodel2.cdi3.json",
11 | "Expressions": [
12 | {
13 | "Name": "live2d_expression0.exp3.json",
14 | "File": "live2d_expression0.exp3.json"
15 | },
16 | {
17 | "Name": "live2d_expression1.exp3.json",
18 | "File": "live2d_expression1.exp3.json"
19 | },
20 | {
21 | "Name": "live2d_expression2.exp3.json",
22 | "File": "live2d_expression2.exp3.json"
23 | }
24 | ],
25 | "Motions": {
26 | "CAT_motion": [
27 | {
28 | "File": "live2d_motion1.motion3.json",
29 | "Sound": "live2d_motion1.flac",
30 | "FadeInTime": 0,
31 | "FadeOutTime": 0
32 | },
33 | {
34 | "File": "live2d_motion2.motion3.json",
35 | "FadeInTime": 0,
36 | "FadeOutTime": 0
37 | }
38 | ],
39 | "CAT_motion_lock": [
40 | {
41 | "File": "live2d_motion1.motion3.json",
42 | "Sound": "live2d_motion1.flac",
43 | "FadeInTime": 0,
44 | "FadeOutTime": 0
45 | },
46 | {
47 | "File": "live2d_motion2.motion3.json",
48 | "FadeInTime": 0,
49 | "FadeOutTime": 0
50 | }
51 | ]
52 | }
53 | },
54 | "Groups": [
55 | {
56 | "Target": "Parameter",
57 | "Name": "EyeBlink",
58 | "Ids": [
59 | "ParamEyeLOpen",
60 | "ParamEyeROpen"
61 | ]
62 | },
63 | {
64 | "Target": "Parameter",
65 | "Name": "LipSync",
66 | "Ids": []
67 | }
68 | ]
69 | }
70 |
--------------------------------------------------------------------------------
/public/models/keyboard/demomodel2.1024/texture_00.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/public/models/keyboard/demomodel2.1024/texture_00.png
--------------------------------------------------------------------------------
/public/models/keyboard/demomodel2.1024/texture_01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/public/models/keyboard/demomodel2.1024/texture_01.png
--------------------------------------------------------------------------------
/public/models/keyboard/demomodel2.1024/texture_02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/public/models/keyboard/demomodel2.1024/texture_02.png
--------------------------------------------------------------------------------
/public/models/keyboard/demomodel2.cdi3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Version": 3,
3 | "Parameters": [
4 | {
5 | "Id": "ParamAngleX",
6 | "GroupId": "",
7 | "Name": "角度 X"
8 | },
9 | {
10 | "Id": "ParamAngleY",
11 | "GroupId": "",
12 | "Name": "角度 Y"
13 | },
14 | {
15 | "Id": "CatParamRightHandDown",
16 | "GroupId": "",
17 | "Name": "右手按下"
18 | },
19 | {
20 | "Id": "CatParamLeftHandDown",
21 | "GroupId": "",
22 | "Name": "左手按下"
23 | },
24 | {
25 | "Id": "ParamAngleZ",
26 | "GroupId": "",
27 | "Name": "角度 Z"
28 | },
29 | {
30 | "Id": "ParamEyeLOpen",
31 | "GroupId": "",
32 | "Name": "左眼 开闭"
33 | },
34 | {
35 | "Id": "ParamEyeLSmile",
36 | "GroupId": "",
37 | "Name": "左眼 微笑"
38 | },
39 | {
40 | "Id": "ParamEyeROpen",
41 | "GroupId": "",
42 | "Name": "右眼"
43 | },
44 | {
45 | "Id": "ParamEyeRSmile",
46 | "GroupId": "",
47 | "Name": "右眼 微笑"
48 | },
49 | {
50 | "Id": "Param3",
51 | "GroupId": "",
52 | "Name": "挥手"
53 | },
54 | {
55 | "Id": "Param",
56 | "GroupId": "ParamGroup",
57 | "Name": "开启闪电"
58 | },
59 | {
60 | "Id": "Param2",
61 | "GroupId": "ParamGroup",
62 | "Name": "闪电划过"
63 | },
64 | {
65 | "Id": "Param4",
66 | "GroupId": "ParamGroup2",
67 | "Name": "表情:thuglife"
68 | },
69 | {
70 | "Id": "Param5",
71 | "GroupId": "ParamGroup2",
72 | "Name": "表情:升天"
73 | },
74 | {
75 | "Id": "ParamEyeBallX",
76 | "GroupId": "",
77 | "Name": "眼球 X"
78 | },
79 | {
80 | "Id": "ParamEyeBallY",
81 | "GroupId": "",
82 | "Name": "眼球 Y"
83 | },
84 | {
85 | "Id": "ParamBrowLY",
86 | "GroupId": "",
87 | "Name": "左眉上下"
88 | },
89 | {
90 | "Id": "ParamBrowRY",
91 | "GroupId": "",
92 | "Name": "右眉 上下"
93 | },
94 | {
95 | "Id": "ParamBrowLX",
96 | "GroupId": "",
97 | "Name": "左眉 左右"
98 | },
99 | {
100 | "Id": "ParamBrowRX",
101 | "GroupId": "",
102 | "Name": "右眉 左右"
103 | },
104 | {
105 | "Id": "ParamBrowLAngle",
106 | "GroupId": "",
107 | "Name": "左眉 角度"
108 | },
109 | {
110 | "Id": "ParamBrowRAngle",
111 | "GroupId": "",
112 | "Name": "右眉 角度"
113 | },
114 | {
115 | "Id": "ParamBrowLForm",
116 | "GroupId": "",
117 | "Name": "左眉 変形"
118 | },
119 | {
120 | "Id": "ParamBrowRForm",
121 | "GroupId": "",
122 | "Name": "右眉 変形"
123 | },
124 | {
125 | "Id": "ParamMouthForm",
126 | "GroupId": "",
127 | "Name": "嘴部 变形"
128 | },
129 | {
130 | "Id": "ParamMouthOpenY",
131 | "GroupId": "",
132 | "Name": "嘴巴 张开和闭合"
133 | },
134 | {
135 | "Id": "ParamCheek",
136 | "GroupId": "",
137 | "Name": "脸颊"
138 | },
139 | {
140 | "Id": "ParamBodyAngleX",
141 | "GroupId": "",
142 | "Name": "身体旋转 X"
143 | },
144 | {
145 | "Id": "ParamBodyAngleY",
146 | "GroupId": "",
147 | "Name": "身体旋转 Y"
148 | },
149 | {
150 | "Id": "ParamBodyAngleZ",
151 | "GroupId": "",
152 | "Name": "身体旋转 Z"
153 | },
154 | {
155 | "Id": "ParamBreath",
156 | "GroupId": "",
157 | "Name": "呼吸"
158 | },
159 | {
160 | "Id": "ParamHairFront",
161 | "GroupId": "",
162 | "Name": "摇动 前发"
163 | },
164 | {
165 | "Id": "ParamHairSide",
166 | "GroupId": "",
167 | "Name": "摇动 侧发"
168 | },
169 | {
170 | "Id": "ParamHairBack",
171 | "GroupId": "",
172 | "Name": "摇动 后发"
173 | }
174 | ],
175 | "ParameterGroups": [
176 | {
177 | "Id": "ParamGroup",
178 | "GroupId": "",
179 | "Name": "闪电"
180 | },
181 | {
182 | "Id": "ParamGroup2",
183 | "GroupId": "",
184 | "Name": "表情"
185 | }
186 | ],
187 | "Parts": [
188 | {
189 | "Id": "Part11",
190 | "Name": "demomodel.psd(未找到对应图层)"
191 | },
192 | {
193 | "Id": "Part7",
194 | "Name": "demomodel.psd(未找到对应图层)"
195 | },
196 | {
197 | "Id": "Part3",
198 | "Name": "demomodel.psd(未找到对应图层)"
199 | },
200 | {
201 | "Id": "Part2",
202 | "Name": "demomodel.psd(未找到对应图层)"
203 | },
204 | {
205 | "Id": "Part",
206 | "Name": "demomodel.psd(未找到对应图层)"
207 | },
208 | {
209 | "Id": "Part10",
210 | "Name": "天使环"
211 | },
212 | {
213 | "Id": "Part5",
214 | "Name": "demomodel.psd(未找到对应图层)"
215 | },
216 | {
217 | "Id": "PartSketch0",
218 | "Name": "[ 参考图 ]"
219 | },
220 | {
221 | "Id": "Part8",
222 | "Name": "thug life"
223 | },
224 | {
225 | "Id": "Part6",
226 | "Name": "闪电"
227 | },
228 | {
229 | "Id": "Part4",
230 | "Name": "闪电"
231 | }
232 | ]
233 | }
234 |
--------------------------------------------------------------------------------
/public/models/keyboard/demomodel2.moc3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/public/models/keyboard/demomodel2.moc3
--------------------------------------------------------------------------------
/public/models/keyboard/exp_1.exp3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Type": "Live2D Expression",
3 | "Parameters": [
4 | {
5 | "Id": "ParamEyeLOpen",
6 | "Value": 0.321,
7 | "Blend": "Multiply"
8 | },
9 | {
10 | "Id": "ParamEyeROpen",
11 | "Value": 0.313,
12 | "Blend": "Multiply"
13 | }
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/public/models/keyboard/exp_2.exp3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Type": "Live2D Expression",
3 | "Parameters": [
4 | {
5 | "Id": "ParamEyeLOpen",
6 | "Value": -1,
7 | "Blend": "Add"
8 | }
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/public/models/keyboard/live2d_expression0.exp3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Type": "Live2D Expression",
3 | "Parameters": []
4 | }
5 |
--------------------------------------------------------------------------------
/public/models/keyboard/live2d_expression1.exp3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Type": "Live2D Expression",
3 | "FadeInTime": 0.8,
4 | "Parameters": [
5 | {
6 | "Id": "Param4",
7 | "Value": 1,
8 | "Blend": "Add"
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/public/models/keyboard/live2d_expression2.exp3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Type": "Live2D Expression",
3 | "FadeInTime": 0.5,
4 | "Parameters": [
5 | {
6 | "Id": "Param5",
7 | "Value": 1,
8 | "Blend": "Add"
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/public/models/keyboard/live2d_motion1.flac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/public/models/keyboard/live2d_motion1.flac
--------------------------------------------------------------------------------
/public/models/keyboard/live2d_motion1.motion3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Version": 3,
3 | "Meta": {
4 | "Duration": 1.633,
5 | "Fps": 30.0,
6 | "Loop": true,
7 | "AreBeziersRestricted": false,
8 | "CurveCount": 2,
9 | "TotalSegmentCount": 8,
10 | "TotalPointCount": 20,
11 | "UserDataCount": 0,
12 | "TotalUserDataSize": 0
13 | },
14 | "Curves": [
15 | {
16 | "Target": "Parameter",
17 | "Id": "Param",
18 | "Segments": [
19 | 0,
20 | 0,
21 | 1,
22 | 0.033,
23 | 0,
24 | 0.067,
25 | 1,
26 | 0.1,
27 | 1,
28 | 1,
29 | 0.411,
30 | 1,
31 | 0.722,
32 | 1,
33 | 1.033,
34 | 1,
35 | 1,
36 | 1.189,
37 | 1,
38 | 1.344,
39 | 0,
40 | 1.5,
41 | 0,
42 | 0,
43 | 1.633,
44 | 0
45 | ]
46 | },
47 | {
48 | "Target": "Parameter",
49 | "Id": "Param2",
50 | "Segments": [
51 | 0,
52 | 0,
53 | 0,
54 | 0.067,
55 | 0,
56 | 1,
57 | 0.1,
58 | 0,
59 | 0.133,
60 | 0.142,
61 | 0.167,
62 | 0.2,
63 | 1,
64 | 0.489,
65 | 0.764,
66 | 0.811,
67 | 1,
68 | 1.133,
69 | 1,
70 | 0,
71 | 1.633,
72 | 1
73 | ]
74 | }
75 | ]
76 | }
77 |
--------------------------------------------------------------------------------
/public/models/keyboard/live2d_motion2.motion3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Version": 3,
3 | "Meta": {
4 | "Duration": 2.333,
5 | "Fps": 30.0,
6 | "Loop": true,
7 | "AreBeziersRestricted": true,
8 | "CurveCount": 2,
9 | "TotalSegmentCount": 7,
10 | "TotalPointCount": 21,
11 | "UserDataCount": 0,
12 | "TotalUserDataSize": 0
13 | },
14 | "Curves": [
15 | {
16 | "Target": "Parameter",
17 | "Id": "CatParamLeftHandDown",
18 | "Segments": [
19 | 0,
20 | 0,
21 | 0,
22 | 2.333,
23 | 0
24 | ]
25 | },
26 | {
27 | "Target": "Parameter",
28 | "Id": "Param3",
29 | "Segments": [
30 | 0,
31 | 0,
32 | 1,
33 | 0.133,
34 | 0,
35 | 0.267,
36 | 30,
37 | 0.4,
38 | 30,
39 | 1,
40 | 0.522,
41 | 30,
42 | 0.644,
43 | 0,
44 | 0.767,
45 | 0,
46 | 1,
47 | 0.9,
48 | 0,
49 | 1.033,
50 | 30,
51 | 1.167,
52 | 30,
53 | 1,
54 | 1.3,
55 | 30,
56 | 1.433,
57 | 0,
58 | 1.567,
59 | 0,
60 | 1,
61 | 1.7,
62 | 0,
63 | 1.833,
64 | 30,
65 | 1.967,
66 | 30,
67 | 1,
68 | 2.089,
69 | 30,
70 | 2.211,
71 | 0,
72 | 2.333,
73 | 0
74 | ]
75 | }
76 | ]
77 | }
78 |
--------------------------------------------------------------------------------
/public/models/standard/cat.model3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Version": 3,
3 | "FileReferences": {
4 | "Moc": "demomodel.moc3",
5 | "Textures": [
6 | "demomodel.1024/texture_00.png",
7 | "demomodel.1024/texture_01.png",
8 | "demomodel.1024/texture_02.png"
9 | ],
10 | "DisplayInfo": "demomodel.cdi3.json",
11 | "Expressions": [
12 | {
13 | "Key": "",
14 | "Name": "去掉表情",
15 | "File": "live2d_expression0.exp3.json"
16 | },
17 | {
18 | "Key": "",
19 | "Name": "戴上墨镜",
20 | "File": "live2d_expression1.exp3.json"
21 | },
22 | {
23 | "Key": "",
24 | "Name": "升天",
25 | "File": "live2d_expression2.exp3.json"
26 | }
27 | ],
28 | "Motions": {
29 | "CAT_motion": [
30 | {
31 | "Key": "",
32 | "Name": "打雷",
33 | "File": "live2d_motion1.motion3.json",
34 | "Sound": "live2d_motion1.flac",
35 | "FadeInTime": 0,
36 | "FadeOutTime": 0
37 | },
38 | {
39 | "Key": "",
40 | "Name": "左手摇摆",
41 | "File": "live2d_motion2.motion3.json",
42 | "FadeInTime": 0,
43 | "FadeOutTime": 0
44 | }
45 | ]
46 | }
47 | },
48 | "Groups": [
49 | {
50 | "Target": "Parameter",
51 | "Name": "EyeBlink",
52 | "Ids": [
53 | "ParamEyeLOpen",
54 | "ParamEyeROpen"
55 | ]
56 | },
57 | {
58 | "Target": "Parameter",
59 | "Name": "LipSync",
60 | "Ids": []
61 | }
62 | ],
63 | "HitAreas": []
64 | }
65 |
--------------------------------------------------------------------------------
/public/models/standard/demomodel.1024/texture_00.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/public/models/standard/demomodel.1024/texture_00.png
--------------------------------------------------------------------------------
/public/models/standard/demomodel.1024/texture_01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/public/models/standard/demomodel.1024/texture_01.png
--------------------------------------------------------------------------------
/public/models/standard/demomodel.1024/texture_02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/public/models/standard/demomodel.1024/texture_02.png
--------------------------------------------------------------------------------
/public/models/standard/demomodel.cdi3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Version": 3,
3 | "Parameters": [
4 | {
5 | "Id": "ParamAngleX",
6 | "GroupId": "",
7 | "Name": "角度 X"
8 | },
9 | {
10 | "Id": "ParamAngleY",
11 | "GroupId": "",
12 | "Name": "角度 Y"
13 | },
14 | {
15 | "Id": "ParamMouseX",
16 | "GroupId": "",
17 | "Name": "鼠标X"
18 | },
19 | {
20 | "Id": "ParamMouseY",
21 | "GroupId": "",
22 | "Name": "鼠标Y"
23 | },
24 | {
25 | "Id": "ParamMouseLeftDown",
26 | "GroupId": "",
27 | "Name": "鼠标左键按下"
28 | },
29 | {
30 | "Id": "ParamMouseRightDown",
31 | "GroupId": "",
32 | "Name": "鼠标右键按下"
33 | },
34 | {
35 | "Id": "CatParamLeftHandDown",
36 | "GroupId": "",
37 | "Name": "键盘按下"
38 | },
39 | {
40 | "Id": "ParamAngleZ",
41 | "GroupId": "",
42 | "Name": "角度 Z"
43 | },
44 | {
45 | "Id": "ParamEyeLOpen",
46 | "GroupId": "",
47 | "Name": "左眼 开闭"
48 | },
49 | {
50 | "Id": "ParamEyeLSmile",
51 | "GroupId": "",
52 | "Name": "左眼 微笑"
53 | },
54 | {
55 | "Id": "ParamEyeROpen",
56 | "GroupId": "",
57 | "Name": "右眼"
58 | },
59 | {
60 | "Id": "ParamEyeRSmile",
61 | "GroupId": "",
62 | "Name": "右眼 微笑"
63 | },
64 | {
65 | "Id": "Param3",
66 | "GroupId": "",
67 | "Name": "挥手"
68 | },
69 | {
70 | "Id": "Param",
71 | "GroupId": "ParamGroup",
72 | "Name": "开启闪电"
73 | },
74 | {
75 | "Id": "Param2",
76 | "GroupId": "ParamGroup",
77 | "Name": "闪电划过"
78 | },
79 | {
80 | "Id": "Param4",
81 | "GroupId": "ParamGroup2",
82 | "Name": "表情:thuglife"
83 | },
84 | {
85 | "Id": "Param5",
86 | "GroupId": "ParamGroup2",
87 | "Name": "表情:升天"
88 | },
89 | {
90 | "Id": "ParamEyeBallX",
91 | "GroupId": "",
92 | "Name": "眼球 X"
93 | },
94 | {
95 | "Id": "ParamEyeBallY",
96 | "GroupId": "",
97 | "Name": "眼球 Y"
98 | },
99 | {
100 | "Id": "ParamBrowLY",
101 | "GroupId": "",
102 | "Name": "左眉上下"
103 | },
104 | {
105 | "Id": "ParamBrowRY",
106 | "GroupId": "",
107 | "Name": "右眉 上下"
108 | },
109 | {
110 | "Id": "ParamBrowLX",
111 | "GroupId": "",
112 | "Name": "左眉 左右"
113 | },
114 | {
115 | "Id": "ParamBrowRX",
116 | "GroupId": "",
117 | "Name": "右眉 左右"
118 | },
119 | {
120 | "Id": "ParamBrowLAngle",
121 | "GroupId": "",
122 | "Name": "左眉 角度"
123 | },
124 | {
125 | "Id": "ParamBrowRAngle",
126 | "GroupId": "",
127 | "Name": "右眉 角度"
128 | },
129 | {
130 | "Id": "ParamBrowLForm",
131 | "GroupId": "",
132 | "Name": "左眉 変形"
133 | },
134 | {
135 | "Id": "ParamBrowRForm",
136 | "GroupId": "",
137 | "Name": "右眉 変形"
138 | },
139 | {
140 | "Id": "ParamMouthForm",
141 | "GroupId": "",
142 | "Name": "嘴部 变形"
143 | },
144 | {
145 | "Id": "ParamMouthOpenY",
146 | "GroupId": "",
147 | "Name": "嘴巴 张开和闭合"
148 | },
149 | {
150 | "Id": "ParamCheek",
151 | "GroupId": "",
152 | "Name": "脸颊"
153 | },
154 | {
155 | "Id": "ParamBodyAngleX",
156 | "GroupId": "",
157 | "Name": "身体旋转 X"
158 | },
159 | {
160 | "Id": "ParamBodyAngleY",
161 | "GroupId": "",
162 | "Name": "身体旋转 Y"
163 | },
164 | {
165 | "Id": "ParamBodyAngleZ",
166 | "GroupId": "",
167 | "Name": "身体旋转 Z"
168 | },
169 | {
170 | "Id": "ParamBreath",
171 | "GroupId": "",
172 | "Name": "呼吸"
173 | },
174 | {
175 | "Id": "ParamHairFront",
176 | "GroupId": "",
177 | "Name": "摇动 前发"
178 | },
179 | {
180 | "Id": "ParamHairSide",
181 | "GroupId": "",
182 | "Name": "摇动 侧发"
183 | },
184 | {
185 | "Id": "ParamHairBack",
186 | "GroupId": "",
187 | "Name": "摇动 后发"
188 | }
189 | ],
190 | "ParameterGroups": [
191 | {
192 | "Id": "ParamGroup",
193 | "GroupId": "",
194 | "Name": "闪电"
195 | },
196 | {
197 | "Id": "ParamGroup2",
198 | "GroupId": "",
199 | "Name": "表情"
200 | }
201 | ],
202 | "Parts": [
203 | {
204 | "Id": "Part11",
205 | "Name": "demomodel.psd(未找到对应图层)"
206 | },
207 | {
208 | "Id": "Part7",
209 | "Name": "demomodel.psd(未找到对应图层)"
210 | },
211 | {
212 | "Id": "Part3",
213 | "Name": "demomodel.psd(未找到对应图层)"
214 | },
215 | {
216 | "Id": "Part2",
217 | "Name": "demomodel.psd(未找到对应图层)"
218 | },
219 | {
220 | "Id": "Part",
221 | "Name": "demomodel.psd(未找到对应图层)"
222 | },
223 | {
224 | "Id": "Part10",
225 | "Name": "天使环"
226 | },
227 | {
228 | "Id": "Part5",
229 | "Name": "demomodel.psd(未找到对应图层)"
230 | },
231 | {
232 | "Id": "Part8",
233 | "Name": "thug life"
234 | },
235 | {
236 | "Id": "Part6",
237 | "Name": "闪电"
238 | },
239 | {
240 | "Id": "Part4",
241 | "Name": "闪电"
242 | }
243 | ]
244 | }
245 |
--------------------------------------------------------------------------------
/public/models/standard/demomodel.moc3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/public/models/standard/demomodel.moc3
--------------------------------------------------------------------------------
/public/models/standard/exp_1.exp3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Type": "Live2D Expression",
3 | "Parameters": [
4 | {
5 | "Id": "ParamEyeLOpen",
6 | "Value": 0.321,
7 | "Blend": "Multiply"
8 | },
9 | {
10 | "Id": "ParamEyeROpen",
11 | "Value": 0.313,
12 | "Blend": "Multiply"
13 | }
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/public/models/standard/exp_2.exp3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Type": "Live2D Expression",
3 | "Parameters": [
4 | {
5 | "Id": "ParamEyeLOpen",
6 | "Value": -1,
7 | "Blend": "Add"
8 | }
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/public/models/standard/live2d_expression0.exp3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Type": "Live2D Expression",
3 | "Parameters": []
4 | }
5 |
--------------------------------------------------------------------------------
/public/models/standard/live2d_expression1.exp3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Type": "Live2D Expression",
3 | "FadeInTime": 0.8,
4 | "Parameters": [
5 | {
6 | "Id": "Param4",
7 | "Value": 1,
8 | "Blend": "Add"
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/public/models/standard/live2d_expression2.exp3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Type": "Live2D Expression",
3 | "FadeInTime": 0.5,
4 | "Parameters": [
5 | {
6 | "Id": "Param5",
7 | "Value": 1,
8 | "Blend": "Add"
9 | }
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/public/models/standard/live2d_motion1.flac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/public/models/standard/live2d_motion1.flac
--------------------------------------------------------------------------------
/public/models/standard/live2d_motion1.motion3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Version": 3,
3 | "Meta": {
4 | "Duration": 1.633,
5 | "Fps": 30.0,
6 | "Loop": true,
7 | "AreBeziersRestricted": false,
8 | "CurveCount": 2,
9 | "TotalSegmentCount": 8,
10 | "TotalPointCount": 20,
11 | "UserDataCount": 0,
12 | "TotalUserDataSize": 0
13 | },
14 | "Curves": [
15 | {
16 | "Target": "Parameter",
17 | "Id": "Param",
18 | "Segments": [
19 | 0,
20 | 0,
21 | 1,
22 | 0.033,
23 | 0,
24 | 0.067,
25 | 1,
26 | 0.1,
27 | 1,
28 | 1,
29 | 0.411,
30 | 1,
31 | 0.722,
32 | 1,
33 | 1.033,
34 | 1,
35 | 1,
36 | 1.189,
37 | 1,
38 | 1.344,
39 | 0,
40 | 1.5,
41 | 0,
42 | 0,
43 | 1.633,
44 | 0
45 | ]
46 | },
47 | {
48 | "Target": "Parameter",
49 | "Id": "Param2",
50 | "Segments": [
51 | 0,
52 | 0,
53 | 0,
54 | 0.067,
55 | 0,
56 | 1,
57 | 0.1,
58 | 0,
59 | 0.133,
60 | 0.142,
61 | 0.167,
62 | 0.2,
63 | 1,
64 | 0.489,
65 | 0.764,
66 | 0.811,
67 | 1,
68 | 1.133,
69 | 1,
70 | 0,
71 | 1.633,
72 | 1
73 | ]
74 | }
75 | ]
76 | }
77 |
--------------------------------------------------------------------------------
/public/models/standard/live2d_motion2.motion3.json:
--------------------------------------------------------------------------------
1 | {
2 | "Version": 3,
3 | "Meta": {
4 | "Duration": 2.333,
5 | "Fps": 30.0,
6 | "Loop": true,
7 | "AreBeziersRestricted": true,
8 | "CurveCount": 2,
9 | "TotalSegmentCount": 7,
10 | "TotalPointCount": 21,
11 | "UserDataCount": 0,
12 | "TotalUserDataSize": 0
13 | },
14 | "Curves": [
15 | {
16 | "Target": "Parameter",
17 | "Id": "CatParamLeftHandDown",
18 | "Segments": [
19 | 0,
20 | 0,
21 | 0,
22 | 2.333,
23 | 0
24 | ]
25 | },
26 | {
27 | "Target": "Parameter",
28 | "Id": "Param3",
29 | "Segments": [
30 | 0,
31 | 0,
32 | 1,
33 | 0.133,
34 | 0,
35 | 0.267,
36 | 30,
37 | 0.4,
38 | 30,
39 | 1,
40 | 0.522,
41 | 30,
42 | 0.644,
43 | 0,
44 | 0.767,
45 | 0,
46 | 1,
47 | 0.9,
48 | 0,
49 | 1.033,
50 | 30,
51 | 1.167,
52 | 30,
53 | 1,
54 | 1.3,
55 | 30,
56 | 1.433,
57 | 0,
58 | 1.567,
59 | 0,
60 | 1,
61 | 1.7,
62 | 0,
63 | 1.833,
64 | 30,
65 | 1.967,
66 | 30,
67 | 1,
68 | 2.089,
69 | 30,
70 | 2.211,
71 | 0,
72 | 2.333,
73 | 0
74 | ]
75 | }
76 | ]
77 | }
78 |
--------------------------------------------------------------------------------
/scripts/buildIcon.ts:
--------------------------------------------------------------------------------
1 | import { execSync } from 'node:child_process'
2 | import { env, platform } from 'node:process'
3 |
4 | (() => {
5 | const isMac = env.PLATFORM?.startsWith('macos') ?? platform === 'darwin'
6 |
7 | const logoName = isMac ? 'logo-mac' : 'logo'
8 |
9 | const command = `tauri icon src-tauri/assets/${logoName}.png`
10 |
11 | execSync(command, { stdio: 'inherit' })
12 | })()
13 |
--------------------------------------------------------------------------------
/scripts/release.ts:
--------------------------------------------------------------------------------
1 | import { readFileSync, writeFileSync } from 'node:fs'
2 | import { dirname, resolve } from 'node:path'
3 | import { fileURLToPath } from 'node:url'
4 |
5 | import { name, version } from '../package.json'
6 |
7 | const __dirname = dirname(fileURLToPath(import.meta.url));
8 |
9 | (() => {
10 | const tomlPath = resolve(__dirname, '..', 'src-tauri', 'Cargo.toml')
11 | const lockPath = resolve(__dirname, '..', 'Cargo.lock')
12 |
13 | for (const path of [tomlPath, lockPath]) {
14 | let content = readFileSync(path, 'utf-8')
15 |
16 | const regexp = new RegExp(
17 | `(name\\s*=\\s*"${name}"\\s*version\\s*=\\s*)"(\\d+\\.\\d+\\.\\d+(-\\w+\\.\\d+)?)"`,
18 | )
19 |
20 | content = content.replace(regexp, `$1"${version}"`)
21 |
22 | writeFileSync(path, content)
23 | }
24 | })()
25 |
--------------------------------------------------------------------------------
/src-tauri/.gitignore:
--------------------------------------------------------------------------------
1 | # Generated by Cargo
2 | # will have compiled files and executables
3 | /target/
4 |
5 | # Generated by Tauri
6 | # will have schema files for capabilities auto-completion
7 | /gen/schemas
8 |
9 | icons
10 | autogenerated
11 | schemas
--------------------------------------------------------------------------------
/src-tauri/BongoCat.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Type=Application
3 | Name={{{name}}}
4 | Exec={{{exec}}}
5 | Icon={{{icon}}}
6 | Categories={{{categories}}}
7 | Comment={{{comment}}}
8 | Terminal=false
9 |
--------------------------------------------------------------------------------
/src-tauri/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "bongo-cat"
3 | version = "0.2.1"
4 | description = "A Tauri App"
5 | authors = [ "ayangweb" ]
6 | edition = "2021"
7 |
8 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
9 |
10 | [lib]
11 | # The `_lib` suffix may seem redundant but it is necessary
12 | # to make the lib name unique and wouldn't conflict with the bin name.
13 | # This seems to be only an issue on Windows, see https://github.com/rust-lang/cargo/issues/8519
14 | name = "bongo_cat_lib"
15 | crate-type = ["staticlib", "cdylib", "rlib"]
16 |
17 | [build-dependencies]
18 | tauri-build = { version = "2", features = [] }
19 |
20 | [dependencies]
21 | tauri = { workspace = true, features = ["tray-icon", "protocol-asset", "macos-private-api", "image-png"] }
22 | serde = { workspace = true, features = ["derive"] }
23 | serde_json.workspace = true
24 | tauri-plugin-custom-window.workspace = true
25 | rdev = "0.5"
26 | tauri-plugin-os = "2"
27 | tauri-plugin-process = "2"
28 | tauri-plugin-opener = "2"
29 | tauri-plugin-pinia = "3"
30 | tauri-plugin-log = "2"
31 | tauri-plugin-updater = "2"
32 | tauri-plugin-prevent-default = "1"
33 | tauri-plugin-single-instance = "2"
34 |
35 | [target."cfg(target_os = \"macos\")".dependencies]
36 | tauri-nspanel.workspace = true
37 |
38 | [features]
39 | cargo-clippy = []
40 |
--------------------------------------------------------------------------------
/src-tauri/assets/logo-mac.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src-tauri/assets/logo-mac.png
--------------------------------------------------------------------------------
/src-tauri/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src-tauri/assets/logo.png
--------------------------------------------------------------------------------
/src-tauri/assets/tray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src-tauri/assets/tray.png
--------------------------------------------------------------------------------
/src-tauri/build.rs:
--------------------------------------------------------------------------------
1 | fn main() {
2 | tauri_build::build()
3 | }
4 |
--------------------------------------------------------------------------------
/src-tauri/capabilities/default.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../gen/schemas/desktop-schema.json",
3 | "identifier": "default",
4 | "description": "Capability for the main window",
5 | "windows": [
6 | "*"
7 | ],
8 | "permissions": [
9 | "core:default",
10 | "core:window:allow-start-dragging",
11 | "core:window:allow-set-size",
12 | "core:window:deny-internal-toggle-maximize",
13 | "core:window:allow-set-always-on-top",
14 | "core:window:allow-set-ignore-cursor-events",
15 | "core:window:allow-set-decorations",
16 | "core:window:allow-set-position",
17 | "custom-window:default",
18 | "os:default",
19 | "process:default",
20 | "opener:default",
21 | "pinia:default",
22 | "log:default",
23 | "updater:default",
24 | "prevent-default:default"
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/src-tauri/src/core/device.rs:
--------------------------------------------------------------------------------
1 | use rdev::{listen, Event, EventType};
2 | use serde::Serialize;
3 | use serde_json::{json, Value};
4 | use std::sync::atomic::{AtomicBool, Ordering};
5 | use tauri::{AppHandle, Emitter};
6 |
7 | static IS_RUNNING: AtomicBool = AtomicBool::new(false);
8 |
9 | #[derive(Debug, Clone, Serialize)]
10 | pub enum DeviceKind {
11 | MousePress,
12 | MouseRelease,
13 | MouseMove,
14 | KeyboardPress,
15 | KeyboardRelease,
16 | }
17 |
18 | #[derive(Debug, Clone, Serialize)]
19 | pub struct DeviceEvent {
20 | kind: DeviceKind,
21 | value: Value,
22 | }
23 |
24 | pub fn start_listening(app_handle: AppHandle) {
25 | if IS_RUNNING.load(Ordering::SeqCst) {
26 | return;
27 | }
28 |
29 | IS_RUNNING.store(true, Ordering::SeqCst);
30 |
31 | let callback = move |event: Event| {
32 | let device = match event.event_type {
33 | EventType::ButtonPress(button) => DeviceEvent {
34 | kind: DeviceKind::MousePress,
35 | value: json!(format!("{:?}", button)),
36 | },
37 | EventType::ButtonRelease(button) => DeviceEvent {
38 | kind: DeviceKind::MouseRelease,
39 | value: json!(format!("{:?}", button)),
40 | },
41 | EventType::MouseMove { x, y } => DeviceEvent {
42 | kind: DeviceKind::MouseMove,
43 | value: json!({ "x": x, "y": y }),
44 | },
45 | EventType::KeyPress(key) => DeviceEvent {
46 | kind: DeviceKind::KeyboardPress,
47 | value: json!(format!("{:?}", key)),
48 | },
49 | EventType::KeyRelease(key) => DeviceEvent {
50 | kind: DeviceKind::KeyboardRelease,
51 | value: json!(format!("{:?}", key)),
52 | },
53 | _ => return,
54 | };
55 |
56 | if let Err(e) = app_handle.emit("device-changed", device) {
57 | eprintln!("Failed to emit event: {:?}", e);
58 | }
59 | };
60 |
61 | #[cfg(target_os = "macos")]
62 | if let Err(e) = listen(callback) {
63 | eprintln!("Device listening error: {:?}", e);
64 | }
65 |
66 | #[cfg(not(target_os = "macos"))]
67 | std::thread::spawn(move || {
68 | if let Err(e) = listen(callback) {
69 | eprintln!("Device listening error: {:?}", e);
70 | }
71 | });
72 | }
73 |
--------------------------------------------------------------------------------
/src-tauri/src/core/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod device;
2 | pub mod prevent_default;
3 | pub mod setup;
4 |
--------------------------------------------------------------------------------
/src-tauri/src/core/prevent_default.rs:
--------------------------------------------------------------------------------
1 | pub fn init() -> tauri::plugin::TauriPlugin {
2 | #[cfg(debug_assertions)]
3 | {
4 | use tauri_plugin_prevent_default::Flags;
5 |
6 | tauri_plugin_prevent_default::Builder::new()
7 | .with_flags(Flags::all().difference(Flags::CONTEXT_MENU))
8 | .build()
9 | }
10 |
11 | #[cfg(not(debug_assertions))]
12 | tauri_plugin_prevent_default::init()
13 | }
14 |
--------------------------------------------------------------------------------
/src-tauri/src/core/setup/linux.rs:
--------------------------------------------------------------------------------
1 | use tauri::{AppHandle, WebviewWindow};
2 |
3 | pub fn platform(
4 | _app_handle: &AppHandle,
5 | _main_window: WebviewWindow,
6 | _preference_window: WebviewWindow,
7 | ) {
8 | }
9 |
--------------------------------------------------------------------------------
/src-tauri/src/core/setup/macos.rs:
--------------------------------------------------------------------------------
1 | use tauri::{ActivationPolicy, AppHandle, Emitter, EventTarget, WebviewWindow};
2 | use tauri_nspanel::{
3 | cocoa::appkit::{NSMainMenuWindowLevel, NSWindowCollectionBehavior},
4 | panel_delegate, WebviewWindowExt,
5 | };
6 | use tauri_plugin_custom_window::MAIN_WINDOW_LABEL;
7 |
8 | #[allow(non_upper_case_globals)]
9 | const NSWindowStyleMaskNonActivatingPanel: i32 = 1 << 7;
10 | #[allow(non_upper_case_globals)]
11 | const NSResizableWindowMask: i32 = 1 << 3;
12 | const WINDOW_FOCUS_EVENT: &str = "tauri://focus";
13 | const WINDOW_BLUR_EVENT: &str = "tauri://blur";
14 | const WINDOW_MOVED_EVENT: &str = "tauri://move";
15 | const WINDOW_RESIZED_EVENT: &str = "tauri://resize";
16 |
17 | pub fn platform(
18 | app_handle: &AppHandle,
19 | main_window: WebviewWindow,
20 | _preference_window: WebviewWindow,
21 | ) {
22 | let _ = app_handle.plugin(tauri_nspanel::init());
23 |
24 | let _ = app_handle.set_activation_policy(ActivationPolicy::Accessory);
25 |
26 | let panel = main_window.to_panel().unwrap();
27 |
28 | panel.set_level(NSMainMenuWindowLevel);
29 |
30 | panel.set_style_mask(NSWindowStyleMaskNonActivatingPanel | NSResizableWindowMask);
31 |
32 | panel.set_collection_behaviour(
33 | NSWindowCollectionBehavior::NSWindowCollectionBehaviorCanJoinAllSpaces
34 | | NSWindowCollectionBehavior::NSWindowCollectionBehaviorStationary
35 | | NSWindowCollectionBehavior::NSWindowCollectionBehaviorFullScreenAuxiliary,
36 | );
37 |
38 | let delegate = panel_delegate!(EcoPanelDelegate {
39 | window_did_become_key,
40 | window_did_resign_key,
41 | window_did_resize,
42 | window_did_move
43 | });
44 |
45 | delegate.set_listener(Box::new(move |delegate_name: String| {
46 | let target = EventTarget::labeled(MAIN_WINDOW_LABEL);
47 |
48 | let window_move_event = || {
49 | if let Ok(position) = main_window.outer_position() {
50 | let _ = main_window.emit_to(target.clone(), WINDOW_MOVED_EVENT, position);
51 | }
52 | };
53 |
54 | match delegate_name.as_str() {
55 | "window_did_become_key" => {
56 | let _ = main_window.emit_to(target, WINDOW_FOCUS_EVENT, true);
57 | }
58 | "window_did_resign_key" => {
59 | let _ = main_window.emit_to(target, WINDOW_BLUR_EVENT, true);
60 | }
61 | "window_did_resize" => {
62 | window_move_event();
63 |
64 | if let Ok(size) = main_window.inner_size() {
65 | let _ = main_window.emit_to(target, WINDOW_RESIZED_EVENT, size);
66 | }
67 | }
68 | "window_did_move" => window_move_event(),
69 | _ => (),
70 | }
71 | }));
72 |
73 | panel.set_delegate(delegate);
74 | }
75 |
--------------------------------------------------------------------------------
/src-tauri/src/core/setup/mod.rs:
--------------------------------------------------------------------------------
1 | use tauri::{AppHandle, WebviewWindow};
2 |
3 | #[cfg(target_os = "macos")]
4 | mod macos;
5 |
6 | #[cfg(target_os = "windows")]
7 | mod windows;
8 |
9 | #[cfg(target_os = "linux")]
10 | mod linux;
11 |
12 | #[cfg(target_os = "macos")]
13 | pub use macos::*;
14 |
15 | #[cfg(target_os = "windows")]
16 | pub use windows::*;
17 |
18 | #[cfg(target_os = "linux")]
19 | pub use linux::*;
20 |
21 | pub fn default(
22 | app_handle: &AppHandle,
23 | main_window: WebviewWindow,
24 | preference_window: WebviewWindow,
25 | ) {
26 | #[cfg(any(dev, debug_assertions))]
27 | main_window.open_devtools();
28 |
29 | platform(app_handle, main_window.clone(), preference_window.clone());
30 | }
31 |
--------------------------------------------------------------------------------
/src-tauri/src/core/setup/windows.rs:
--------------------------------------------------------------------------------
1 | use tauri::{AppHandle, WebviewWindow};
2 |
3 | pub fn platform(
4 | _app_handle: &AppHandle,
5 | _main_window: WebviewWindow,
6 | _preference_window: WebviewWindow,
7 | ) {
8 | }
9 |
--------------------------------------------------------------------------------
/src-tauri/src/lib.rs:
--------------------------------------------------------------------------------
1 | mod core;
2 |
3 | use core::{device, prevent_default, setup};
4 | use tauri::{Manager, WindowEvent};
5 | use tauri_plugin_custom_window::{
6 | show_preference_window, MAIN_WINDOW_LABEL, PREFERENCE_WINDOW_LABEL,
7 | };
8 |
9 | #[cfg_attr(mobile, tauri::mobile_entry_point)]
10 | pub fn run() {
11 | tauri::Builder::default()
12 | .setup(|app| {
13 | let app_handle = app.handle();
14 |
15 | let main_window = app.get_webview_window(MAIN_WINDOW_LABEL).unwrap();
16 |
17 | let preference_window = app.get_webview_window(PREFERENCE_WINDOW_LABEL).unwrap();
18 |
19 | setup::default(&app_handle, main_window.clone(), preference_window.clone());
20 |
21 | device::start_listening(app_handle.clone());
22 |
23 | Ok(())
24 | })
25 | .plugin(tauri_plugin_custom_window::init())
26 | .plugin(tauri_plugin_os::init())
27 | .plugin(tauri_plugin_process::init())
28 | .plugin(tauri_plugin_opener::init())
29 | .plugin(tauri_plugin_pinia::init())
30 | .plugin(tauri_plugin_updater::Builder::new().build())
31 | .plugin(prevent_default::init())
32 | .plugin(tauri_plugin_single_instance::init(
33 | |app_handle, _argv, _cwd| {
34 | show_preference_window(app_handle);
35 | },
36 | ))
37 | .on_window_event(|window, event| match event {
38 | WindowEvent::CloseRequested { api, .. } => {
39 | let _ = window.hide();
40 |
41 | api.prevent_close();
42 | }
43 | _ => {}
44 | })
45 | .plugin(tauri_plugin_log::Builder::new().build())
46 | .run(tauri::generate_context!())
47 | .expect("error while running tauri application");
48 | }
49 |
--------------------------------------------------------------------------------
/src-tauri/src/main.rs:
--------------------------------------------------------------------------------
1 | #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
2 |
3 | fn main() {
4 | bongo_cat_lib::run()
5 | }
6 |
--------------------------------------------------------------------------------
/src-tauri/src/plugins/window/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "tauri-plugin-custom-window"
3 | version = "0.1.0"
4 | authors = []
5 | description = ""
6 | edition = "2021"
7 | rust-version = "1.77.2"
8 | links = "tauri-plugin-custom-window"
9 |
10 | [dependencies]
11 | tauri.workspace = true
12 | serde.workspace = true
13 |
14 | [build-dependencies]
15 | tauri-plugin.workspace = true
16 |
17 | [target."cfg(target_os = \"macos\")".dependencies]
18 | tauri-nspanel.workspace = true
19 |
--------------------------------------------------------------------------------
/src-tauri/src/plugins/window/build.rs:
--------------------------------------------------------------------------------
1 | const COMMANDS: &[&str] = &["show_window", "hide_window"];
2 |
3 | fn main() {
4 | tauri_plugin::Builder::new(COMMANDS).build();
5 | }
6 |
--------------------------------------------------------------------------------
/src-tauri/src/plugins/window/permissions/default.toml:
--------------------------------------------------------------------------------
1 | "$schema" = "schemas/schema.json"
2 |
3 | [default]
4 | description = "Default permissions for the plugin"
5 | permissions = ["allow-show-window", "allow-hide-window"]
6 |
--------------------------------------------------------------------------------
/src-tauri/src/plugins/window/src/commands/macos.rs:
--------------------------------------------------------------------------------
1 | use super::{is_main_window, shared_hide_window, shared_show_window};
2 | use crate::MAIN_WINDOW_LABEL;
3 | use tauri::{command, AppHandle, Runtime, WebviewWindow};
4 | use tauri_nspanel::ManagerExt;
5 |
6 | pub enum MacOSPanelStatus {
7 | Show,
8 | Hide,
9 | }
10 |
11 | #[command]
12 | pub async fn show_window(app_handle: AppHandle, window: WebviewWindow) {
13 | if is_main_window(&window) {
14 | set_macos_panel(&app_handle, &window, MacOSPanelStatus::Show);
15 | } else {
16 | shared_show_window(&app_handle, &window);
17 | }
18 | }
19 |
20 | #[command]
21 | pub async fn hide_window(app_handle: AppHandle, window: WebviewWindow) {
22 | if is_main_window(&window) {
23 | set_macos_panel(&app_handle, &window, MacOSPanelStatus::Hide);
24 | } else {
25 | shared_hide_window(&app_handle, &window);
26 | }
27 | }
28 |
29 | pub fn set_macos_panel(
30 | app_handle: &AppHandle,
31 | window: &WebviewWindow,
32 | status: MacOSPanelStatus,
33 | ) {
34 | if is_main_window(window) {
35 | let app_handle_clone = app_handle.clone();
36 |
37 | let _ = app_handle.run_on_main_thread(move || {
38 | if let Ok(panel) = app_handle_clone.get_webview_panel(MAIN_WINDOW_LABEL) {
39 | match status {
40 | MacOSPanelStatus::Show => {
41 | panel.show();
42 | }
43 | MacOSPanelStatus::Hide => {
44 | panel.order_out(None);
45 | }
46 | }
47 | }
48 | });
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src-tauri/src/plugins/window/src/commands/mod.rs:
--------------------------------------------------------------------------------
1 | use tauri::{async_runtime::spawn, AppHandle, Manager, Runtime, WebviewWindow};
2 |
3 | pub static MAIN_WINDOW_LABEL: &str = "main";
4 | pub static PREFERENCE_WINDOW_LABEL: &str = "preference";
5 |
6 | #[cfg(target_os = "macos")]
7 | mod macos;
8 |
9 | #[cfg(not(target_os = "macos"))]
10 | mod not_macos;
11 |
12 | #[cfg(target_os = "macos")]
13 | pub use macos::*;
14 |
15 | #[cfg(not(target_os = "macos"))]
16 | pub use not_macos::*;
17 |
18 | pub fn is_main_window(window: &WebviewWindow) -> bool {
19 | window.label() == MAIN_WINDOW_LABEL
20 | }
21 |
22 | fn shared_show_window(app_handle: &AppHandle, window: &WebviewWindow) {
23 | let _ = window.show();
24 | let _ = window.unminimize();
25 | let _ = window.set_focus();
26 |
27 | let _ = app_handle;
28 | }
29 |
30 | fn shared_hide_window(app_handle: &AppHandle, window: &WebviewWindow) {
31 | let _ = window.hide();
32 |
33 | let _ = app_handle;
34 | }
35 |
36 | pub fn show_main_window(app_handle: &AppHandle) {
37 | show_window_by_label(app_handle, MAIN_WINDOW_LABEL);
38 | }
39 |
40 | pub fn show_preference_window(app_handle: &AppHandle) {
41 | show_window_by_label(app_handle, PREFERENCE_WINDOW_LABEL);
42 | }
43 |
44 | fn show_window_by_label(app_handle: &AppHandle, label: &str) {
45 | if let Some(window) = app_handle.get_webview_window(label) {
46 | let app_handle_clone = app_handle.clone();
47 |
48 | spawn(async move {
49 | show_window(app_handle_clone, window).await;
50 | });
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src-tauri/src/plugins/window/src/commands/not_macos.rs:
--------------------------------------------------------------------------------
1 | use super::{shared_hide_window, shared_show_window};
2 | use tauri::{command, AppHandle, Runtime, WebviewWindow};
3 |
4 | #[command]
5 | pub async fn show_window(app_handle: AppHandle, window: WebviewWindow) {
6 | shared_show_window(&app_handle, &window);
7 | }
8 |
9 | #[command]
10 | pub async fn hide_window(app_handle: AppHandle, window: WebviewWindow) {
11 | shared_hide_window(&app_handle, &window);
12 | }
13 |
--------------------------------------------------------------------------------
/src-tauri/src/plugins/window/src/lib.rs:
--------------------------------------------------------------------------------
1 | use tauri::{
2 | generate_handler,
3 | plugin::{Builder, TauriPlugin},
4 | Runtime,
5 | };
6 |
7 | mod commands;
8 |
9 | pub use commands::*;
10 |
11 | pub fn init() -> TauriPlugin {
12 | Builder::new("custom-window")
13 | .invoke_handler(generate_handler![
14 | commands::show_window,
15 | commands::hide_window,
16 | ])
17 | .build()
18 | }
19 |
--------------------------------------------------------------------------------
/src-tauri/tauri.conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://schema.tauri.app/config/2",
3 | "productName": "BongoCat",
4 | "version": "../package.json",
5 | "identifier": "com.ayangweb.BongoCat",
6 | "build": {
7 | "beforeDevCommand": "pnpm dev",
8 | "devUrl": "http://localhost:1420",
9 | "beforeBuildCommand": "pnpm build",
10 | "frontendDist": "../dist"
11 | },
12 | "app": {
13 | "macOSPrivateApi": true,
14 | "windows": [
15 | {
16 | "label": "main",
17 | "title": "BongoCat",
18 | "url": "index.html/#/",
19 | "width": 408,
20 | "height": 236,
21 | "minWidth": 204,
22 | "minHeight": 118,
23 | "shadow": false,
24 | "alwaysOnTop": true,
25 | "transparent": true,
26 | "decorations": false,
27 | "acceptFirstMouse": true,
28 | "skipTaskbar": true
29 | },
30 | {
31 | "label": "preference",
32 | "title": "偏好设置",
33 | "url": "index.html/#/preference",
34 | "width": 600,
35 | "height": 450,
36 | "visible": false,
37 | "resizable": false,
38 | "maximizable": false,
39 | "titleBarStyle": "Overlay",
40 | "hiddenTitle": true
41 | }
42 | ],
43 | "security": {
44 | "csp": null,
45 | "dangerousDisableAssetCspModification": true,
46 | "assetProtocol": {
47 | "enable": true,
48 | "scope": {
49 | "allow": ["**/*"],
50 | "requireLiteralLeadingDot": false
51 | }
52 | }
53 | }
54 | },
55 | "bundle": {
56 | "active": true,
57 | "category": "Game",
58 | "createUpdaterArtifacts": true,
59 | "targets": ["nsis", "dmg", "app", "appimage", "deb", "rpm"],
60 | "shortDescription": "BongoCat",
61 | "icon": [
62 | "icons/32x32.png",
63 | "icons/128x128.png",
64 | "icons/128x128@2x.png",
65 | "icons/icon.icns",
66 | "icons/icon.ico"
67 | ],
68 | "resources": ["assets/tray.png", "assets/logo.png"]
69 | },
70 | "plugins": {
71 | "updater": {
72 | "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEVBRjJFMzE3MjEwMUZEMTAKUldRUS9RRWhGK1B5NmdkemhKcUFrVjZBQXlzdExpakdWVEJDeU9XckVsbzV2cFIycVJOempWa2UK",
73 | "endpoints": [
74 | "https://gh-proxy.com/github.com/ayangweb/BongoCat/releases/latest/download/latest.json"
75 | ]
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src-tauri/tauri.linux.conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "identifier": "com.ayangweb.BongoCat",
3 | "bundle": {
4 | "linux": {
5 | "deb": {
6 | "depends": ["gstreamer1.0-plugins-good"],
7 | "desktopTemplate": "./BongoCat.desktop"
8 | },
9 | "rpm": {
10 | "depends": ["gstreamer1-plugins-good"],
11 | "desktopTemplate": "./BongoCat.desktop"
12 | }
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src-tauri/tauri.macos.conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "identifier": "com.ayangweb.BongoCat",
3 | "bundle": {
4 | "resources": ["assets/tray.png", "assets/logo.png"]
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/src-tauri/tauri.windows.conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "identifier": "com.ayangweb.BongoCat",
3 | "bundle": {
4 | "windows": {
5 | "digestAlgorithm": "sha256",
6 | "nsis": {
7 | "languages": ["SimpChinese"],
8 | "installMode": "both"
9 | }
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/src/assets/css/global.scss:
--------------------------------------------------------------------------------
1 | html {
2 | --uno: select-none overscroll-none antialiased;
3 |
4 | color-scheme: light;
5 |
6 | &.dark {
7 | color-scheme: dark;
8 | }
9 |
10 | img {
11 | -webkit-user-drag: none;
12 | }
13 |
14 | button {
15 | outline: none !important;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/assets/images/keys/Alt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Alt.png
--------------------------------------------------------------------------------
/src/assets/images/keys/AltGr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/AltGr.png
--------------------------------------------------------------------------------
/src/assets/images/keys/BackQuote.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/BackQuote.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Backspace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Backspace.png
--------------------------------------------------------------------------------
/src/assets/images/keys/CapsLock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/CapsLock.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Control.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Control.png
--------------------------------------------------------------------------------
/src/assets/images/keys/ControlLeft.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/ControlLeft.png
--------------------------------------------------------------------------------
/src/assets/images/keys/ControlRight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/ControlRight.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Delete.png
--------------------------------------------------------------------------------
/src/assets/images/keys/DownArrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/DownArrow.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Escape.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Escape.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Fn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Fn.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyA.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyA.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyB.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyB.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyC.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyC.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyD.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyD.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyE.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyE.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyF.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyF.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyG.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyG.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyH.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyH.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyI.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyJ.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyJ.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyK.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyK.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyL.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyL.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyM.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyN.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyN.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyO.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyO.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyP.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyQ.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyQ.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyR.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyR.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyS.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyS.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyT.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyT.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyU.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyU.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyV.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyV.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyW.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyW.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyX.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyX.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyY.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyY.png
--------------------------------------------------------------------------------
/src/assets/images/keys/KeyZ.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/KeyZ.png
--------------------------------------------------------------------------------
/src/assets/images/keys/LeftArrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/LeftArrow.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Meta.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Meta.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Num0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Num0.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Num1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Num1.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Num2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Num2.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Num3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Num3.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Num4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Num4.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Num5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Num5.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Num6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Num6.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Num7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Num7.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Num8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Num8.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Num9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Num9.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Return.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Return.png
--------------------------------------------------------------------------------
/src/assets/images/keys/RightArrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/RightArrow.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Shift.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Shift.png
--------------------------------------------------------------------------------
/src/assets/images/keys/ShiftLeft.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/ShiftLeft.png
--------------------------------------------------------------------------------
/src/assets/images/keys/ShiftRight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/ShiftRight.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Slash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Slash.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Space.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Space.png
--------------------------------------------------------------------------------
/src/assets/images/keys/Tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/Tab.png
--------------------------------------------------------------------------------
/src/assets/images/keys/UpArrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ayangweb/BongoCat/474bc5202ab176afc54a15dad94fc6e05be6d073/src/assets/images/keys/UpArrow.png
--------------------------------------------------------------------------------
/src/components/pro-list-item/index.vue:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | {{ title }}
38 |
39 |
40 |
44 |
45 | {{ description }}
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/src/components/pro-list/index.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 | {{ title }}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/components/update-app/index.vue:
--------------------------------------------------------------------------------
1 |
108 |
109 |
110 |
111 |
112 | {{ loading ? downloadProgress : "立即更新" }}
113 |
114 |
115 |
116 |
117 | 更新版本:
118 |
119 | {{ updateInfo?.currentVersion }} 👉
120 |
123 | {{ updateInfo?.version }}
124 |
125 |
126 |
127 |
128 |
129 | 更新时间:
130 | {{ updateInfo?.date }}
131 |
132 |
133 |
134 | 更新日志:
135 |
136 |
140 |
141 |
142 |
143 |
144 |
--------------------------------------------------------------------------------
/src/composables/useDevice.ts:
--------------------------------------------------------------------------------
1 | import type { Ref } from 'vue'
2 |
3 | import { useDebounceFn } from '@vueuse/core'
4 | import { reactive, ref } from 'vue'
5 |
6 | import { LISTEN_KEY } from '../constants'
7 |
8 | import { useTauriListen } from './useTauriListen'
9 |
10 | import { useCatStore } from '@/stores/cat'
11 |
12 | type MouseButtonValue = 'Left' | 'Right' | 'Middle'
13 |
14 | interface MouseButtonEvent {
15 | kind: 'MousePress' | 'MouseRelease'
16 | value: MouseButtonValue
17 | }
18 |
19 | interface MouseMoveValue {
20 | x: number
21 | y: number
22 | }
23 |
24 | interface MouseMoveEvent {
25 | kind: 'MouseMove'
26 | value: MouseMoveValue
27 | }
28 |
29 | interface KeyboardEvent {
30 | kind: 'KeyboardPress' | 'KeyboardRelease'
31 | value: string
32 | }
33 |
34 | type DeviceEvent = MouseButtonEvent | MouseMoveEvent | KeyboardEvent
35 |
36 | function getSupportKeys() {
37 | const files = import.meta.glob('../assets/images/keys/*.png', { eager: true })
38 |
39 | return Object.keys(files).map((path) => {
40 | return path.split('/').pop()?.replace('.png', '')
41 | })
42 | }
43 |
44 | const supportKeys = getSupportKeys()
45 |
46 | export function useDevice() {
47 | const pressedMouses = ref([])
48 | const mousePosition = reactive({ x: 0, y: 0 })
49 | const pressedKeys = ref([])
50 | const catStore = useCatStore()
51 |
52 | const debounceCapsLockRelease = useDebounceFn(() => {
53 | handleRelease(pressedKeys, 'CapsLock')
54 | }, 100)
55 |
56 | const handlePress = (array: Ref, value?: T) => {
57 | if (!value) return
58 |
59 | array.value = [...new Set([...array.value, value])]
60 | }
61 |
62 | const handleRelease = (array: Ref, value?: T) => {
63 | if (!value) return
64 |
65 | array.value = array.value.filter(item => item !== value)
66 | }
67 |
68 | const normalizeKeyValue = (key: string) => {
69 | key = key.replace(/^(Meta).*/, '$1').replace(/F(\d+)/, 'Fn')
70 |
71 | const isInvalidArrowKey = key.endsWith('Arrow') && catStore.mode !== 'keyboard'
72 | const isUnsupportedKey = !supportKeys.includes(key)
73 |
74 | if (isInvalidArrowKey || isUnsupportedKey) return
75 |
76 | return key
77 | }
78 |
79 | useTauriListen(LISTEN_KEY.DEVICE_CHANGED, ({ payload }) => {
80 | const { kind, value } = payload
81 |
82 | if (value === 'CapsLock') {
83 | handlePress(pressedKeys, 'CapsLock')
84 |
85 | return debounceCapsLockRelease()
86 | }
87 |
88 | switch (kind) {
89 | case 'MousePress':
90 | return handlePress(pressedMouses, value)
91 | case 'MouseRelease':
92 | return handleRelease(pressedMouses, value)
93 | case 'MouseMove':
94 | return Object.assign(mousePosition, value)
95 | case 'KeyboardPress':
96 | return handlePress(pressedKeys, normalizeKeyValue(value))
97 | case 'KeyboardRelease':
98 | return handleRelease(pressedKeys, normalizeKeyValue(value))
99 | }
100 | })
101 |
102 | return {
103 | pressedMouses,
104 | mousePosition,
105 | pressedKeys,
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/composables/useModel.ts:
--------------------------------------------------------------------------------
1 | import { LogicalSize } from '@tauri-apps/api/dpi'
2 | import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'
3 | import { watch } from 'vue'
4 |
5 | import live2d from '../utils/live2d'
6 | import { getCursorMonitor } from '../utils/monitor'
7 |
8 | import { useCatStore } from '@/stores/cat'
9 |
10 | export function useModel() {
11 | const carStore = useCatStore()
12 |
13 | watch(() => carStore.mode, handleLoad)
14 |
15 | async function handleLoad() {
16 | const data = await live2d.load(`/models/${carStore.mode}/cat.model3.json`)
17 |
18 | handleResize()
19 |
20 | Object.assign(carStore, data)
21 | }
22 |
23 | function handleDestroy() {
24 | live2d.destroy()
25 | }
26 |
27 | async function handleResize() {
28 | if (!live2d.model) return
29 |
30 | const appWindow = getCurrentWebviewWindow()
31 | const { innerWidth } = window
32 |
33 | await appWindow.setSize(
34 | new LogicalSize({
35 | width: innerWidth,
36 | height: innerWidth * (354 / 612),
37 | }),
38 | )
39 |
40 | live2d.model?.scale.set(innerWidth / 612)
41 | }
42 |
43 | function handleKeyDown(value: string[]) {
44 | const hasArrowKey = value.some(key => key.endsWith('Arrow'))
45 | const hasNonArrowKey = value.some(key => !key.endsWith('Arrow'))
46 |
47 | live2d.setParameterValue('CatParamRightHandDown', hasArrowKey)
48 | live2d.setParameterValue('CatParamLeftHandDown', hasNonArrowKey)
49 | }
50 |
51 | async function handleMouseMove() {
52 | if (carStore.mode !== 'standard' || !live2d.model) return
53 |
54 | const monitor = await getCursorMonitor()
55 |
56 | if (!monitor) return
57 |
58 | const { size, cursorX, cursorY } = monitor
59 | const { width, height } = size
60 |
61 | const xRatio = cursorX / width
62 | const yRatio = cursorY / height
63 |
64 | const x = (xRatio * 60) - 30
65 | const y = (yRatio * 60) - 30
66 |
67 | live2d.setParameterValue('ParamMouseX', -x)
68 | live2d.setParameterValue('ParamMouseY', -y)
69 | live2d.setParameterValue('ParamAngleX', x)
70 | live2d.setParameterValue('ParamAngleY', -y)
71 | }
72 |
73 | function handleMouseDown(value: string[]) {
74 | const hasLeftDown = value.includes('Left')
75 | const hasRightDown = value.includes('Right')
76 |
77 | live2d.setParameterValue('ParamMouseLeftDown', hasLeftDown)
78 | live2d.setParameterValue('ParamMouseRightDown', hasRightDown)
79 | }
80 |
81 | return {
82 | handleLoad,
83 | handleDestroy,
84 | handleResize,
85 | handleKeyDown,
86 | handleMouseMove,
87 | handleMouseDown,
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/composables/useTauriListen.ts:
--------------------------------------------------------------------------------
1 | import { listen } from '@tauri-apps/api/event'
2 | import { noop } from '@vueuse/core'
3 | import { onMounted, onUnmounted, ref } from 'vue'
4 |
5 | export function useTauriListen(...args: Parameters>) {
6 | const unlisten = ref(noop)
7 |
8 | onMounted(async () => {
9 | unlisten.value = await listen(...args)
10 | })
11 |
12 | onUnmounted(() => {
13 | unlisten.value()
14 | })
15 | }
16 |
--------------------------------------------------------------------------------
/src/composables/useThemeVars.ts:
--------------------------------------------------------------------------------
1 | import { theme } from 'ant-design-vue'
2 | import { dash } from 'radash'
3 |
4 | export function useThemeVars() {
5 | const { defaultAlgorithm, darkAlgorithm, defaultConfig } = theme
6 |
7 | const generateColorVars = () => {
8 | const { token } = defaultConfig
9 |
10 | const colors = [
11 | defaultAlgorithm(token),
12 | darkAlgorithm(token),
13 | ]
14 |
15 | for (const [index, item] of colors.entries()) {
16 | const isDark = index !== 0
17 | const vars: Record = {}
18 |
19 | for (const [key, value] of Object.entries(item)) {
20 | vars[`--ant-${dash(key)}`] = value
21 | }
22 |
23 | const style = document.createElement('style')
24 | style.dataset.theme = isDark ? 'dark' : 'light'
25 | const selector = isDark ? 'html.dark' : ':root'
26 | const values = Object.entries(vars).map(([key, value]) => `${key}: ${value};`)
27 |
28 | style.innerHTML = `${selector}{\n${values.join('\n')}\n}`
29 | document.head.appendChild(style)
30 | }
31 | }
32 |
33 | return {
34 | generateColorVars,
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/composables/useTray.ts:
--------------------------------------------------------------------------------
1 | import type { TrayIconOptions } from '@tauri-apps/api/tray'
2 |
3 | import { getName, getVersion } from '@tauri-apps/api/app'
4 | import { emit } from '@tauri-apps/api/event'
5 | import { CheckMenuItem, Menu, MenuItem, PredefinedMenuItem, Submenu } from '@tauri-apps/api/menu'
6 | import { resolveResource } from '@tauri-apps/api/path'
7 | import { TrayIcon } from '@tauri-apps/api/tray'
8 | import { openUrl } from '@tauri-apps/plugin-opener'
9 | import { exit, relaunch } from '@tauri-apps/plugin-process'
10 | import { ref, watch } from 'vue'
11 |
12 | import { GITHUB_LINK, LISTEN_KEY } from '../constants'
13 | import { hideWindow, showWindow } from '../plugins/window'
14 | import { isMac } from '../utils/platform'
15 |
16 | import { useCatStore } from '@/stores/cat'
17 |
18 | const TRAY_ID = 'BONGO_CAT_TRAY'
19 |
20 | export function useTray() {
21 | const visible = ref(true)
22 | const catStore = useCatStore()
23 |
24 | watch([visible, () => catStore.mode, () => catStore.penetrable], () => {
25 | updateTrayMenu()
26 | })
27 |
28 | const createTray = async () => {
29 | const tray = await getTrayById()
30 |
31 | if (tray) return
32 |
33 | const appName = await getName()
34 | const appVersion = await getVersion()
35 |
36 | const menu = await getTrayMenu()
37 |
38 | const icon = await resolveResource('assets/tray.png')
39 |
40 | const options: TrayIconOptions = {
41 | menu,
42 | icon,
43 | id: TRAY_ID,
44 | tooltip: `${appName} v${appVersion}`,
45 | iconAsTemplate: false,
46 | menuOnLeftClick: true,
47 | }
48 |
49 | return TrayIcon.new(options)
50 | }
51 |
52 | const getTrayById = () => {
53 | return TrayIcon.getById(TRAY_ID)
54 | }
55 |
56 | const getTrayMenu = async () => {
57 | const appVersion = await getVersion()
58 |
59 | const items = await Promise.all([
60 | MenuItem.new({
61 | text: '偏好设置...',
62 | accelerator: isMac ? 'Cmd+,' : '',
63 | action: () => showWindow(),
64 | }),
65 | MenuItem.new({
66 | text: visible.value ? '隐藏猫咪' : '显示猫咪',
67 | action: () => {
68 | if (visible.value) {
69 | hideWindow('main')
70 | } else {
71 | showWindow('main')
72 | }
73 |
74 | visible.value = !visible.value
75 | },
76 | }),
77 | Submenu.new({
78 | text: '猫咪模式',
79 | items: await Promise.all([
80 | CheckMenuItem.new({
81 | text: '标准模式',
82 | checked: catStore.mode === 'standard',
83 | action: () => {
84 | catStore.mode = 'standard'
85 | },
86 | }),
87 | CheckMenuItem.new({
88 | text: '键盘模式',
89 | checked: catStore.mode === 'keyboard',
90 | action: () => {
91 | catStore.mode = 'keyboard'
92 | },
93 | }),
94 | ]),
95 | }),
96 | CheckMenuItem.new({
97 | text: '窗口穿透',
98 | checked: catStore.penetrable,
99 | action: () => {
100 | catStore.penetrable = !catStore.penetrable
101 | },
102 | }),
103 | PredefinedMenuItem.new({ item: 'Separator' }),
104 | MenuItem.new({
105 | text: '检查更新',
106 | action: () => {
107 | showWindow()
108 |
109 | emit(LISTEN_KEY.UPDATE_APP)
110 | },
111 | }),
112 | MenuItem.new({
113 | text: '开源地址',
114 | action: () => openUrl(GITHUB_LINK),
115 | }),
116 | PredefinedMenuItem.new({ item: 'Separator' }),
117 | MenuItem.new({
118 | text: `版本 ${appVersion}`,
119 | enabled: false,
120 | }),
121 | MenuItem.new({
122 | text: '重启应用',
123 | action: relaunch,
124 | }),
125 | MenuItem.new({
126 | text: '退出应用',
127 | accelerator: isMac ? 'Cmd+Q' : '',
128 | action: () => exit(0),
129 | }),
130 | ])
131 |
132 | return Menu.new({ items })
133 | }
134 |
135 | const updateTrayMenu = async () => {
136 | const tray = await getTrayById()
137 |
138 | if (!tray) return
139 |
140 | const menu = await getTrayMenu()
141 |
142 | tray.setMenu(menu)
143 | }
144 |
145 | return {
146 | createTray,
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/src/composables/useWindowState.ts:
--------------------------------------------------------------------------------
1 | import type { Event } from '@tauri-apps/api/event'
2 |
3 | import { PhysicalPosition, PhysicalSize } from '@tauri-apps/api/dpi'
4 | import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'
5 | import { onMounted, ref } from 'vue'
6 |
7 | import { useAppStore } from '@/stores/app'
8 |
9 | export type WindowState = Record | undefined>
10 |
11 | const appWindow = getCurrentWebviewWindow()
12 | const { label } = appWindow
13 |
14 | export function useWindowState() {
15 | const appStore = useAppStore()
16 | const isRestored = ref(false)
17 |
18 | onMounted(() => {
19 | appWindow.onMoved(onChange)
20 |
21 | appWindow.onResized(onChange)
22 | })
23 |
24 | const onChange = async (event: Event) => {
25 | const minimized = await appWindow.isMinimized()
26 |
27 | if (minimized) return
28 |
29 | appStore.windowState[label] ??= {}
30 |
31 | Object.assign(appStore.windowState[label], event.payload)
32 | }
33 |
34 | const restoreState = async () => {
35 | const { x, y, width, height } = appStore.windowState[label] ?? {}
36 |
37 | if (x && y) {
38 | await appWindow.setPosition(new PhysicalPosition(x, y))
39 | }
40 |
41 | if (width && height) {
42 | await appWindow.setSize(new PhysicalSize(width, height))
43 | }
44 |
45 | isRestored.value = true
46 | }
47 |
48 | return {
49 | isRestored,
50 | restoreState,
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/constants/index.ts:
--------------------------------------------------------------------------------
1 | export const GITHUB_LINK = 'https://github.com/ayangweb/BongoCat'
2 |
3 | export const LISTEN_KEY = {
4 | SHOW_WINDOW: 'show-window',
5 | HIDE_WINDOW: 'hide-window',
6 | DEVICE_CHANGED: 'device-changed',
7 | UPDATE_APP: 'update-app',
8 | }
9 |
--------------------------------------------------------------------------------
/src/layouts/preference/index.vue:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | {{ item.meta?.title }}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createPlugin } from '@tauri-store/pinia'
2 | import { createPinia } from 'pinia'
3 | import { createApp } from 'vue'
4 |
5 | import App from './App.vue'
6 | import router from './router'
7 | import 'virtual:uno.css'
8 | import 'ant-design-vue/dist/reset.css'
9 | import './assets/css/global.scss'
10 |
11 | const pinia = createPinia()
12 | pinia.use(createPlugin({ saveOnChange: true }))
13 |
14 | createApp(App).use(router).use(pinia).mount('#app')
15 |
--------------------------------------------------------------------------------
/src/pages/about/index.vue:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 |
24 |
25 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
38 |
39 |
40 |
41 | {{ GITHUB_LINK }}
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/pages/cat/index.vue:
--------------------------------------------------------------------------------
1 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/pages/general/index.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/pages/main/index.vue:
--------------------------------------------------------------------------------
1 |
51 |
52 |
53 |
59 |
![]()
60 |
61 |
62 |
63 |
![]()
64 |
65 |
66 |
67 | 重绘中...
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/src/pages/model/index.vue:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 | 敬请期待...
6 |
7 |
--------------------------------------------------------------------------------
/src/plugins/window.ts:
--------------------------------------------------------------------------------
1 | import { invoke } from '@tauri-apps/api/core'
2 | import { emit } from '@tauri-apps/api/event'
3 |
4 | import { LISTEN_KEY } from '../constants'
5 |
6 | type WindowLabel = 'main' | 'preference'
7 |
8 | const COMMAND = {
9 | SHOW_WINDOW: 'plugin:custom-window|show_window',
10 | HIDE_WINDOW: 'plugin:custom-window|hide_window',
11 | }
12 |
13 | export function showWindow(label?: WindowLabel) {
14 | if (label) {
15 | emit(LISTEN_KEY.SHOW_WINDOW, label)
16 | } else {
17 | invoke(COMMAND.SHOW_WINDOW)
18 | }
19 | }
20 |
21 | export function hideWindow(label?: WindowLabel) {
22 | if (label) {
23 | emit(LISTEN_KEY.HIDE_WINDOW, label)
24 | } else {
25 | invoke(COMMAND.HIDE_WINDOW)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/router/index.ts:
--------------------------------------------------------------------------------
1 | // @unocss-include
2 | import type { RouteRecordRaw } from 'vue-router'
3 |
4 | import { createRouter, createWebHashHistory } from 'vue-router'
5 |
6 | import Preference from '../layouts/preference/index.vue'
7 | import General from '../pages/general/index.vue'
8 | import Main from '../pages/main/index.vue'
9 |
10 | export const preferenceRoutes: RouteRecordRaw[] = [
11 | {
12 | path: 'cat',
13 | component: () => import('../pages/cat/index.vue'),
14 | meta: {
15 | title: '猫咪设置',
16 | icon: 'i-solar:cat-outline',
17 | },
18 | },
19 | {
20 | path: 'general',
21 | component: General,
22 | meta: {
23 | title: '通用设置',
24 | icon: 'i-solar:settings-outline',
25 | },
26 | },
27 | {
28 | path: 'model',
29 | component: () => import('../pages/model/index.vue'),
30 | meta: {
31 | title: '模型管理',
32 | icon: 'i-solar:magic-stick-3-outline',
33 | },
34 | },
35 | {
36 | path: 'about',
37 | component: () => import('../pages/about/index.vue'),
38 | meta: {
39 | title: '关于',
40 | icon: 'i-solar:info-circle-outline',
41 | },
42 | },
43 | ]
44 |
45 | const routes: Readonly = [
46 | {
47 | path: '/',
48 | component: Main,
49 | },
50 | {
51 | path: '/preference',
52 | component: Preference,
53 | redirect: '/preference/cat',
54 | children: preferenceRoutes,
55 | },
56 | ]
57 |
58 | const router = createRouter({
59 | history: createWebHashHistory(),
60 | routes,
61 | })
62 |
63 | export default router
64 |
--------------------------------------------------------------------------------
/src/stores/app.ts:
--------------------------------------------------------------------------------
1 | import type { WindowState } from '@/composables/useWindowState'
2 |
3 | import { getName, getVersion } from '@tauri-apps/api/app'
4 | import { defineStore } from 'pinia'
5 | import { onMounted, reactive, ref } from 'vue'
6 |
7 | export const useAppStore = defineStore('app', () => {
8 | const name = ref('')
9 | const version = ref('')
10 | const windowState = reactive({})
11 |
12 | onMounted(async () => {
13 | name.value = await getName()
14 | version.value = await getVersion()
15 | })
16 |
17 | return {
18 | name,
19 | version,
20 | windowState,
21 | }
22 | })
23 |
--------------------------------------------------------------------------------
/src/stores/cat.ts:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia'
2 | import { ref } from 'vue'
3 |
4 | export const useCatStore = defineStore('cat', () => {
5 | const mode = ref<'standard' | 'keyboard'>('standard')
6 | const penetrable = ref(false)
7 | const opacity = ref(100)
8 | const mirrorMode = ref(false)
9 |
10 | return {
11 | mode,
12 | penetrable,
13 | opacity,
14 | mirrorMode,
15 | }
16 | })
17 |
--------------------------------------------------------------------------------
/src/stores/general.ts:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia'
2 | import { ref } from 'vue'
3 |
4 | export const useGeneralStore = defineStore('general', () => {
5 | const autoCheckUpdate = ref(false)
6 |
7 | return {
8 | autoCheckUpdate,
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/src/stores/model.ts:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia'
2 | import { ref } from 'vue'
3 |
4 | interface Motion {
5 | Key: string
6 | Name: string
7 | File: string
8 | Sound?: string
9 | FadeInTime: number
10 | FadeOutTime: number
11 | }
12 |
13 | interface Expression {
14 | Key: string
15 | Name: string
16 | File: string
17 | }
18 |
19 | export const useModelStore = defineStore('model', () => {
20 | const motions = ref([])
21 | const expressions = ref([])
22 |
23 | return {
24 | motions,
25 | expressions,
26 | }
27 | })
28 |
--------------------------------------------------------------------------------
/src/utils/live2d.ts:
--------------------------------------------------------------------------------
1 | import { Live2DModel } from 'pixi-live2d-display'
2 | import { Application, Ticker } from 'pixi.js'
3 |
4 | Live2DModel.registerTicker(Ticker)
5 |
6 | class Live2d {
7 | private app: Application | null = null
8 | public model: Live2DModel | null = null
9 |
10 | constructor() { }
11 |
12 | private mount() {
13 | const view = document.getElementById('live2dCanvas') as HTMLCanvasElement
14 |
15 | this.app = new Application({
16 | view,
17 | resizeTo: window,
18 | backgroundAlpha: 0,
19 | autoDensity: true,
20 | resolution: devicePixelRatio,
21 | })
22 | }
23 |
24 | public async load(url: string) {
25 | if (!this.app) {
26 | this.mount()
27 | }
28 |
29 | const model = await Live2DModel.from(url)
30 |
31 | if (this.app?.stage.children.length) {
32 | this.app.stage.removeChildren()
33 | }
34 |
35 | this.app?.stage.addChild(model)
36 |
37 | const { definitions, expressionManager } = model.internalModel.motionManager
38 |
39 | this.model = model
40 |
41 | return {
42 | motions: Object.values(definitions).flat(),
43 | expressions: expressionManager?.definitions ?? [],
44 | }
45 | }
46 |
47 | public destroy() {
48 | this.model?.destroy()
49 | }
50 |
51 | public setParameterValue(id: string, value: number | boolean) {
52 | return this.model?.internalModel.coreModel.setParameterValueById(id, Number(value))
53 | }
54 | }
55 |
56 | const live2d = new Live2d()
57 |
58 | export default live2d
59 |
--------------------------------------------------------------------------------
/src/utils/monitor.ts:
--------------------------------------------------------------------------------
1 | import {
2 | availableMonitors,
3 | cursorPosition,
4 | } from '@tauri-apps/api/window'
5 |
6 | export async function getCursorMonitor() {
7 | const monitors = await availableMonitors()
8 |
9 | if (!monitors.length) return
10 |
11 | const { x, y } = await cursorPosition()
12 |
13 | const monitor = monitors.find((monitor) => {
14 | const { position, size } = monitor
15 |
16 | const inX = x >= position.x && x <= position.x + size.width
17 | const inY = y >= position.y && y <= position.y + size.height
18 |
19 | return inX && inY
20 | })
21 |
22 | if (!monitor) return
23 |
24 | return {
25 | ...monitor,
26 | cursorX: x,
27 | cursorY: y,
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/utils/platform.ts:
--------------------------------------------------------------------------------
1 | import { platform } from '@tauri-apps/plugin-os'
2 |
3 | export const isMac = platform() === 'macos'
4 |
5 | export const isWindows = platform() === 'windows'
6 |
7 | export const isLinux = platform() === 'linux'
8 |
--------------------------------------------------------------------------------
/src/utils/tauri.ts:
--------------------------------------------------------------------------------
1 | export function getMainWebviewWindow() {
2 | }
3 |
--------------------------------------------------------------------------------
/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | declare module '*.vue' {
4 | import type { DefineComponent } from 'vue'
5 |
6 | const component: DefineComponent