Full Code of TSKI433/hime-display for AI

master c0a74fafacf8 cached
173 files
45.8 MB
864.0k tokens
2557 symbols
1 requests
Download .txt
Showing preview only (3,493K chars total). Download the full file or copy to clipboard to get everything.
Repository: TSKI433/hime-display
Branch: master
Commit: c0a74fafacf8
Files: 173
Total size: 45.8 MB

Directory structure:
gitextract_hi3z8e4c/

├── .eslintrc.js
├── .github/
│   └── workflows/
│       └── release.yml
├── .gitignore
├── LICENSE
├── README-CN.md
├── README-JP.md
├── README.md
├── build.config.js
├── package.json
├── public/
│   └── background/
│       └── background.tiff
├── scripts/
│   ├── build.js
│   ├── constants.js
│   └── dev-runner.js
└── src/
    ├── main/
    │   ├── Application.js
    │   ├── Launcher.js
    │   ├── core/
    │   │   ├── ExceptionHandler.js
    │   │   └── Logger.js
    │   ├── index.js
    │   ├── menus/
    │   │   └── tray.js
    │   ├── options/
    │   │   ├── paths.js
    │   │   └── windows.js
    │   ├── package.json
    │   ├── ui/
    │   │   ├── ThemeManager.js
    │   │   ├── TrayManager.js
    │   │   └── WindowManager.js
    │   └── vite.config.js
    ├── preload/
    │   ├── control/
    │   │   ├── config.js
    │   │   ├── database.js
    │   │   ├── index.js
    │   │   ├── ipc.js
    │   │   ├── paths.js
    │   │   ├── theme.js
    │   │   ├── utils.js
    │   │   └── vite.config.js
    │   ├── display/
    │   │   ├── index.js
    │   │   ├── ipc.js
    │   │   └── vite.config.js
    │   └── package.json
    ├── renderer/
    │   ├── control/
    │   │   ├── App.vue
    │   │   ├── components/
    │   │   │   ├── Common/
    │   │   │   │   ├── ConfigItem.vue
    │   │   │   │   ├── SvgIcon.vue
    │   │   │   │   ├── SvgIconElButton.vue
    │   │   │   │   └── TitleWithDivider.vue
    │   │   │   ├── Contents/
    │   │   │   │   ├── About.vue
    │   │   │   │   ├── Control/
    │   │   │   │   │   ├── Common/
    │   │   │   │   │   │   ├── 2d/
    │   │   │   │   │   │   │   ├── EventAnimation.vue
    │   │   │   │   │   │   │   └── Transform2D.vue
    │   │   │   │   │   │   ├── 3d/
    │   │   │   │   │   │   │   ├── AnimationControl.vue
    │   │   │   │   │   │   │   ├── ObjectTransform3D.vue
    │   │   │   │   │   │   │   ├── ParameterControl.vue
    │   │   │   │   │   │   │   └── Transform3D.vue
    │   │   │   │   │   │   ├── ControlLoadError.vue
    │   │   │   │   │   │   ├── ModelDescription.vue
    │   │   │   │   │   │   └── MotionCapture.vue
    │   │   │   │   │   ├── Live2DControl/
    │   │   │   │   │   │   ├── AnimationControl.vue
    │   │   │   │   │   │   ├── ParameterControl.vue
    │   │   │   │   │   │   └── index.vue
    │   │   │   │   │   ├── MMDControl/
    │   │   │   │   │   │   └── index.vue
    │   │   │   │   │   ├── SpineControl/
    │   │   │   │   │   │   ├── AnimationControl.vue
    │   │   │   │   │   │   ├── ParameterControl.vue
    │   │   │   │   │   │   └── index.vue
    │   │   │   │   │   ├── VRoidControl/
    │   │   │   │   │   │   └── index.vue
    │   │   │   │   │   └── index.vue
    │   │   │   │   ├── Display.vue
    │   │   │   │   ├── General.vue
    │   │   │   │   ├── Model.vue
    │   │   │   │   └── Source.vue
    │   │   │   ├── Main.vue
    │   │   │   └── Menu/
    │   │   │       ├── Index.vue
    │   │   │       └── MenuItem.vue
    │   │   ├── i18n.js
    │   │   ├── main.js
    │   │   ├── store/
    │   │   │   ├── app.js
    │   │   │   └── control.js
    │   │   └── styles/
    │   │       └── el-theme.scss
    │   ├── control.html
    │   ├── display/
    │   │   ├── Application.js
    │   │   ├── main.js
    │   │   ├── modelManagers/
    │   │   │   ├── Live2dManager.js
    │   │   │   ├── MmdManager.js
    │   │   │   ├── ModelManager.js
    │   │   │   ├── ModelManager3D.js
    │   │   │   ├── SpineManager.js
    │   │   │   ├── SpineManager42.js
    │   │   │   └── VroidManager.js
    │   │   └── utils/
    │   │       ├── 2d/
    │   │       │   └── utils.js
    │   │       ├── 3d/
    │   │       │   ├── AudioManager.js
    │   │       │   ├── Monitor.js
    │   │       │   ├── MouseFocusHelper.js
    │   │       │   └── NodeInfo.js
    │   │       ├── animation/
    │   │       │   ├── Mixamo2MMDAnimationConverter.js
    │   │       │   ├── Mixamo2MMDAnimationConverterNew.js
    │   │       │   └── utils.js
    │   │       ├── capture/
    │   │       │   ├── FaceMeshCaptureManager.js
    │   │       │   ├── HolisticCaptureManager.js
    │   │       │   ├── Live2DFaceMeshCaptureManager.js
    │   │       │   ├── MMDFaceMeshCaptureManager.js
    │   │       │   ├── MMDHolisticCaptureManager.js
    │   │       │   ├── VRoidFaceMeshCaptureManager.js
    │   │       │   ├── VRoidHolisticCaptureManager.js
    │   │       │   ├── parents/
    │   │       │   │   └── parents.js
    │   │       │   └── rig/
    │   │       │       ├── 3DRig.js
    │   │       │       ├── MMDRig.js
    │   │       │       └── VRoidRig.js
    │   │       ├── common.js
    │   │       ├── live2d/
    │   │       │   ├── Cubism2Shim.js
    │   │       │   └── Monitor.js
    │   │       ├── mmd/
    │   │       │   ├── AnimationManager.js
    │   │       │   └── Monitor.js
    │   │       ├── record/
    │   │       │   └── RecordManager.js
    │   │       ├── spine/
    │   │       │   └── premultipliedImageLoader.js
    │   │       └── vroid/
    │   │           └── Monitor.js
    │   ├── display.html
    │   ├── package.json
    │   ├── public/
    │   │   └── lib/
    │   │       ├── @mediapipe/
    │   │       │   ├── cdn/
    │   │       │   │   ├── camera_utils.js
    │   │       │   │   ├── drawing_utils.js
    │   │       │   │   ├── face_mesh.js
    │   │       │   │   └── holistic.js
    │   │       │   ├── face_mesh/
    │   │       │   │   ├── face_mesh.binarypb
    │   │       │   │   ├── face_mesh_solution_packed_assets.data
    │   │       │   │   ├── face_mesh_solution_packed_assets_loader.js
    │   │       │   │   ├── face_mesh_solution_simd_wasm_bin.data
    │   │       │   │   ├── face_mesh_solution_simd_wasm_bin.js
    │   │       │   │   ├── face_mesh_solution_simd_wasm_bin.wasm
    │   │       │   │   ├── face_mesh_solution_wasm_bin.js
    │   │       │   │   └── face_mesh_solution_wasm_bin.wasm
    │   │       │   └── holistic/
    │   │       │       ├── holistic.binarypb
    │   │       │       ├── holistic_solution_packed_assets.data
    │   │       │       ├── holistic_solution_packed_assets_loader.js
    │   │       │       ├── holistic_solution_simd_wasm_bin.data
    │   │       │       ├── holistic_solution_simd_wasm_bin.js
    │   │       │       ├── holistic_solution_simd_wasm_bin.wasm
    │   │       │       ├── holistic_solution_wasm_bin.js
    │   │       │       ├── holistic_solution_wasm_bin.wasm
    │   │       │       ├── pose_landmark_full.tflite
    │   │       │       ├── pose_landmark_heavy.tflite
    │   │       │       └── pose_landmark_lite.tflite
    │   │       ├── spine/
    │   │       │   └── pixi-spine.umd.js
    │   │       └── three/
    │   │           ├── ammo.wasm.js
    │   │           └── ammo.wasm.wasm
    │   └── vite.config.js
    └── shared/
        ├── constants.js
        ├── defaults/
        │   ├── defalutDatabase.js
        │   └── defaultConfig.js
        └── locales/
            ├── en/
            │   ├── control.js
            │   ├── display.js
            │   ├── general.js
            │   ├── index.js
            │   ├── menu.js
            │   ├── message.js
            │   ├── model.js
            │   ├── source.js
            │   └── tray.js
            ├── i18next.js
            ├── jp/
            │   ├── control.js
            │   ├── display.js
            │   ├── general.js
            │   ├── index.js
            │   ├── menu.js
            │   ├── message.js
            │   ├── model.js
            │   ├── source.js
            │   └── tray.js
            ├── languageNames.js
            ├── resources.js
            └── zh-CN/
                ├── control.js
                ├── display.js
                ├── general.js
                ├── index.js
                ├── menu.js
                ├── message.js
                ├── model.js
                ├── source.js
                └── tray.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .eslintrc.js
================================================
module.exports = {
  env: {
    browser: true,
    commonjs: true,
    es2021: true,
    node: true,
  },
  extends: ["plugin:vue/essential", "prettier", "plugin:prettier/recommended"],
  parserOptions: {
    ecmaVersion: "latest",
  },
  plugins: ["vue"],
  rules: {
    "prettier/prettier": "warn",
  },
};


================================================
FILE: .github/workflows/release.yml
================================================
name: Build App

on:
  workflow_dispatch:
    inputs:
      version:
        description: "Version label (e.g. v1.2.3)"
        required: false
  release:
    types: [published]

jobs:
  release:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [macos-latest, windows-latest]

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: "22"

      - name: Install dependencies
        run: yarn install

      - name: Build the app
        run: |
          if [[ "${{ runner.os }}" == "macOS" ]]; then
            yarn build:macos
          elif [[ "${{ runner.os }}" == "Windows" ]]; then
            yarn build:windows
          fi
        shell: bash

      - name: Determine version
        run: |
          echo "VERSION=${{ github.event.release.tag_name != '' && github.event.release.tag_name || github.event.inputs.version != '' && github.event.inputs.version || 'v-dev' }}" >> $GITHUB_ENV
        shell: bash

      - name: Package build output for macOS
        if: runner.os == 'macOS'
        run: |
          mkdir release
          cp build/*.dmg release/ 2>/dev/null || true
          cd release && zip -r "HimeDisplay-macos-${VERSION}.zip" . && cd ..
        shell: bash

      - name: Package build output for Windows
        if: runner.os == 'Windows'
        run: |
          mkdir release
          copy build\*.exe release\ 2>$null
          Compress-Archive -Path release\* -DestinationPath ("release\HimeDisplay-windows-$env:VERSION.zip")
        shell: pwsh

      - name: Upload build artifacts
        uses: actions/upload-artifact@v4
        with:
          name: HimeDisplay-${{ runner.os }}-${{ env.VERSION }}
          path: |
            build/*.dmg
            build/*.exe

      - name: Upload to GitHub Release (only on release)
        if: github.event_name == 'release'
        uses: softprops/action-gh-release@v2
        with:
          files: release/HimeDisplay-${{ runner.os }}-${{ env.VERSION }}.zip
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
node_modules
/npm-debug.log*
yarn-error.log

# misc
.DS_Store

# local
*.local

# dist
dist
build

.idea

gomibako
/info
.yarnrc

auto-imports.d.ts
components.d.ts

================================================
FILE: LICENSE
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.


================================================
FILE: README-CN.md
================================================
# Hime Display

<p align="center">
<img width="200px" src="./images/icon.png">
</p>

> illustrated by [MakoSaikou](https://www.pixiv.net/users/72669923)

[English](./README.md) | 简体中文 | [日本語](./README-JP.md)

[下载](https://hime.xdrv.cn/download/) | [文档](https://hime.xdrv.cn/) | [介绍视频](https://www.bilibili.com/video/BV1Me411u7pF)

此应用旨在打造一个开源、跨平台的通用桌面模型展示器。

## 预览

### 控制面板

<p align="center">
<img width="450" src="./images/control-panel-cn.png">
</p>

### 展示器

什么没看见?那就对了,展示器其实就是一个透明窗口。

## 特性

1. 多种模型类型支持:支持载入 Live2D、MMD、VRoid、Spine 四种模型。
2. 动作捕捉:借助于 Google 的 MediaPipe 对 Live2D、MMD、VRoid 提供了动捕支持。
3. 跨平台:同时对 macOS 与 Windows 提供了支持。
4. 多语言支持: 对简体中文、日语、英语提供了支持。
5. 全面的模型控制:可对模型的进行各种操作,包括骨骼变换,变形,动画播放。
6. 动画转译:MMD 模型可以直接加载来源于 Mixamo 的动画(VRoid 计划之后支持)。

## 基础载入

### 模型库数据库设计

以一个或多个文件路径作为数据源,根据一些模型文件特征,递归检测该路径下的模型,添加至数据库后载入。

### 加载模型的方法

1. 在控制面板中点击`来源`;
2. 然后`添加数据源`,选择模型及动作文件,音频所在的目录;
3. 点击数据源操作中的刷新按钮;
4. 点击控制面板菜单中的`模型`,在模型数据库中选择希望载入的模型,选中的模型将会高亮显示;
5. 然后点击数据库下方的`载入选中模型`。

### 注意事项

1. 不同类型的模型以及音频与动作文件均可放置到同一数据源下。
2. 为提高效率和增强通用性,对于大多数文件类型,该检测过程没有读取文件的内容,主要通过文件扩展名判断,因此即使文件存在问题或者不支持,也有可能被载入到数据库中。
3. 对于模型文件,由于一些类型的模型的文件名称通常不是模型名称,将以模型文件的上级目录名作为模型名称,因此在同一目录下放置多个模型可能命名混乱。
4. 对于音频与动作文件,文件名通常与内容直接相关,因此将直接采用文件名作为名称,同时放到同一个目录下不会造成命名混乱。
5. 添加数据源后可以点击编辑检索类型,默认检测全部类型。
6. 执行刷新操作后,将自动更新统计信息,模型数据库,音频数据库,动作数据库(后两者在 3D 模型的动画控制页面中显示)。

## 模型机能对比

|          |        MMD        |        VRoid        |           Live2D            |             Spine             |
| :------: | :---------------: | :-----------------: | :-------------------------: | :---------------------------: |
| 模型信息 |        ✅         |         ✅          |             ✅              |              ✅               |
| 对象变换 |        ✅         |         ✅          |             ✅              |              ✅               |
| 动画播放 |        ✅         |  ❌<br/>(待开发)  |             ✅              |              ✅               |
| 物理模拟 | ✅<br/>(仅动画) | ✅<br/>(所有状态) | ❌<br/>(好像有,还没深究) | ❌<br/>(Spine 跟我扯这个?) |
| 参数控制 |       变形        |        变形         |     Parameter<br/>Part      |      ❌<br/>(人懒没做)      |
| 面部捕捉 |        ✅         |         ✅          |             ✅              |     ❌<br/>(无参数规范)     |
| 全身捕捉 |        ✅         |         ✅          |    ❌<br/>(无参数规范)    |     ❌<br/>(无参数规范)     |

## 主要开发技术

本应用使用前端技术,基于[Electron](https://www.electronjs.org/)开发,构建工具使用了[Vite](https://vitejs.dev/)。

数据库存储采用了[lowdb](https://github.com/typicode/lowdb)。

多语言的支持采用了[i18next](https://www.i18next.com/)。

控制面板采用[Vue](https://vuejs.org/)框架开发,使用了[Element Plus](https://element-plus.org/)组件库。

2D 模型使用[Pixi.js](https://pixijs.com/)作为渲染引擎,3D 模型使用[Three.js](https://threejs.org/)作为渲染引擎。

动作捕捉使用了 Google 的[MediaPipe](https://mediapipe.dev/)进行识别,并使用[Kalidokit](https://github.com/yeemachine/kalidokit)进行捕捉数据解析。

## 开发

```bash
# 安装依赖
yarn
# 启动
yarn start
# 构建(具体build版本可以在根目录下的build.config.js文件中配置)
yarn build
```

## Special Thanks

这是我的初次尝试开发一个完整的应用,各方面经验都十分欠缺。

本项目的文件结构参考了同样使用 Electron 开发的下载工具[Motrix](https://motrix.app/),在此表示感谢。

感谢 [笺染菲素](https://space.bilibili.com/33572615) 测试应用并提供了不少建议。

感谢 [HuiDesktop](https://github.com/HuiDesktop/HuiDesktop) 的作者 [pure01fx](https://github.com/pure01fx) 提供的 Spine 方面的一些技术支持。

感谢 [greenjerry](https://github.com/greenjerry) 对我在物质,精神层面,以及软件和硬件上的大力支持。


================================================
FILE: README-JP.md
================================================
# Hime Display

<p align="center">
<img width="200px" src="./images/icon.png">
</p>

> illustrated by [MakoSaikou](https://www.pixiv.net/users/72669923)

[English](./README.md) | [简体中文](./README-CN.md) | 日本語

[ダウンロード](https://hime.xdrv.cn/download/) | [ドキュメント(中国語のみ)](https://hime.xdrv.cn/) | [紹介動画](https://www.bilibili.com/video/BV1Me411u7pF)

このアプリケーションは、オープンソースで、クロスプラットフォームのユニバーサルなデスクトップモデルディスプレイヤーを狙っています。

## プレビュー

### コントロールパネル

<p align="center">
<img width="450" src="./images/control-panel-jp.png">
</p>

### ディスプレイウインドウ

何も見えない?そう、ディスプレイは実際には透明なウィンドウです。

## 特徴

1. 多種類のモデルタイプをサポート:Live2D、MMD、VRoid、Spine を支持します。
2. モーションキャプチャ:Google の MediaPipe を使用して、Live2D、MMD、VRoid にモーションキャプチャを提供します。
3. クロスプラットフォーム:macOS と Windows の両方に対応しています。
4. 多言語対応:簡体中国語、日本語、英語に対応しています。
5. 全面的なモデルコントロール:モデルの各種操作を行うことができます。ボーン変形、モーフ、アニメーション再生など。
6. アニメーショントランスレート:MMD モデルは、Mixamo からのアニメーション(VRoid は後にサポートする予定)を直接ロードできます。

## 基本の使い方

### モデルデータベースのデザイン

1 つ以上のファイルパスをデータソースとして、いくつかのモデルファイルの特徴に基づいて、そのパス以下のモデルを再帰的に検出し、データベースに追加してから読み込みます。

### モデルをロードするの方法

1. コントロールパネルの`ソース`をクリックします。
2. そして`データソースを追加`をクリックし、モデルとアニメーションファイル、音声ファイルがあるディレクトリを選択します。
3. データソース操作の更新ボタンをクリックします。
4. コントロールパネルのメニューの`モデル`をクリックし、ロードしたいモデルを選択します。選択したモデルはハイライトで表示されます。
5. そして、データベースの下の`選択したモデルをロード`をクリックします。

### 注意事項

1.  異なるタイプのモデルと音声とアニメーションファイルを同じデータソースに配置できます。
2.  効率化と汎用性のため、ほとんどのファイルタイプは、検索プロセスでファイルの内容を読み取らず、主にファイルの拡張子で判断されます。サポートされていないファイルが存在する場合でも、データベースにロードされる可能性があります。
3.  モデルファイルについては、一部のモデルのファイル名は通常モデル名ではないため、モデルファイルの上位ディレクトリの名前がモデル名として使用されるから、複数のモデルを同じディレクトリに配置すれば、混乱を招く可能性があります。
4.  オーディオファイルとアクションファイルの場合、通常はファイル名はコンテンツに直接関係しているから、ファイル名がそのまま名前として使用され、同じディレクトリに配置しても混乱は起こりません。
5.  データソースを追加した後、検索タイプの編集をクリックするとロードされたいモデルタイプを配置できます。デフォルトでは全てびタイプが検索されます。
6.  更新操作を実行した後、統計インフォメーション、モデルデータベース、オーディオデータベース、モーションデータベースが自動的に更新されます (後者の 2 つは 3D モデルのアニメーションコントロールページに表示されます)。

## モデル機能の対比

|                      |             MMD              |         VRoid          |            Live2D            |            Spine             |
| :------------------: | :--------------------------: | :--------------------: | :--------------------------: | :--------------------------: |
|      モデル情報      |              ✅              |           ✅           |              ✅              |              ✅              |
|   オブジェクト変換   |              ✅              |           ✅           |              ✅              |              ✅              |
|  アニメーション再生  |              ✅              |   ❌<br/> (開発予定)   |              ✅              |              ✅              |
| 物理シミュレーション | ✅<br/> (アニメーションのみ) | ✅<br/> (すべての状態) | ❌<br/> (まだ調べていません) |   ❌<br/> (スパインは無理)   |
|    パラメータ制御    |            モーフ            |         モーフ         |      Parameter<br/>Part      |              ❌              |
|     顔キャプチャ     |              ✅              |           ✅           |              ✅              | ❌<br/> (パラメータ基準なし) |
|    全身キャプチャ    |              ✅              |           ✅           | ❌<br/> (パラメータ基準なし) | ❌<br/> (パラメータ基準なし) |

## 主な開発技術

このアプリケーションは、フロントエンド技術を使用し、[Electron](https://www.electronjs.org/) に使って開発されており、構築ツールは [Vite](https://vitejs.dev/) を使用しています。

データベースは [lowdb](https://github.com/typicode/lowdb) を使用しています。

多言語対応は[i18next](https://www.i18next.com/) を採用。

コントロールパネルは [Vue](https://vuejs.org/) フレームワークで開発され、[Element Plus](https://element-plus.org/) コンポーネントライブラリを使用します。

2D モデルはレンダリングエンジンに[Pixi.js](https://pixijs.com/)を、3D モデルはレンダリングエンジンに[Three.js](https://threejs.org/)を使用しています。

モーション キャプチャは、Google の [MediaPipe](https://mediapipe.dev/) を使用し、キャプチャデータの分析は [Kalidokit](https://github.com/yeemachine/kalidokit) を使用します。

## 開発

```bash
# デペンデンシーのインストール
yarn
# 起動
yarn start
# ビルド(具体的なビルドタイプは、ルートディレクトリのbuild.config.jsファイルで配置できます)
yarn build
```

## スペシャルサンクス

私にとって、健全なアプリケーションを開発のは初めてで、まだ右も左もわかりません。

このプロジェクトのファイル構造は、同じく Electron によって開発されたダウンロードツール [Motrix](https://motrix.app/) を参照しています。ありがとうございます。

アプリケーションをテストし、多くの提案を提供してくれた [笺染菲素](https://space.bilibili.com/33572615) に感謝します。

[HuiDesktop](https://github.com/HuiDesktop/HuiDesktop) の作成者 [pure01fx](https://github.com/pure01fx) による Spine のテクニカルサポートに感謝します。

[greenjerry](https://github.com/greenjerry) には、物質的、精神的、そしてソフトウェア、およびハードウェアで私をサポートしていただき、本当にありがとうございます。


================================================
FILE: README.md
================================================
# Hime Display

<p align="center">
<img width="200px" src="./images/icon.png">
</p>

> illustrated by [MakoSaikou](https://www.pixiv.net/users/72669923)

English | [简体中文](./README-CN.md) | [日本語](./README-JP.md)

[Download](https://hime.xdrv.cn/download/) | [Docs(Chinese Only)](https://hime.xdrv.cn/) | [Introduction Video](https://www.bilibili.com/video/BV1Me411u7pF)

Hime Display aims to create an open-source, cross-platform, universal desktop model presenter.

## Preview

### Control Panel

<p align="center">
<img width="450" src="./images/control-panel-en.png">
</p>

### Display Window

Can't see anything? that's right, the display window is just a transparent window.

## Features

1. Multiple Model Type Support: Supports loading Live2D, MMD, VRoid, Spine models.
2. Motion Capture: Provides motion capture support for Live2D, MMD, VRoid with the help of Google's MediaPipe.
3. Cross Platform: Supports Windows and macOS.
4. Multilingual support: Supports English, Simplified Chinese, and Japanese.
5. Full Model Control: Various operations can be performed on the model, including bone transformation, deformation, and animation playback.
6. Animation transition: MMD model can load animations from Mixamo directly (Plan to support VRoid).

## Basic Usage

### Design of model database

The application uses one or more paths as the model data source. It can recursively detect the model under these paths according to some model file features and add them to the database.

### Method to load models

1. Click `Source` in left row of the control panel.
2. `Add Data Source`, select the directory of models, motions, and audios.
3. Click `Refresh` in the source path operations.
4. Click `Model` in left row, select the model you want to load in the model database, the selected one will be highlighted.
5. Last step, Click `Load Selected Model` under the database.

### Attentions

1. Different types of models, motions, audios can be put in the same data source.
2. In order to improve efficiency and enhance generality, for most file types, the detection process does not read the content of the file, and mainly judges by the file extension. So even if the file has problems or is not supported, it may be loaded into the database.
3. For some types of models, their file names are usually not the model names, and the names of the upper-level directory of the model files will be used as the model names, so placing multiple model files in the same directory may be confusing.
4. For motions and audios, their file names are usually related to the contents, so the file names will be used as the names, and placeing them into one directory will not cause naming confusion.
5. After adding data source, you can click `Edit` and decide the search type. All types will be detected by default.
6. When the search is complete, it will automatically update the statistic info, model database, motion database, and audio database (the latter two are displayed in the animation control page of the selected and displayed 3D model)

## Implemented Features Comparison

|                    |           MMD           |        VRoid        |          Live2D           |           Spine           |
| :----------------: | :---------------------: | :-----------------: | :-----------------------: | :-----------------------: |
| Model Description  |           ✅            |         ✅          |            ✅             |            ✅             |
|  Object Transform  |           ✅            |         ✅          |            ✅             |            ✅             |
| Animation Control  |           ✅            | ❌<br/>(Developing) |            ✅             |            ✅             |
| Physics Simulation | ✅<br/>(Animation only) | ✅<br/>(All status) |   ❌<br/>(Considering)    |   ❌<br/>(Not support)    |
| Parameter Control  |          Morph          |        Morph        |    Parameter<br/>Part     |       ❌<br/>(TODO)       |
|    Face Capture    |           ✅            |         ✅          |            ✅             | ❌<br/>(No specification) |
|  Holistic Capture  |           ✅            |         ✅          | ❌<br/>(No specification) | ❌<br/>(No specification) |

## Main Techniques

This application mainly uses Front-end technology, based on [Electron](https://www.electronjs.org/), mainly uses [Vite](https://vitejs.dev/) as build tools.

Uses [lowdb](https://github.com/typicode/lowdb) as the database.

Multilingual support adopted [i18next](https://www.i18next.com/).

The control panel adopted [Vue](https://vuejs.org/) framework and [Element Plus](https://element-plus.org/) component library.

Uses [Pixi.js](https://pixijs.com/) as the rendering engine of 2D models, and the 3D models use [Three.js](https://threejs.org/).

Motion capture adopts Google's [MediaPipe](https://mediapipe.dev/), and adopts [Kalidokit](https://github.com/yeemachine/kalidokit) to analyse captured data.

## Develop

```bash
# Install dependencies
yarn
# start
yarn start
# build (The specific build version can be configured in the `build.config.js` file in the root directory)
yarn build
```

## Special Thanks

This is my first attempt to develop a full application, maybe there are some deficiencies.

The file structure of this application refers to a download tool [Motrix](https://motrix.app/) which is also developed by Electron.

Thanks to [笺染菲素](https://space.bilibili.com/33572615) for testing the application and providing many suggestions.

Thanks to [pure01fx](https://github.com/pure01fx), the author of [HuiDesktop](https://github.com/HuiDesktop/HuiDesktop) for some technical support on Spine.

Thanks to [greenjerry](https://github.com/greenjerry) for supporting me in material, spiritual, software and hardware.


================================================
FILE: build.config.js
================================================
/**
 * @type {import('electron-builder').CliOptions}
 * {@link https://www.electron.build/configuration/configuration}
 */
const options = {
  // targets: builder.createTargets([
  //   builder.Platform.WINDOWS,
  //   builder.Platform.MAC,
  // ]),
  // config: {
  productName: "Hime Display",
  directories: {
    output: "build",
  },
  // https://github.com/electron-userland/electron-builder/issues/5463
  // 太脑瘫了,electron-builder在使用GitHub Actions时必须手动指定不自动执行publish过程
  publish: null,
  files: ["dist/renderer/**/*", "dist/main/**/*"],
  // asar: false,
  dmg: {
    background: "public/background/background.tiff",
    window: {
      width: 540,
      height: 380,
    },
    contents: [
      {
        x: 410,
        y: 230,
        type: "link",
        path: "/Applications",
      },
      {
        x: 130,
        y: 230,
        type: "file",
      },
    ],
  },
  mac: {
    icon: "public/icons/icon.png",
    extendInfo: {
      // 现在的macOS应用想要访问摄像机等权限必须在此声明,i18n我是没本事做到这儿来了,因此就用英文了
      NSCameraUsageDescription:
        "Face mesh and holistic capturing need to access to your camera",
      "com.apple.security.device.camera": true,
    },
  },
  nsis: {
    oneClick: false,
    allowElevation: true,
    allowToChangeInstallationDirectory: true,
    createDesktopShortcut: true,
    createStartMenuShortcut: false,
  },
  win: {
    icon: "public/icons/icon.png",
    target: [
      {
        target: "nsis",
        arch: ["x64"],
      },
    ],
  },
  // linux: {
  //   icon: "public/icons",
  // },
  // },
};

module.exports = options;


================================================
FILE: package.json
================================================
{
  "name": "hime-display",
  "version": "1.2.0",
  "description": "A universal desktop model displayer for Live2D, Spine, MMD and VRoid.",
  "main": "./dist/main/main.cjs.js",
  "repository": {
    "type": "git",
    "url": "https://github.com/TSKI433/hime-display"
  },
  "author": "TSKI433",
  "license": "GPL-3.0",
  "private": true,
  "workspaces": {
    "packages": [
      "src/*"
    ]
  },
  "scripts": {
    "start": "node ./scripts/dev-runner",
    "build": "node ./scripts/build",
    "build:macos": "node ./scripts/build --macos",
    "build:windows": "node ./scripts/build --windows"
  },
  "dependencies": {
    "electron-is": "^3.0.0",
    "electron-log": "^5.3.4",
    "lowdb": "1.0.0"
  },
  "devDependencies": {
    "chalk": "^5.4.1",
    "electron": "^35.2.1",
    "electron-builder": "^26.0.12",
    "eslint": "^9.25.1",
    "eslint-config-prettier": "^10.1.2",
    "eslint-plugin-prettier": "^5.2.6",
    "eslint-plugin-vue": "^10.0.0",
    "listr": "^0.14.3",
    "vite": "^6.3.3"
  }
}


================================================
FILE: scripts/build.js
================================================
const path = require("path");
const chalk = require("chalk");
const ListR = require("listr");
const builder = require("electron-builder");
const { build: viteBuild, createLogger } = require("vite");

const builderConfig = require("../build.config");
const {
  MAIN_ROOT,
  MAIN_CONTROL_PRELOAD_ROOT,
  MAIN_DISPLAY_PRELOAD_ROOT,
  RENDERER_ROOT,
} = require("./constants");

const args = process.argv.slice(2);
let targets = null;
if (args.includes("--macos")) {
  targets = builder.Platform.MAC.createTarget();
} else if (args.includes("--windows")) {
  targets = builder.Platform.WINDOWS.createTarget();
} else {
  targets = builder.createTargets([
    builder.Platform.WINDOWS,
    builder.Platform.MAC,
  ]);
}

function build() {
  const tasks = new ListR([
    {
      title: "building renderer process",
      task: buildRenderer,
    },
    {
      title: "building main process",
      task: buildMainProcess(MAIN_ROOT),
    },
    {
      title: "building main control preload process",
      task: buildMainProcess(MAIN_CONTROL_PRELOAD_ROOT),
    },
    {
      title: "building main display preload process",
      task: buildMainProcess(MAIN_DISPLAY_PRELOAD_ROOT),
    },
  ]);

  tasks
    .run()
    .then(() => {
      builder.build({
        targets,
        config: builderConfig,
      });
    })
    .catch((error) => {
      createLogger().error(
        chalk.red(`error during build application:\n${error.stack}`)
      );
      process.exit(1);
    });
}

async function buildRenderer() {
  try {
    const rendererOutput = await viteBuild({
      root: RENDERER_ROOT,
      base: "./",
      build: {
        outDir: path.resolve(__dirname, "../dist/renderer"),
      },
    });
    return rendererOutput;
  } catch (error) {
    createLogger().error(
      chalk.red(`error during build renderer:\n${error.stack}`)
    );
    process.exit(1);
  }
}

function buildMainProcess(root) {
  return async function () {
    try {
      const buildOutput = await viteBuild({
        root,
        build: {
          outDir: path.resolve(__dirname, "../dist/main"),
        },
      });
      return buildOutput;
    } catch (error) {
      createLogger().error(
        chalk.red(`error during build main process:\n${error.stack}`)
      );
      process.exit(1);
    }
  };
}

build();


================================================
FILE: scripts/constants.js
================================================
const path = require("path");

module.exports = {
  MAIN_ROOT: path.resolve(__dirname, "../src/main"),
  // MAIN_PRELOAD_ROOT: path.resolve(__dirname, "../src/preload"),
  MAIN_CONTROL_PRELOAD_ROOT: path.resolve(__dirname, "../src/preload/control"),
  MAIN_DISPLAY_PRELOAD_ROOT: path.resolve(__dirname, "../src/preload/display"),
  RENDERER_ROOT: path.resolve(__dirname, "../src/renderer"),
};


================================================
FILE: scripts/dev-runner.js
================================================
const path = require("path");
const chalk = require("chalk");
const electron = require("electron");
const { spawn } = require("child_process");
const { createServer, createLogger, build } = require("vite");
const {
  MAIN_ROOT,
  MAIN_CONTROL_PRELOAD_ROOT,
  MAIN_DISPLAY_PRELOAD_ROOT,
  RENDERER_ROOT,
} = require("./constants");

let manualRestart;
let electronProcess;

async function startRenderer() {
  try {
    const viteServer = await createServer({
      root: RENDERER_ROOT,
    });
    await viteServer.listen();
    return viteServer;
  } catch (error) {
    createLogger().error(
      chalk.red(`error when starting dev server:\n${error.stack}`)
    );
  }
}

async function watchMainProcess(root) {
  try {
    const rollupWatcher = await build({
      root,
      mode: "development",
      build: {
        emptyOutDir: false,
        outDir: path.resolve(__dirname, "../dist/dev"),
        watch: true,
      },
    });
    return await new Promise((resolve, reject) => {
      rollupWatcher.on("event", (event) => {
        if (event.code === "BUNDLE_END") {
          resolve(rollupWatcher);
        }
      });
    });
  } catch (error) {
    createLogger().error(
      chalk.red(`error during watch main process:\n${error.stack}`)
    );
    process.exit(1);
  }
}

function startElectron(RENDERER_URL) {
  let args = [
    "--inspect=5858",
    path.join(__dirname, "../dist/dev/main.cjs.js"),
  ];

  if (process.env.npm_execpath.endsWith("yarn.js")) {
    args = args.concat(process.argv.slice(3));
  } else if (process.env.npm_execpath.endsWith("npm-cli.js")) {
    args = args.concat(process.argv.slice(2));
  }

  electronProcess = spawn(electron, args, {
    env: {
      ...process.env,
      RENDERER_URL,
    },
    stdio: "inherit",
  });

  electronProcess.on("close", () => {
    if (!manualRestart) process.exit();
  });
}

async function start() {
  const rendererServer = await startRenderer();
  const { port = 3000, https = false } = rendererServer.config.server;
  const RENDERER_URL = `http${https ? "s" : ""}://localhost:${port}`;

  const mainWatcher = await watchMainProcess(MAIN_ROOT);
  const mainControlPreloadWatcher = await watchMainProcess(
    MAIN_CONTROL_PRELOAD_ROOT
  );
  const mainDisplayPreloadWatcher = await watchMainProcess(
    MAIN_DISPLAY_PRELOAD_ROOT
  );

  startElectron(RENDERER_URL);

  const manageElectronProcess = (event) => {
    if (event.code !== "BUNDLE_END") {
      return;
    }

    if (electronProcess && electronProcess.kill) {
      manualRestart = true;
      process.kill(electronProcess.pid);
      electronProcess = null;
      startElectron(RENDERER_URL);

      setTimeout(() => {
        manualRestart = false;
      }, 5000);
    }
  };

  mainWatcher.on("event", manageElectronProcess);
  mainControlPreloadWatcher.on("event", manageElectronProcess);
  mainDisplayPreloadWatcher.on("event", manageElectronProcess);
}

start();


================================================
FILE: src/main/Application.js
================================================
import { EventEmitter } from "events";
import { WindowManager } from "./ui/WindowManager";
import { ThemeManager } from "./ui/ThemeManager";
import { TrayManager } from "./ui/TrayManager";
import fs from "fs";
import { Buffer } from "buffer";
import low from "lowdb";
import lowFileSync from "lowdb/adapters/FileSync";
import {
  APP_CONFIG_PATH,
  APP_DATA_PATH,
  CHROMIUM_PREFERENCE_PATH,
} from "./options/paths";
import { defaultConfig } from "@shared/defaults/defaultConfig";
import { ipcMain, dialog, systemPreferences, app } from "electron";
import is from "electron-is";
import i18next from "@shared/locales/i18next";

export class Application extends EventEmitter {
  constructor() {
    super();
    // this.isReady = false;
    this.init();
  }
  init() {
    this.setChromiumPreference();
    this.initConfigDB();
    this.initLanguage();
    this.initWindowManager();
    this.initThemeManager();
    this.initTrayManager();
    this.handleIpcMessages();
  }
  startApp() {
    // 为了实现展示器加载上一次的模型这种操作,控制面板必须要在启动应用的时候启动,只是show与hide的区别,而这个判断已经下方到windowManager里面去了
    this.openWindow("controlPanel");
    if (this.configDB.get(["general", "open-display-at-launch"]).value()) {
      this.openWindow(this.configDB.get(["display", "display-mode"]).value());
    }
    // win.once("ready-to-show", () => {
    // this.isReady = true;
    // this.emit("ready");
    // });
  }
  openWindow(windowName) {
    return this.windowManager.openWindow(windowName);
  }
  setChromiumPreference() {
    // 每一次启动应用时,将默认的开发者工具窗口设定为一个独立的窗口,防止全屏透明的展示器打开窗口内开发者工具的时候透明失效
    low(new lowFileSync(CHROMIUM_PREFERENCE_PATH))
      .set("electron.devtools.preferences.currentDockState", '"undocked"')
      .write();
  }
  initConfigDB() {
    this.configDB = low(new lowFileSync(APP_CONFIG_PATH));
    // 看样子lowdb的这个defaults只能浅层defaults,到第二级就不管用了
    this.configDB.defaults(defaultConfig).write();
  }
  initLanguage() {
    i18next.changeLanguage(this.configDB.get(["general", "language"]).value());
  }
  initWindowManager() {
    // 启动window时也需要读取配置数据库
    this.windowManager = new WindowManager(this.configDB);
  }
  initThemeManager() {
    this.themeManager = new ThemeManager();
    this.themeManager.on("system-theme-change", (theme) => {
      this.windowManager.sendMessageToWindow(
        "control",
        "main:update-theme",
        theme
      );
    });
  }
  initTrayManager() {
    this.trayManager = new TrayManager();
    this.trayManager.buildMenu();
    this.trayManager.on("tray:open-control-window", () => {
      // this.openWindow("controlPanel");
      // 更改机制,目前控制面板永远不会被关闭,只会隐藏
      this.windowManager.windows.control.show();
    });
    this.trayManager.on("tray:open-display-window", () => {
      this.openWindow(this.configDB.get(["display", "display-mode"]).value());
    });
    this.trayManager.on("tray:quit-app", () => {
      // this.windowManager.windows.control.destroy();
      // 使用before-quit事件来处理应用无法正确退出的问题,直接上exit实在是有点暴力
      app.quit();
    });
  }
  handleIpcMessages() {
    // 向子进程提供数据库存储目录
    ipcMain.on("control2main:query-data-path", (event) => {
      event.returnValue = APP_DATA_PATH;
    });
    ipcMain.on("control2main:query-system-theme", (event) => {
      event.returnValue = this.themeManager.getSystemTheme();
    });
    ipcMain.handle("control2main:select-path", (windowName) => {
      return dialog.showOpenDialogSync(this.windowManager.windows[windowName], {
        properties: ["openDirectory"],
      });
    });
    ipcMain.on("control2main:launch-display-window", () => {
      this.openWindow(this.configDB.get(["display", "display-mode"]).value());
    });
    ipcMain.on("control2main:relaunch-display-window", () => {
      // 使用destroy方法,防止使用close导致关闭窗口受阻
      this.windowManager.windows.display.destroy();
      this.openWindow(this.configDB.get(["display", "display-mode"]).value());
    });
    ipcMain.on("control2main:close-display-window", () => {
      this.windowManager.windows.display.destroy();
    });
    ipcMain.handle("control2main:query-window-ids", () => {
      // 因为关闭了新建窗口的this.allUpdateWindowIds();,对展示器的通知状态只能在这里进行
      this.windowManager.updateWindowIds("display");
      return this.windowManager.windowIds;
    });
    ipcMain.handle("display2main:query-window-ids", () => {
      // 控制面板有必要确认展示器的模型载入状态,刷新页面后模型也会变为未载入状态
      // 这里仅向控制面板发送消息,如果展示器发送消息,展示器的windowId在query状态同时成了update,会导致奇怪的问题,id直接变undefined了
      // 为实现启动展示器自动加载之前的模型,也必须这么设计,而且还要把主进程检测到窗口打开时的广播操作关了,因为这个时候新建的窗口可能还没有准备接收消息
      this.windowManager.updateWindowIds("control");
      return this.windowManager.windowIds;
    });
    ipcMain.handle("display2main:query-config", () => {
      return {
        config: this.configDB.value(),
        // 属于是让windowName搭个顺风车……免得初始化的时候多弄出一个通信来
        windowName: this.windowManager.windows.display.windowName,
      };
    });
    ipcMain.on("control2main:update-config", () => {
      this.configDB.read();
    });
    ipcMain.on("control2main:open-dev-tool", (event, type) => {
      if (
        type === "display" &&
        this.windowManager.windows.display.windowName === "displayFullScreen"
      ) {
        dialog
          .showMessageBox(this.windowManager.windows.control, {
            type: "info",
            message: i18next.t("message.display-open-dev-title"),
            detail: i18next.t("message.display-open-dev-detail"),
            buttons: [
              i18next.t("message.confirm"),
              i18next.t("message.cancel"),
            ],
            defaultId: 0,
            cancelId: 1,
          })
          .then((result) => {
            result.response === 0 &&
              this.windowManager.windows[type].webContents.openDevTools();
          });
      } else {
        this.windowManager.windows[type].webContents.openDevTools();
      }
    });
    ipcMain.handle("display2main:ask-for-media-access", () => {
      return this.askForMediaAccess();
    });
    ipcMain.on("display2main:set-ignore-mouse-events", (event, ...args) => {
      this.windowManager.windows.display.setIgnoreMouseEvents(...args);
    });
    ipcMain.on("control2main:change-language", (event, language) => {
      console.log("[Hime Display] change language to", language);
      i18next.changeLanguage(language);
      this.trayManager.buildMenu();
    });
    // 窗口之间的消息中转
    const routes = [
      ["display2control:model-control-info", "control"],
      ["display2control:send-to-model-control", "control"],
      ["display2control:send-display-window-state", "control"],
      ["display2control:error", "control"],
      ["control2display:load-model", "display"],
      ["control2display:send-to-model-manager", "display"],
      ["control2display:query-display-window-state", "display"],
      ["control2display:screenshot", "display"],
    ];
    routes.forEach(([channel, targetWindowKey]) => {
      ipcMain.on(channel, (event, ...args) => {
        const targetWindow = this.windowManager.windows[targetWindowKey];
        if (targetWindow) {
          targetWindow.webContents.send(channel, ...args);
        }
      });
    });
  }
  async askForMediaAccess() {
    if (is.macOS()) {
      return systemPreferences.askForMediaAccess("camera");
    } else {
      return true;
    }
  }
  quitApp() {}
}


================================================
FILE: src/main/Launcher.js
================================================
import { EventEmitter } from "events";
import { app } from "electron";
// import is from "electron-is";
import { ExceptionHandler } from "./core/ExceptionHandler";
import { logger } from "./core/Logger";
import { Application } from "./Application";
export class Launcher extends EventEmitter {
  constructor() {
    super();
    this.file = "";
    this.init();
  }

  init() {
    this.exceptionHandler = new ExceptionHandler();
    // this.openedAtLogin = is.macOS()
    //   ? app.getLoginItemSettings().wasOpenedAtLogin
    //   : false;
    // logger.info("[Hime Display] openedAtLogin:", this.openedAtLogin);
    this.handleAppEvents();
  }
  handleAppEvents() {
    app.on("ready", () => {
      this.application = new Application();
      this.application.startApp();
      // this.application.on("ready", () => {
      // this.sendFileToApplication();
      // });
    });
    app.on("activate", () => {
      if (this.application) {
        logger.info("[Hime Display] activate");
        // this.application.openWindow("controlPanel");
        this.application.windowManager.windows.control.show();
      }
    });
    // 为了实现缓存不被清理的效果,展示器的close事件的默认行为已经被阻止,若不对app执行exit,应用会因为展示器未关闭而不退出,这里在应用希望退出时强制关闭展示器来解决这个问题
    app.on("before-quit", () => {
      this.application.windowManager.windows.control.destroy();
    });
    app.on("will-quit", () => {
      logger.info("[Hime Display] will-quit");
      if (this.application) {
        this.application.quitApp();
      }
    });
    // 监听此事件后,将不会在所有窗口退出时自动退出
    app.on("window-all-closed", () => {});
  }
}


================================================
FILE: src/main/core/ExceptionHandler.js
================================================
import { app, dialog } from "electron";
import { logger } from "./Logger";
import is from "electron-is";
export class ExceptionHandler {
  constructor() {
    this.init();
  }
  init() {
    if (is.dev()) {
      return;
    }
    process.on("uncaughtException", (error) => {
      const { message, stack } = error;
      logger.error(`[Hime Display] Uncaught exception: ${message}`);
      logger.error(stack);
      dialog.showErrorBox("Hime Display Error: ", stack);
      app.quit();
    });
  }
}


================================================
FILE: src/main/core/Logger.js
================================================
import logger from "electron-log";
logger.info("[Hime Display] Logger init");
export { logger };


================================================
FILE: src/main/index.js
================================================
import { Launcher } from "./Launcher";
new Launcher();


================================================
FILE: src/main/menus/tray.js
================================================
export const trayMenuTemplate = [
  { locale: "tray.open-control-window", event: "tray:open-control-window" },
  { locale: "tray.open-display-window", event: "tray:open-display-window" },
  { locale: "tray.quit-app", event: "tray:quit-app" },
];


================================================
FILE: src/main/options/paths.js
================================================
import { app } from "electron";
import { resolve } from "path";
export const APP_DATA_PATH = app.getPath("userData");
export const APP_CONFIG_PATH = resolve(APP_DATA_PATH, "config.json");
export const APP_DATABASE_PATH = resolve(APP_DATA_PATH, "database.json");
export const CHROMIUM_PREFERENCE_PATH = resolve(APP_DATA_PATH, "Preferences");


================================================
FILE: src/main/options/windows.js
================================================
import { resolve } from "path";
import { DEV_SERVER_PORT } from "@shared/constants";
export const windowsOptions = {
  controlPanel: {
    attrs: {
      title: "Hime Display 控制面板",
      height: 600,
      width: 700,
      titleBarStyle: "hidden",
      vibrancy: "menu",
      autoHideMenuBar: true,
      titleBarOverlay: true,
      resizable: false,
      // visualEffectState: "active",
      // skipTaskbar: true,
      // 默认不显示,但必须启动
      show: false,
      webPreferences: {
        // nodeIntegration: true,
        // contextIsolation: false,
        // webSecurity: false,
        devTools: true,
        sandbox: false,
        preload: resolve(__dirname, "./control-preload.cjs.js"),
      },
    },
    url: import.meta.env.DEV
      ? `http://localhost:${DEV_SERVER_PORT}/control.html`
      : "file://" + resolve(__dirname, "../renderer/control.html"),
    dev: {
      autoOpenDevTool: false,
    },
    pageType: "control",
  },
  displayFullScreen: {
    attrs: {
      title: "Hime Display",
      frame: false, //去除边框
      hasShadow: false, //live2d模型会动,导致阴影出问题,所以干脆不要了
      transparent: true, //让窗口透明
      autoHideMenuBar: true,
      skipTaskbar: true,
      roundedCorners: false, //去除边角圆角,本来就是要占满整个屏幕的,stats面板被圆角弄掉一块实在有点难看
      webPreferences: {
        // nodeIntegration: true,
        // contextIsolation: false,
        // 便于访问本地文件
        webSecurity: false,
        devTools: true,
        preload: resolve(__dirname, "./display-preload.cjs.js"),
      },
    },
    url: import.meta.env.DEV
      ? `http://localhost:${DEV_SERVER_PORT}/display.html`
      : "file://" + resolve(__dirname, "../renderer/display.html"),
    dev: {
      autoOpenDevTool: false,
    },
    pageType: "display",
  },
  displayWindowed: {
    attrs: {
      title: "Hime Display",
      // frame: false, //去除边框
      // hasShadow: false, //live2d模型会动,导致阴影出问题,所以干脆不要了
      // transparent: true, //让窗口透明
      autoHideMenuBar: true,
      // skipTaskbar: true,
      webPreferences: {
        // nodeIntegration: true,
        // contextIsolation: false,
        webSecurity: false,
        devTools: true,
        preload: resolve(__dirname, "./display-preload.cjs.js"),
      },
    },
    url: import.meta.env.DEV
      ? `http://localhost:${DEV_SERVER_PORT}/display.html`
      : "file://" + resolve(__dirname, "../renderer/display.html"),
    dev: {
      autoOpenDevTool: false,
    },
    pageType: "display",
  },
};


================================================
FILE: src/main/package.json
================================================
{
  "name": "@app/main",
  "version": "0.0.0",
  "dependencies": {
    "electron": "^35.2.1",
    "electron-is": "^3.0.0",
    "electron-log": "^5.3.4",
    "lowdb": "1.0.0"
  },
  "devDependencies": {
    "rollup-plugin-auto-external": "^2.0.0",
    "vite": "^6.3.3"
  }
}


================================================
FILE: src/main/ui/ThemeManager.js
================================================
import { nativeTheme } from "electron";
import { EventEmitter } from "events";
export class ThemeManager extends EventEmitter {
  constructor() {
    super();
    this.init();
  }
  init() {
    this.handelEvents();
  }
  handelEvents() {
    nativeTheme.on("updated", () => {
      this.emit("system-theme-change", this.getSystemTheme());
    });
  }
  getSystemTheme() {
    return nativeTheme.shouldUseDarkColors ? "dark" : "light";
  }
}


================================================
FILE: src/main/ui/TrayManager.js
================================================
import i18next from "@shared/locales/i18next";
import { trayMenuTemplate } from "../menus/tray";
import { Tray, Menu } from "electron";
import path from "path";
import { EventEmitter } from "events";
import is from "electron-is";
// 我其实已经注意到macOS上显示的菜单为英语了,之所以没有对其进行处理,是因为这个应用用不到那个菜单,但是如果把菜单弄成null的话,默认注册的快捷键会失效,复制粘贴什么都用不了,所以直接懒得干了
export class TrayManager extends EventEmitter {
  constructor() {
    super();
    this.template = trayMenuTemplate;
    if (is.macOS()) {
      this.tray = new Tray(
        path.resolve(__dirname, "./assets/trayTemplate.png")
      );
    } else {
      this.tray = new Tray(path.resolve(__dirname, "./assets/trayWindows.png"));
    }
  }
  translateTemplate() {
    for (const item of this.template) {
      item.label = i18next.t(item.locale);
      item.click = () => {
        this.emit(item.event);
      };
    }
  }
  buildMenu() {
    this.translateTemplate();
    this.menu = Menu.buildFromTemplate(this.template);
    this.tray.setContextMenu(this.menu);
  }
}


================================================
FILE: src/main/ui/WindowManager.js
================================================
import { EventEmitter } from "events";
import { windowsOptions } from "../options/windows";
import { BrowserWindow } from "electron";
import { logger } from "../core/Logger";
import is from "electron-is";
export class WindowManager extends EventEmitter {
  constructor(configDB) {
    super();
    this.configDB = configDB;
    this.windows = {
      control: null,
      display: null,
    };
    this.windowIds = {
      control: -1,
      display: -1,
    };
  }
  openWindow(windowName) {
    const pageOptions = windowsOptions[windowName];
    const pageType = pageOptions.pageType;
    if (this.windows[pageType] !== null) {
      // return new Error(`${pageType} window opened again before set to null`);
      // this.windows[pageType].show();
      return this.windows[pageType];
    }
    const window = new BrowserWindow(pageOptions.attrs);
    logger.info(
      `[Hime Display] new window created, windowName: ${windowName}, ID: ${window.webContents.id}`
    );
    // 此标识主要用于展示器判断自身类型
    window.windowName = windowName;
    this.windows[pageType] = window;
    this.windowIds[pageType] = window.webContents.id;
    window.loadURL(pageOptions.url);
    if (import.meta.env.DEV && pageOptions.dev.autoOpenDevTool) {
      window.webContents.openDevTools();
    }
    window.on("closed", () => {
      this.windows[pageType] = null;
      this.windowIds[pageType] = -1;
      this.allUpdateWindowIds();
    });
    if (windowName === "displayFullScreen") {
      window.maximize();
      window.setIgnoreMouseEvents(true, {
        forward: true,
      });
      if (this.configDB.get(["display", "keep-display-at-top"]).value()) {
        // 之前这个级别太高了,搞不好会出大问题……
        // window.setAlwaysOnTop(true, "screen-saver", 1);
        // 对于macOS而言,默认的层级已经足够了,但Windows在该层级下无法置顶
        if (is.macOS()) {
          window.setAlwaysOnTop(true);
        } else {
          window.setAlwaysOnTop(true, "screen-saver");
        }
      }

      switch (this.configDB.get(["display", "display-range"]).value()) {
        case "singleDesktop": {
          break;
        }
        case "allDesktops": {
          window.setVisibleOnAllWorkspaces(true);
          break;
        }
        case "allWorkspaces": {
          window.setVisibleOnAllWorkspaces(true, {
            visibleOnFullScreen: true, //在所有窗口上显示,全屏应用也不例外,目前已证实这个操作会带来一些问题,例如菜单栏无法正确显示,好像跟内部的进程转换有关
            // 实测该项目设定为true时,在全屏状态下窗口不会显示
            // skipTransformProcessType: true,
          });
          break;
        }
      }
    }
    if (windowName === "controlPanel") {
      if (this.configDB.get(["general", "open-control-at-launch"]).value()) {
        window.once("ready-to-show", () => {
          window.show();
        });
      }
      //保持display窗口一直处于聚焦状态,以处理鼠标事件
      window.on("blur", () => {
        if (this.windows.display?.windowName === "displayFullScreen") {
          this.windows.display.focus();
        }
      });
      // 更改机制,目前控制面板永远不会被关闭,只会隐藏
      window.on("close", (event) => {
        event.preventDefault();
        window.hide();
      });
    }
    // 为实现启动展示器自动加载之前的模型,需要在这里关闭事件通知,因为展示器窗口是在启动触发下方函数时,展示器只是开始加载了,并不一定准备好了接受消息,这时告知控制面板展示器已经准备好了的话,控制面板发送的消息无法被接收到
    // this.allUpdateWindowIds();
    return this.windows[pageType];
  }
  sendMessageToWindow(windowName, message, ...args) {
    const window = this.windows[windowName];
    if (window === null) {
      return;
    }
    logger.info(`[Hime Display] send to ${windowName}: ${message}`, ...args);
    window.webContents.send(message, ...args);
  }
  allUpdateWindowIds() {
    Object.keys(this.windows).forEach((key) => {
      this.updateWindowIds(key);
    });
  }
  updateWindowIds(windowName) {
    this.sendMessageToWindow(
      windowName,
      "main2control&display:update-window-ids",
      this.windowIds
    );
  }
  // 备选方案,使用MessageChannel实现两个渲染进程的通信
  // buildMessagePort() {
  //   const { port1, port2 } = new MessageChannel();
  //   this.windows.control.webContents.postMessage("buildMessagePort", null, [
  //     port1,
  //   ]);
  //   this.windows.display.webContents.postMessage("buildMessagePort", null, [
  //     port2,
  //   ]);
  // }
}


================================================
FILE: src/main/vite.config.js
================================================
import { resolve } from "path";
import { defineConfig } from "vite";
import autoExternal from "rollup-plugin-auto-external";

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    lib: {
      entry: resolve(__dirname, "./index.js"),
      name: "main",
      formats: ["cjs"],
      fileName: (format) => `main.${format}.js`,
    },
    rollupOptions: {
      plugins: [
        autoExternal({
          packagePath: resolve(__dirname, "./package.json"),
        }),
      ],
    },
  },
  resolve: {
    alias: {
      "@shared": resolve(__dirname, "../shared"),
    },
  },
});


================================================
FILE: src/preload/control/config.js
================================================
// 几经考虑,还是把配置数据库也搬到控制面板了,IPC通信实在是麻烦了,不如直接在控制面板的preload中加载数据库
import low from "lowdb";
import lowFileSync from "lowdb/adapters/FileSync";
import path from "path";
import { APP_DATA_PATH } from "./paths";
import { ipcRenderer } from "electron";
import { defaultConfig } from "@shared/defaults/defaultConfig";
const APP_CONFIG_PATH = path.join(APP_DATA_PATH, "config.json");
const db = low(new lowFileSync(APP_CONFIG_PATH));
// 不是我想重复写代码,这个config和database绝对用不了class的继承,preload暴露的对象直接把原型链全灭了,所以只能一个一个写函数,也不用class了
export function value() {
  return db.value();
}
export function write(value, data) {
  db.set(value, data).write();
  // display从主进程请求配置,还得通知主进程更新一下
  ipcRenderer.send("control2main:update-config");
}
export function resetAllConfig() {
  db.setState(defaultConfig).write();
  ipcRenderer.send("control2main:update-config");
}


================================================
FILE: src/preload/control/database.js
================================================
// 由于数据库仅在控制面板使用而不在主进程以及展示器使用,决定直接在控制面板的preload中加载数据库,减少IPC通信,优化性能
import low from "lowdb";
import lowFileSync from "lowdb/adapters/FileSync";
import fs from "fs";
import util from "util";
import path from "path";
import { defalutDatabase } from "@shared/defaults/defalutDatabase";
import { APP_DATA_PATH } from "./paths";
import { detectSpineVersionFromBinary } from "./utils";
const APP_DATABASE_PATH = path.join(APP_DATA_PATH, "database.json");
const db = low(new lowFileSync(APP_DATABASE_PATH));
db.defaults(defalutDatabase).write();
export function value() {
  return db.value();
}
export function write(value, data) {
  db.set(value, data).write();
}
export function removeDataFromSourcePath(sourcePath) {
  // 不愧是lodash,极致精简语法,remove({sourcePath}),优雅啊
  // 从本源来讲,要追溯到_.matches,然后再到_.isMatch,然后再搭配上ES6的对象属性简写,最终浓缩成这个简单的语句
  ["model", "motion3D", "audio3D"].forEach((type) => {
    db.get(type).remove({ sourcePath }).write();
  });
}
export async function loadDataFromSourcePathInfo(sourcePathInfo) {
  // 已改变载入机制
  // removeRemovedSourceTypeData(sourcePathInfo);
  // await removeDeletedData(sourcePathInfo.sourcePath);

  removeDataFromSourcePath(sourcePathInfo.sourcePath);
  // 这里的await后面虽然没有任何操作,但是还是必要的,因为可以推住Promise的resolve时机,确保控制面板载入刷新以后的数据
  await loadDataFromPath(
    sourcePathInfo.sourcePath,
    sourcePathInfo.sourceTypes,
    sourcePathInfo.sourcePath
  );
}
// 造了半天我在造个寂寞,跟异步同步扯了半天有意思吗?改变思路,直接把刷新数据源的相关数据全删了重载
// // 若更改过一个数据源的sourceTypes,需要删除一些原来sourceType允许载入的数据
// function removeRemovedSourceTypeData(sourcePathInfo) {
//   db.get("model")
//     .remove(
//       (item) =>
//         item.sourcePath === sourcePathInfo.sourcePath &&
//         !sourcePathInfo.sourceTypes[item.modelType]
//     )
//     .write();
//   if (!sourcePathInfo.sourceTypes.motion3D) {
//     db.get("motion3D")
//       .remove({ sourcePath: sourcePathInfo.sourcePath })
//       .write();
//   }
//   if (!sourcePathInfo.sourceTypes.audio3D) {
//     db.get("audio3D").remove({ sourcePath: sourcePathInfo.sourcePath }).write();
//   }
// }
// // 移除目录中被删除的模型数据
// function removeDeletedData(sourcePath) {
//   const promises = [];
//   ["model", "motion3D", "audio3D"].forEach((type) => {
//     db.get(type)
//       .value()
//       .forEach((item) => {
//         if (item.sourcePath === sourcePath) {
//           promises.push(
//             new Promise((resolve) => {
//               fs.access(
//                 item.entranceFile.slice(7).split("/").join(path.sep),
//                 fs.constants.F_OK,
//                 (err) => {
//                   console.log(item.entranceFile, err);
//                   if (err) {
//                     console.log(`${item.entranceFile} is deleted`);
//                     db.get(type)
//                       .remove({ entranceFile: item.entranceFile })
//                       .write();
//                   }
//                   // 又被坑了,resolve一定要放在if之后,不然一些promise一直没有resolve,导致程序卡在这个程序的await上。
//                   resolve();
//                 }
//               );
//             })
//           );
//         }
//       });
//   });
//   return Promise.all(promises);
// }

// 后面这些函数里面带的sourcePath都是最原始,不受递归影响的那个sourcePath,用于判断一个模型由哪个源检索到的,方便跟随删除
async function loadDataFromPath(dataPath, sourceTypes, sourcePath) {
  //根据文件路径读取文件,返回文件列表
  // 全部使用箭头函数,确保this对象可以传进去
  const files = await util.promisify(fs.readdir)(dataPath);
  let promises = [];
  //遍历读取到的文件列表
  // 为了保证顶级的Promise在所有目录读取结束后再返回,这里无法使用forEach,因为这样以来就无法await了,直接在里面forEach里面async整活也做不到让顶级的一步函数等着
  for (const filename of files) {
    //获取当前文件的绝对路径
    const dir = path.join(dataPath, filename);
    //根据文件路径获取文件信息,返回一个fs.Stats对象
    const stats = await util.promisify(fs.stat)(dir);
    const isFile = stats.isFile(); //是文件
    const isDir = stats.isDirectory(); //是文件夹
    if (isFile) {
      //是文件
      // 这里也需要加到promise里面,不然会出现还没有检索完成,整个promise就已经resolve了,导致后面的数据没有载入
      promises.push(detectDatabaseItem(dir, sourceTypes, sourcePath));
    }
    if (isDir) {
      //递归,如果是文件夹,就继续遍历该文件夹下面的文件
      // 这里不能在push里面写await,Promise.all应该接收一个Promise的列表
      promises.push(loadDataFromPath(dir, sourceTypes, sourcePath));
      // 这样写的话和同步都没有区别了
      // await this.refreshModelDB(dir);
    }
  }
  // console.log(sourcePath);
  // 异步的关键
  return Promise.all(promises);
}
async function detectDatabaseItem(fileDir, sourceTypes, sourcePath) {
  const extensionName = path.extname(fileDir);
  switch (extensionName) {
    case ".json": {
      // 回调函数往上无法嵌套,转换成Promise
      const fileData = await util.promisify(fs.readFile)(fileDir);
      let fileJson;
      try {
        fileJson = JSON.parse(fileData.toString());
        if (sourceTypes["Live2D"]) {
          processLive2dJson(fileDir, fileJson, sourcePath);
        }
        if (sourceTypes["Spine"]) {
          processSpineJson(fileDir, fileJson, sourcePath);
        }
      } catch (e) {
        console.warn(`File ${fileDir} is not a valid json file`);
      }
      break;
    }
    case ".pmx": {
      if (sourceTypes["MMD"]) {
        processPmx(fileDir, sourcePath);
      }
      break;
    }
    case ".vrm": {
      if (sourceTypes["VRoid"]) {
        processVrm(fileDir, sourcePath);
      }
      break;
    }
    case ".skel": {
      if (sourceTypes["Spine"]) {
        const fileData = await util.promisify(fs.readFile)(fileDir);
        processSkel(fileDir, sourcePath, fileData);
      }
      break;
    }
    case ".vmd": {
      if (sourceTypes["motion3D"]) {
        processVmd(fileDir, sourcePath);
      }
      break;
    }
    case ".fbx": {
      if (sourceTypes["motion3D"]) {
        processFbx(fileDir, sourcePath);
      }
      break;
    }
    case ".wav": {
      if (sourceTypes["audio3D"]) {
        processWav(fileDir, sourcePath);
      }
      break;
    }
    case ".mp3": {
      if (sourceTypes["audio3D"]) {
        processMp3(fileDir, sourcePath);
      }
      break;
    }
  }
}
function processLive2dJson(fileDir, fileJson, sourcePath) {
  if ("model" in fileJson) {
    writeModelInfo({
      name: splitDirName(fileDir),
      modelType: "Live2D",
      extensionName: "moc",
      entranceFile: resolveEntrancePath(fileDir),
      themeColor: "#ff6e2d",
      sourcePath,
      // has_motion: "motions" in fileJson ? true : false;
    });
  } else if ("FileReferences" in fileJson) {
    writeModelInfo({
      name: splitDirName(fileDir),
      modelType: "Live2D",
      extensionName: "moc3",
      entranceFile: resolveEntrancePath(fileDir),
      themeColor: "#ff6e2d",
      sourcePath,
      // has_motion:"Motions" in fileJson.FileReferences ? true : false
    });
  }
}
function processPmx(fileDir, sourcePath) {
  writeModelInfo({
    name: splitDirName(fileDir),
    modelType: "MMD",
    extensionName: "pmx",
    entranceFile: resolveEntrancePath(fileDir),
    themeColor: "#39c5bb",
    sourcePath,
  });
}
function processVrm(fileDir, sourcePath) {
  writeModelInfo({
    name: splitDirName(fileDir),
    modelType: "VRoid",
    extensionName: "vrm",
    entranceFile: resolveEntrancePath(fileDir),
    themeColor: "#ffec00",
    sourcePath,
  });
}
// todo: spine模型比较特殊,即使是加载模型,版本也不向下兼容……因此之后有必要进一步对模型版本进行判断
function processSkel(fileDir, sourcePath, fileData) {
  const version = detectSpineVersionFromBinary(fileData);
  writeModelInfo({
    name: splitDirName(fileDir),
    modelType: "Spine",
    extensionName: "skel",
    entranceFile: resolveEntrancePath(fileDir),
    themeColor: "#3fa9f5",
    sourcePath,
    version,
  });
}
function processSpineJson(fileDir, fileJson, sourcePath) {
  if ("skeleton" in fileJson && "spine" in fileJson.skeleton) {
    writeModelInfo({
      name: splitDirName(fileDir),
      modelType: "Spine",
      extensionName: "json",
      entranceFile: resolveEntrancePath(fileDir),
      themeColor: "#3fa9f5",
      sourcePath,
      version: fileJson.skeleton.spine,
    });
  }
}
function processVmd(fileDir, sourcePath) {
  writeMotion3DInfo({
    // 根据我在B碗上的下载经验,有一些配布中都会带有多个版本的vmd,这些文件的名称都不是曲名,但没有办法,只能让用户手动改一下文件名了
    name: path.basename(fileDir),
    extensionName: "vmd",
    entranceFile: resolveEntrancePath(fileDir),
    sourcePath,
  });
}
function processFbx(fileDir, sourcePath) {
  writeMotion3DInfo({
    name: path.basename(fileDir),
    extensionName: "fbx",
    entranceFile: resolveEntrancePath(fileDir),
    sourcePath,
  });
}
function processWav(fileDir, sourcePath) {
  writeAudio3DInfo({
    name: path.basename(fileDir),
    extensionName: "wav",
    entranceFile: resolveEntrancePath(fileDir),
    sourcePath,
  });
}
function processMp3(fileDir, sourcePath) {
  writeAudio3DInfo({
    name: path.basename(fileDir),
    extensionName: "mp3",
    entranceFile: resolveEntrancePath(fileDir),
    sourcePath,
  });
}
// 因为有些模型入口文件名完全没有辨识度,如model.json,以模型入口文件的的上级目录名作为模型名称
function splitDirName(fileDir) {
  // 同时切分Windows和UNIX路径
  return path.dirname(fileDir).split("/").pop().split("\\").pop();
}
// Windows下使用file:会导致路径出错,热重载开发环境下不使用file:会导致路径报错
// Windows的路径斜杠导致MMD和Spine模型无法加载,这里统一又进行了一次斜杠的替换……Windows我忍你很久了啊,光在这个路径上这已经是第三次出问题了
function resolveEntrancePath(fileDir) {
  return (
    (import.meta.env.DEV ? "file:///" : "") +
    path.resolve(fileDir).split(path.sep).join("/")
  );
}
function writeModelInfo(modelInfo) {
  //  防止重复写入模型数据
  // 现在以模型入口文件的路径作为唯一标识,如果已经存在,则不再写入。不直接用motionInfo是考虑到万一有人载入了具有包含关系的多个源路径,这会导致模型重复写入
  if (
    db
      .get("model")
      .findIndex((item) => item.entranceFile === modelInfo.entranceFile)
      .value() == -1
  ) {
    db.get("model").push(modelInfo).write();
  }
}
function writeMotion3DInfo(motionInfo) {
  if (
    db
      .get("motion3D")
      .findIndex((item) => item.entranceFile === motionInfo.entranceFile)
      .value() == -1
  ) {
    db.get("motion3D").push(motionInfo).write();
  }
}
function writeAudio3DInfo(audioInfo) {
  if (
    db
      .get("audio3D")
      .findIndex((item) => item.entranceFile === audioInfo.entranceFile)
      .value() == -1
  ) {
    db.get("audio3D").push(audioInfo).write();
  }
}


================================================
FILE: src/preload/control/index.js
================================================
import { contextBridge } from "electron";
import { shell } from "electron";
import * as database from "./database";
import * as config from "./config";
import * as ipc from "./ipc";
import "./theme";
contextBridge.exposeInMainWorld("nodeAPI", {
  database,
  config,
  ipc,
  showInFolder,
  openLink,
});
function showInFolder(path) {
  shell.showItemInFolder(path);
}
function openLink(link) {
  shell.openExternal(link);
}


================================================
FILE: src/preload/control/ipc.js
================================================
import { ipcRenderer } from "electron";
export function selectPath() {
  return ipcRenderer.invoke("control2main:select-path", "controlPanel");
}
export function launchDisplayWindow() {
  ipcRenderer.send("control2main:launch-display-window");
}
export function relaunchDisplayWindow() {
  ipcRenderer.send("control2main:relaunch-display-window");
}
export function closeDisplayWindow() {
  ipcRenderer.send("control2main:close-display-window");
}
export function queryWindowIds() {
  return ipcRenderer.invoke("control2main:query-window-ids");
}
export function handleUpdateWindowIds(callback) {
  ipcRenderer.on("main2control&display:update-window-ids", callback);
}
export function receiveModelControlInfo(callback) {
  ipcRenderer.once("display2control:model-control-info", callback);
}
export function handleSendToModelControl(callback) {
  console.log("handleSendToModelControl");
  ipcRenderer.on("display2control:send-to-model-control", callback);
}
export function removeManagerListeners() {
  ipcRenderer.removeAllListeners("display2control:send-to-model-control");
}
export function openDevTool(type) {
  ipcRenderer.send("control2main:open-dev-tool", type);
}
export function changeLanguage(language) {
  ipcRenderer.send("control2main:change-language", language);
}
export function handleDisplayWindowState(callback) {
  ipcRenderer.once("display2control:send-display-window-state", callback);
}
export function handleDisplayWindowError(callback) {
  ipcRenderer.on("display2control:error", callback);
}

export function loadModel(modelInfo) {
  ipcRenderer.send("control2display:load-model", modelInfo);
}

export function sendToModelManager(message) {
  ipcRenderer.send("control2display:send-to-model-manager", message);
}

export function queryDisplayWindowState() {
  ipcRenderer.send("control2display:query-display-window-state");
}
export function screenshot() {
  ipcRenderer.send("control2display:screenshot");
}


================================================
FILE: src/preload/control/paths.js
================================================
import { ipcRenderer } from "electron";
// console.time("control:query-database-path");
// 应用的许多后续操作必须要等到数据库加载完成,若使用异步请求可能有一定概率导致无法访问数据库报错
// 毕竟涉及到主进程通信,能少一次算一次,数据库路径到后方再拼接吧
export const APP_DATA_PATH = ipcRenderer.sendSync(
  "control2main:query-data-path"
);
// console.timeEnd("control:query-database-path");


================================================
FILE: src/preload/control/theme.js
================================================
import { ipcRenderer } from "electron";
// document.addEventListener("DOMContentLoaded", () => {
//   ipcRenderer.invoke("control2main:query-system-theme").then((theme) => {
// updateTheme(theme);
//   });
// });
// 经测试,采用异步函数加载深色主题时,会出现又浅色到深色主题的闪烁,因此只能改用同步阻塞函数
// 放到DOMContentLoaded之前有助于减少等待时长,虽然说相对于DOMContentLoaded完成所花的几百甚至一千多ms来讲,这里省下的约0.5ms可能什么都不是
// console.time("control2main:query-system-theme");
const theme = ipcRenderer.sendSync("control2main:query-system-theme");
// 不放在DOMContentLoaded事件之后会导致document.documentElement为null
document.addEventListener("DOMContentLoaded", () => {
  // console.timeEnd("control2main:query-system-theme");
  updateTheme(theme);
});
ipcRenderer.on("main:update-theme", (evnet, theme) => {
  updateTheme(theme);
});
function updateTheme(theme) {
  if (theme === "dark") {
    document.documentElement.className = "dark";
  } else if (theme === "light") {
    document.documentElement.className = "";
  }
}


================================================
FILE: src/preload/control/utils.js
================================================
export function detectSpineVersionFromBinary(dataToParse) {
  const versionOld = readSpineVersionOldFormat(dataToParse);
  if (isSpineValidVersion(versionOld)) {
    return versionOld;
  }

  const versionNew = readSpineVersionNewFormat(dataToParse);
  if (isSpineValidVersion(versionNew)) {
    return versionNew;
  }
  return "Unknown";
}

function readSpineVersionOldFormat(dataToParse) {
  const input = new SpineBinaryInput(dataToParse);
  let version = "";

  try {
    input.readString();
    version = input.readString();
  } catch (e) {
    version = "";
  }

  return version;
}

function readSpineVersionNewFormat(dataToParse) {
  const input = new SpineBinaryInput(dataToParse);
  let version = "";

  try {
    input.readInt32();
    input.readInt32();
    version = input.readString();
  } catch (e) {
    version = "";
  }

  return version;
}
function isSpineValidVersion(version) {
  return typeof version === "string" && /^\d+\.\d+\.\d+$/.test(version);
}

class SpineBinaryInput {
  constructor(
    data,
    strings = new Array(),
    index = 0,
    buffer = new DataView(data.buffer)
  ) {
    this.data = data;
    this.strings = strings;
    this.index = index;
    this.buffer = buffer;
  }

  readByte() {
    return this.buffer.getInt8(this.index++);
  }

  readUnsignedByte() {
    return this.buffer.getUint8(this.index++);
  }

  readShort() {
    const value = this.buffer.getInt16(this.index);

    this.index += 2;

    return value;
  }

  readInt32() {
    const value = this.buffer.getInt32(this.index);

    this.index += 4;

    return value;
  }

  readInt(optimizePositive) {
    let b = this.readByte();
    let result = b & 0x7f;

    if ((b & 0x80) != 0) {
      b = this.readByte();
      result |= (b & 0x7f) << 7;
      if ((b & 0x80) != 0) {
        b = this.readByte();
        result |= (b & 0x7f) << 14;
        if ((b & 0x80) != 0) {
          b = this.readByte();
          result |= (b & 0x7f) << 21;
          if ((b & 0x80) != 0) {
            b = this.readByte();
            result |= (b & 0x7f) << 28;
          }
        }
      }
    }

    return optimizePositive ? result : (result >>> 1) ^ -(result & 1);
  }

  readStringRef() {
    const index = this.readInt(true);

    return index == 0 ? null : this.strings[index - 1];
  }

  readString() {
    let byteCount = this.readInt(true);

    switch (byteCount) {
      case 0:
        return null;
      case 1:
        return "";
    }
    byteCount--;
    let chars = "";

    for (let i = 0; i < byteCount; ) {
      const b = this.readUnsignedByte();

      switch (b >> 4) {
        case 12:
        case 13:
          chars += String.fromCharCode(
            ((b & 0x1f) << 6) | (this.readByte() & 0x3f)
          );
          i += 2;
          break;
        case 14:
          chars += String.fromCharCode(
            ((b & 0x0f) << 12) |
              ((this.readByte() & 0x3f) << 6) |
              (this.readByte() & 0x3f)
          );
          i += 3;
          break;
        default:
          chars += String.fromCharCode(b);
          i++;
      }
    }

    return chars;
  }

  readFloat() {
    const value = this.buffer.getFloat32(this.index);

    this.index += 4;

    return value;
  }

  readBoolean() {
    return this.readByte() != 0;
  }
}


================================================
FILE: src/preload/control/vite.config.js
================================================
import { resolve } from "path";
import { defineConfig } from "vite";
import autoExternal from "rollup-plugin-auto-external";

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    lib: {
      entry: resolve(__dirname, "./index.js"),
      name: "main",
      formats: ["cjs"],
      fileName: (format) => `control-preload.${format}.js`,
    },
    rollupOptions: {
      plugins: [
        autoExternal({
          packagePath: resolve(__dirname, "../package.json"),
        }),
      ],
    },
  },
  resolve: {
    alias: {
      "@shared": resolve(__dirname, "../../shared"),
    },
  },
});


================================================
FILE: src/preload/display/index.js
================================================
import { contextBridge } from "electron";
import * as ipc from "./ipc";
contextBridge.exposeInMainWorld("nodeAPI", {
  ipc,
});


================================================
FILE: src/preload/display/ipc.js
================================================
import { ipcRenderer } from "electron";
export function handleLoadModel(callback) {
  ipcRenderer.on("control2display:load-model", callback);
}
export function queryWindowIds() {
  return ipcRenderer.invoke("display2main:query-window-ids");
}
export function handleUpdateWindowIds(callback) {
  ipcRenderer.on("main2control&display:update-window-ids", callback);
}
export function queryConfig() {
  // 尬住了,这里请求配置是后续操作的基础,必须要用同步请求
  // 然而electron的API里,ipcRenderer有sendTo,但是没有sendSyncTo,也没有invokeTo……用成sendTo本来就是考虑到之后通信频率比较高,不想走主进程的中继,这里请求要等待相应,实在没办法,不然要实现类似invokeTo的话,大概得这么写:
  // return new Promise((resolve, reject) => {
  //   ipcRenderer.sendTo(controlWindowId, "display2main:query-config");
  //   ipcRenderer.once("control-resopnce:query-config", (event, config) => {
  //     resolve(config);
  //   });
  // });
  // config数据主进程也有,这里还是invoke主进程吧
  return ipcRenderer.invoke("display2main:query-config");
}

export function handleSendToModelManager(callback) {
  ipcRenderer.on("control2display:send-to-model-manager", callback);
}
export function askForMediaAccess() {
  return ipcRenderer.invoke("display2main:ask-for-media-access");
}
export function setIgnoreMouseEvents(...args) {
  ipcRenderer.send("display2main:set-ignore-mouse-events", ...args);
}

export function handleQueryDisplayWindowState(callback) {
  ipcRenderer.on("control2display:query-display-window-state", callback);
}

export function sendModelControlInfo(modelControlInfo) {
  ipcRenderer.send("display2control:model-control-info", modelControlInfo);
}

export function sendToModelControl(message) {
  ipcRenderer.send("display2control:send-to-model-control", message);
}

export function sendDisplayWindowState(state) {
  ipcRenderer.send("display2control:send-display-window-state", state);
}

export function throwError(message) {
  ipcRenderer.send("display2control:error", message);
}

export function handleScreenshot(callback) {
  ipcRenderer.on("control2display:screenshot", callback);
}


================================================
FILE: src/preload/display/vite.config.js
================================================
import { resolve } from "path";
import { defineConfig } from "vite";
import autoExternal from "rollup-plugin-auto-external";

// https://vitejs.dev/config/
export default defineConfig({
  build: {
    lib: {
      entry: resolve(__dirname, "./index.js"),
      name: "main",
      formats: ["cjs"],
      fileName: (format) => `display-preload.${format}.js`,
    },
    rollupOptions: {
      plugins: [
        autoExternal({
          packagePath: resolve(__dirname, "../package.json"),
        }),
      ],
    },
  },
});


================================================
FILE: src/preload/package.json
================================================
{
  "name": "@app/preload",
  "version": "0.0.0",
  "dependencies": {
    "electron": "^35.2.1",
    "lowdb": "1.0.0"
  },
  "devDependencies": {
    "rollup-plugin-auto-external": "^2.0.0",
    "vite": "^6.3.3"
  }
}


================================================
FILE: src/renderer/control/App.vue
================================================
<template>
  <div class="drag-area"></div>
  <el-config-provider :locale="locale">
    <el-container>
      <hime-menu></hime-menu>
      <hime-main></hime-main>
    </el-container>
  </el-config-provider>
</template>

<script setup>
import throttle from "lodash/throttle";
import HimeMenu from "@control/components/Menu/Index.vue";
import HimeMain from "@control/components/Main.vue";
import { useAppStore } from "@control/store/app";
import { useControlStore } from "@control/store/control";
import { useTranslation } from "i18next-vue";
import zhCn from "element-plus/dist/locale/zh-cn.mjs";
import en from "element-plus/dist/locale/en.mjs";
import ja from "element-plus/dist/locale/ja.mjs";
// 发现element-plus的bug,使用自动引入ElMessage的方式会导致非深色模式下主题色被覆盖,因此这里手动引入了一遍
import { ElMessage } from "element-plus";
import { computed, watch } from "vue";
const { i18next } = useTranslation();
const appStore = useAppStore();
const controlStore = useControlStore();
const ipcAPI = window.nodeAPI.ipc;
appStore.syncDatabase();
appStore.syncConfig();
ipcAPI.queryWindowIds().then((windowIds) => {
  appStore.displayWindowId = windowIds.display;
  appStore.displayWindowOpened.value =
    appStore.displayWindowId === -1 ? false : true;
});
ipcAPI.handleUpdateWindowIds((event, windowIds) => {
  appStore.displayWindowId = windowIds.display;
  appStore.displayWindowOpened.value =
    appStore.displayWindowId === -1 ? false : true;
  // 展示器关闭或重载时重置模型控制器的状态
  // controlStore.currentModelType = "";
  // controlStore.modelControlInfoLoading = false;
  // controlStore.modelControlInfo = null;
  // 原来pinia有个方法叫reset……
  controlStore.$reset();
});

i18next.changeLanguage(appStore.config.general.language);
const locale = computed(() =>
  appStore.config.general.language === "en"
    ? en
    : appStore.config.general.language === "zh-CN"
    ? zhCn
    : appStore.config.general.language === "jp"
    ? ja
    : null
);

// 报错信息使用节流函数封装,防止因渲染错误疯狂弹窗
const handleDisplayWindowError = throttle((event, message) => {
  ElMessage({
    showClose: true,
    message: `Display Error: ${message}`,
    type: "error",
  });
}, 3000);
ipcAPI.handleDisplayWindowError(handleDisplayWindowError);
const handleControlWindowError = throttle((message) => {
  ElMessage({
    showClose: true,
    message: `Control Error: ${message}`,
    type: "error",
  });
}, 3000);

// if (appStore.config.general["error-report"]) {
//   window.onerror = function (message) {
//     handleControlWindowError(message);
//   };
//   window.addEventListener("unhandledrejection", rejectErrorHandler);
// }
const rejectErrorHandler = function (event) {
  handleControlWindowError(event.reason.message);
};
watch(
  () => appStore.config.general["error-report"],
  () => {
    // console.log("watch", appStore.config.general["error-report"]);
    if (appStore.config.general["error-report"]) {
      window.onerror = function (message) {
        handleControlWindowError(message);
      };
      const rejectErrorHandler = function (event) {
        handleControlWindowError(event.reason.message);
      };
      window.addEventListener("unhandledrejection", rejectErrorHandler);
    } else {
      window.onerror = null;
      window.removeEventListener("unhandledrejection", rejectErrorHandler);
    }
  }
);
window.appStore = appStore;
</script>

<style lang="scss">
:root {
  height: 100%;
  font-family: var(--el-font-family);
  font-size: var(--el-font-size-base);
  color: var(--el-text-color-regular);
  user-select: none;
  table {
    font-size: var(--el-font-size-base);
  }
}
body {
  height: 100%;
  margin: 0;
}
// 禁止图片拖拽
img {
  -webkit-user-drag: none;
}
#app {
  height: 100%;
  .el-container {
    height: 100%;
  }
}
.drag-area {
  position: fixed;
  top: 0;
  left: 0;
  height: 30px;
  width: 100%;
  -webkit-app-region: drag;
}
// 默认的表头背景色和底色不搭
.el-table th.el-table__cell {
  background-color: rgba(0, 0, 0, 0);
}
// 貌似是element plus的问题,自动引入时,深色模式下显示popover的效果不对劲
// https://github.com/element-plus/element-plus/issues/8113
// https://github.com/element-plus/element-plus/pull/8133
// 已在2.2.7修复
// .el-popper.is-light {
//   background: var(--el-bg-color-overlay);
//   border: 1px solid var(--el-border-color-light);
// }
.el-divider--horizontal.hime-el-divider {
  margin: 12px 0;
}
.el-table {
  --el-bg-color: transparent;
}
</style>


================================================
FILE: src/renderer/control/components/Common/ConfigItem.vue
================================================
<template>
  <div
    class="hime-config-item"
    :class="{ 'hime-config-item--top': labelPosition === 'top' }"
  >
    <div v-if="label" class="hime-config-item__label">{{ label }}:</div>
    <slot></slot>
  </div>
</template>

<script setup>
const props = defineProps({
  label: String,
  labelPosition: {
    type: String,
    default: "left",
  },
});
</script>

<style lang="scss">
.hime-config-item {
  display: flex;
  // 实践发现不设下面这一条的话small版的el-input-number会抽风
  align-items: center;
  + .hime-config-item {
    margin-top: 10px;
  }

  &.hime-config-item--top {
    flex-direction: column;
    align-items: flex-start;
    margin-top: initial;
    & > .hime-config-item__label {
      margin: 0 0 10px;
      font-weight: bold;
    }
  }
  .hime-config-item__label {
    margin-right: 10px;
  }
  // https://github.com/element-plus/element-plus/issues/15834#issuecomment-1936919229
  // 版本2.5.0后,el-select的样式发生了变化,需要手动置顶宽度,否则行内样式异常
  // 那问题来了,之前的默认宽度是哪里来的?经过我的疯狂刨根问底,结论是,大概是用户代理样式表设定的默认行为……
  & > .el-select {
    --el-select-width: 160px;
  }
}
</style>


================================================
FILE: src/renderer/control/components/Common/SvgIcon.vue
================================================
<template>
  <svg aria-hidden="true">
    <use :xlink:href="symbolId" :fill="color" />
  </svg>
</template>

<script>
import { defineComponent, computed } from "vue";

export default defineComponent({
  name: "SvgIcon",
  props: {
    prefix: {
      type: String,
      default: "icon",
    },
    name: {
      type: String,
      required: true,
    },
    color: {
      type: String,
      default: "#333",
    },
  },
  setup(props) {
    const symbolId = computed(() => `#${props.prefix}-${props.name}`);
    return { symbolId };
  },
});
</script>


================================================
FILE: src/renderer/control/components/Common/SvgIconElButton.vue
================================================
<template>
  <el-button>
    <svg-icon :name="name" class="hime-el-svg-icon"></svg-icon>
  </el-button>
</template>

<script setup>
import SvgIcon from "@control/components/Common/SvgIcon.vue";
const props = defineProps({
  name: String,
});
</script>

<style lang="scss">
.hime-el-svg-icon {
  height: var(--el-font-size-base);
  width: var(--el-font-size-base);
  use {
    fill: var(--el-button-text-color);
  }
}
</style>


================================================
FILE: src/renderer/control/components/Common/TitleWithDivider.vue
================================================
<template>
  <div style="font-size: 2rem"><slot></slot></div>
  <el-divider class="hime-el-divider" />
</template>

<script setup></script>

<style lang="scss"></style>


================================================
FILE: src/renderer/control/components/Contents/About.vue
================================================
<template>
  <div class="hime-content">
    <hime-title-with-divider>{{ $t("menu.about") }}</hime-title-with-divider>
    <el-card :class="{ hide, expend }">
      <div class="hime-about__logo">
        <div class="icon" @click="toggleClass">
          <img :src="iconImage" alt="" />
        </div>
        <div class="hime-about__info">
          <div class="title">Hime Display</div>
          <div class="hime-about__info__item">Version 1.2.0</div>
          <div class="hime-about__info__item">
            Developed by
            <a href="https://github.com/TSKI433" @click.prevent="openLink"
              >TSKI433</a
            >
          </div>
          <div class="hime-about__info__item">
            Illustrated by
            <a
              href="https://www.pixiv.net/users/72669923"
              @click.prevent="openLink"
              >MakoSaikou</a
            >
          </div>
          <div class="hime-about__info__item">
            Special Thanks:
            <a href="https://github.com/greenjerry" @click.prevent="openLink"
              >greenjerry</a
            >
            |
            <a href="https://github.com/pure01fx" @click.prevent="openLink"
              >pure01fx</a
            >
          </div>
          <div class="hime-about__info__item">
            Links:
            <a
              href="https://github.com/TSKI433/hime-display"
              @click.prevent="openLink"
              >GitHub</a
            >
            |
            <a href="https://hime.xdrv.cn/" @click.prevent="openLink"
              >Documention</a
            >
          </div>
        </div>
      </div>
    </el-card>
  </div>
</template>

<script setup>
import HimeTitleWithDivider from "@control/components/Common/TitleWithDivider.vue";
import iconImage from "@control/assets/logo.png";
import { ref } from "vue";
const hide = ref(false);
const expend = ref(false);
function toggleClass() {
  if (expend.value) {
    expend.value = false;
    hide.value = true;
    setTimeout(() => {
      hide.value = false;
    }, 1000);
  } else {
    expend.value = true;
  }
}
function openLink(event) {
  window.nodeAPI.openLink(event.target.href);
}
</script>

<style lang="scss">
@keyframes rotate {
  0% {
    transform: rotate3d(0, 0, 0, 0deg);
  }
  70% {
    transform: rotate3d(0.3, 0.4, 0.2, 380deg);
  }
  85% {
    transform: rotate3d(0.3, 0.4, 0.2, 350deg);
  }
  100% {
    transform: rotate3d(0.3, 0.4, 0.2, 360deg);
  }
}
.el-card {
  margin-right: 178px;
  margin-left: 178px;
  transition: cubic-bezier(0.83, 0.28, 0.16, 0.98) 0.8s;
  border-radius: 16px;
  &.hide {
    .hime-about__logo {
      .icon {
        animation: rotate 1s cubic-bezier(0.53, 0.15, 0.57, 0.96);
      }
      .hime-about__info {
        opacity: 0;
      }
    }
  }
  &.expend {
    margin-right: 0;
    margin-left: 0;
    .hime-about__logo {
      .hime-about__info {
        opacity: 1;
      }
    }
  }
  .hime-about__logo {
    display: flex;
    position: relative;
    .icon {
      width: 220px;
      display: flex;
      justify-content: center;
      img {
        height: 180px;
      }
    }
    .hime-about__info {
      transition: cubic-bezier(0.8, 0.31, 0.08, 0.82) 1.2s;
      opacity: 0;
      white-space: nowrap;
      position: absolute;
      left: 220px;
      display: flex;
      flex-direction: column;
      justify-content: space-evenly;
      align-items: flex-start;
      .title {
        font-size: 3rem;
        a {
          text-decoration: none;
          color: var(--el-text-color-primary);
        }
      }
      .hime-about__info__item {
        margin-top: 4px;
        font-size: var(--el-font-size-large);
        color: var(--el-text-color-secondary);
        a {
          text-decoration: none;
          color: var(--el-color-primary);
        }
      }
    }
  }
}
// .link-icon {
//   height: 1em;
//   width: 1em;
//   use {
//     fill: var(--el-text-color-secondary);
//   }
// }
</style>


================================================
FILE: src/renderer/control/components/Contents/Control/Common/2d/EventAnimation.vue
================================================
<template>
  <config-item :label="$t('control.animation.event-motion')">
    <el-select v-model="eventSelected" style="width: 80px; margin-right: 12px">
      <el-option value="click" />
      <el-option value="drag" />
    </el-select>
    <el-button @click="setEventAnimation('none')">
      {{ $t("control.animation.no-motion") }}
    </el-button>
    <el-button @click="setEventAnimation('random')">
      {{ $t("control.animation.random-motion") }}
    </el-button>
    <el-button
      @click="setEventAnimation('database')"
      :disabled="!motionTableSelected"
    >
      {{ $t("control.animation.selected-motion") }}
    </el-button>
  </config-item>
  <config-item :label="$t('control.animation.click-motion-now')">
    {{ clickAnimation.label }}
  </config-item>
  <config-item :label="$t('control.animation.drag-motion-now')">
    {{ dragAnimation.label }}
  </config-item>
</template>

<script setup>
import ConfigItem from "@control/components/Common/ConfigItem.vue";
import { useAppStore } from "@control/store/app";
import { reactive, toRaw, ref } from "vue";
const appStore = useAppStore();
const ipcAPI = window.nodeAPI.ipc;
const props = defineProps({
  currentMotion: Object,
  motionTableSelected: Boolean,
  modelType: String,
});
const currentMotion = props.currentMotion;

const clickAnimation = reactive({
  name: "clickAnimation",
  value: "random",
  // label用于UI显示
  label: "random",
});
const dragAnimation = reactive({
  name: "dragAnimation",
  value: "none",
  label: "none",
});
const eventSelected = ref("click");
function setEventAnimation(animation) {
  const instantConfig =
    eventSelected.value === "click" ? clickAnimation : dragAnimation;
  if (animation === "none" || animation === "random") {
    instantConfig.value = animation;
    instantConfig.label = animation;
    // 使用group曲线救国判断是否是live2d控制……
  } else if (props.modelType === "Live2d") {
    instantConfig.value = currentMotion.value.File
      ? currentMotion.value.File
      : currentMotion.value.file;
    instantConfig.label = currentMotion.value.name;
  } else if (props.modelType === "Spine") {
    instantConfig.value = currentMotion.value.name;
    instantConfig.label = currentMotion.value.name;
  }
  ipcAPI.sendToModelManager({
    channel: "control:change-instant-config",
    data: toRaw(instantConfig),
  });
}
</script>

<style lang="scss"></style>


================================================
FILE: src/renderer/control/components/Contents/Control/Common/2d/Transform2D.vue
================================================
<template>
  <config-item label="x">
    <el-input-number
      :precision="2"
      :step="10"
      v-model="transform.x"
      @change="setModelTransform"
    >
    </el-input-number>
  </config-item>
  <config-item label="y">
    <el-input-number
      :precision="2"
      :step="10"
      v-model="transform.y"
      @change="setModelTransform"
    >
    </el-input-number>
  </config-item>
  <config-item :label="$t('control.transform.scale')">
    <el-input-number
      :precision="2"
      :step="0.01"
      v-model="transform.scale"
      @change="setModelTransform"
    >
    </el-input-number>
  </config-item>
</template>

<script setup>
import { reactive, toRaw } from "vue";
import ConfigItem from "@control/components/Common/ConfigItem.vue";
import { useAppStore } from "@control/store/app";
const appStore = useAppStore();
const ipcAPI = window.nodeAPI.ipc;
const transform = reactive({
  x: 0,
  y: 0,
  scale: 1,
});
function setModelTransform() {
  ipcAPI.sendToModelManager({
    channel: "control:set-model-transform",
    data: toRaw(transform),
  });
}
ipcAPI.handleSendToModelControl((event, message) => {
  switch (message.channel) {
    case "manager:update-model-transform": {
      transform.x = message.data.x;
      transform.y = message.data.y;
      transform.scale = message.data.scale;
      break;
    }
  }
});
ipcAPI.sendToModelManager({
  channel: "control:query-model-transform",
  data: null,
});
</script>

<style lang="scss" scoped></style>


================================================
FILE: src/renderer/control/components/Contents/Control/Common/3d/AnimationControl.vue
================================================
<template>
  <el-scrollbar max-height="400px">
    <el-collapse class="hime-control-collapse">
      <el-collapse-item
        :title="$t('control.animation.motion-db')"
        name="motionDatabase"
      >
        <el-table
          :border="true"
          :data="appStore.database.motion3D"
          @current-change="changeCurrentMotionInfo"
          size="small"
          height="160"
          highlight-current-row
        >
          <el-table-column type="index" width="60" align="center" />
          <el-table-column
            :label="$t('control.animation.motion-name')"
            prop="name"
            show-overflow-tooltip
            width="300"
          />
          <el-table-column
            :label="$t('control.animation.extension-name')"
            align="center"
          >
            <template #default="props">
              <el-tag effect="light">
                {{ props.row.extensionName }}
              </el-tag>
            </template>
          </el-table-column>
        </el-table>
      </el-collapse-item>
      <el-collapse-item
        :title="$t('control.animation.audio-db')"
        name="audioDatabase"
      >
        <el-table
          :data="appStore.database.audio3D"
          :border="true"
          @current-change="changeCurrentAudioInfo"
          size="small"
          height="160"
          highlight-current-row
        >
          <el-table-column type="index" width="60" align="center" />
          <el-table-column
            :label="$t('control.animation.audio-name')"
            prop="name"
            show-overflow-tooltip
            width="300"
          />
          <el-table-column
            :label="$t('control.animation.extension-name')"
            align="center"
          >
            <template #default="props">
              <el-tag effect="light">
                {{ props.row.extensionName }}
              </el-tag>
            </template>
          </el-table-column>
        </el-table>
      </el-collapse-item>
    </el-collapse>
    <config-item :label="$t('control.animation.audio-delay')">
      <el-input-number
        v-model="delayTime"
        :disabled="!audioTableSelected"
      ></el-input-number>
    </config-item>
    <config-item
      :label="$t('control.animation.physics-simulation')"
      v-if="modelType == 'MMD'"
    >
      <el-switch v-model="physicsSimulation.value" />
    </config-item>
    <config-item
      :label="$t('control.animation.mixamo-convert-mode')"
      v-if="modelType == 'MMD'"
    >
      <el-select v-model="mixamoLegTranslateMode.value">
        <el-option :label="$t('control.animation.ik-calculate')" value="ik" />
        <el-option
          :label="$t('control.animation.rotate-calculate')"
          value="rotate"
        />
      </el-select>
    </config-item>
    <config-item :label="$t('control.animation.loop-play')">
      <el-switch v-model="animationLoop" />
    </config-item>
    <config-item :label="$t('control.animation.load')">
      <el-button @click="playMotion" :disabled="!motionTableSelected">{{
        $t("control.animation.load-motion")
      }}</el-button>
      <el-button
        @click="playMotionWithAudio"
        :disabled="!motionTableSelected || !audioTableSelected"
        >{{ $t("control.animation.load-motion-and-audio") }}</el-button
      >
    </config-item>
    <config-item :label="$t('control.animation.control')">
      <el-button @click="setMotionState" :disabled="!motionLoaded">{{
        motionPlaying
          ? $t("control.animation.pause")
          : $t("control.animation.play")
      }}</el-button>
      <el-button @click="quitAnimationPlay" :disabled="!motionLoaded">{{
        $t("control.animation.quit-motion")
      }}</el-button>
    </config-item>
  </el-scrollbar>
</template>

<script setup>
import { useAppStore } from "@control/store/app";
import ConfigItem from "@control/components/Common/ConfigItem.vue";
// 发现奇妙的现象,这里不引入ref不会直接报错,而是先蹦出两三百个vue的警告来
import { reactive, ref, watch, toRaw } from "vue";
const appStore = useAppStore();
const ipcAPI = window.nodeAPI.ipc;
const props = defineProps({
  modelType: String,
});
const currentMotionInfo = reactive({ value: null });
const currentAudioInfo = reactive({ value: null });
const motionTableSelected = ref(false);
const audioTableSelected = ref(false);
const animationLoop = ref(true);
const delayTime = ref(0);
function changeCurrentMotionInfo(currentRow) {
  motionTableSelected.value = true;
  currentMotionInfo.value = currentRow;
}
function changeCurrentAudioInfo(currentRow) {
  audioTableSelected.value = true;
  currentAudioInfo.value = currentRow;
}
function playMotion() {
  if (currentMotionInfo.value !== null) {
    ipcAPI.sendToModelManager({
      channel: "control:play-motion",
      data: {
        motionFilePath: currentMotionInfo.value.entranceFile,
        animationLoop: animationLoop.value,
      },
    });
  }
}
function playMotionWithAudio() {
  if (currentMotionInfo.value !== null && currentAudioInfo.value !== null) {
    ipcAPI.sendToModelManager({
      channel: "control:play-motion-with-audio",
      data: {
        motionFilePath: currentMotionInfo.value.entranceFile,
        audioFilePath: currentAudioInfo.value.entranceFile,
        delayTime: delayTime.value,
        // TODO:音频跟着loop,现在懒得做
        animationLoop: animationLoop.value,
      },
    });
  }
}
const motionLoaded = ref(false);
const motionPlaying = ref(false);
function setMotionState() {
  if (motionLoaded.value) {
    ipcAPI.sendToModelManager({
      channel: "control:set-motion-state",
      data: {
        state: motionPlaying.value ? "pause" : "play",
      },
    });
    motionPlaying.value = !motionPlaying.value;
  }
}
function quitAnimationPlay() {
  ipcAPI.sendToModelManager({
    channel: "control:quit-motion",
    data: null,
  });
  motionLoaded.value = false;
  motionPlaying.value = false;
}
const physicsSimulation = reactive({
  name: "physicsSimulation",
  value: true,
});
watch(physicsSimulation, () => {
  // 发现个有意思的问题,使用watch监视reactive,回调函数返回的新旧两个参数其实都指向那个reactive对象,所以下方的判断永远不成立
  // if (newVal.value !== oldVal.value) {
  ipcAPI.sendToModelManager({
    channel: "control:change-instant-config",
    data: toRaw(physicsSimulation),
  });
});
const mixamoLegTranslateMode = reactive({
  name: "mixamoLegTranslateMode",
  value: "ik",
});
watch(mixamoLegTranslateMode, () => {
  ipcAPI.sendToModelManager({
    channel: "control:change-instant-config",
    data: toRaw(mixamoLegTranslateMode),
  });
});
ipcAPI.handleSendToModelControl((event, message) => {
  switch (message.channel) {
    case "manager:update-motion-info": {
      console.log("[Hime Display] Update motion info:", message.data);
      motionLoaded.value = true;
      motionPlaying.value = true;
      break;
    }
  }
});
</script>

<style lang="scss">
.hime-control-collapse {
  margin-bottom: 16px;
}
</style>


================================================
FILE: src/renderer/control/components/Contents/Control/Common/3d/ObjectTransform3D.vue
================================================
<template>
  <config-item :label="$t('control.transform.tree-select')">
    <el-tree-select
      :data="[transformInfo.tree]"
      check-strictly
      v-model="nodeIdNow"
    />
  </config-item>
  <!-- 我去,这几天这么巧的吗,又碰到一个Element Plus刚刚修复了的bug:https://github.com/element-plus/element-plus/issues/8542 -->
  <config-item :label="$t('control.transform.auto-fill-select')">
    <el-select v-model="nodeIdNow" filterable>
      <el-option
        v-for="transformItem in transformInfo.list"
        :label="transformItem.label"
        :value="transformItem.value"
      >
      </el-option>
    </el-select>
  </config-item>
  <transform
    :transform-object="transformObject"
    @input="setNodeTransform"
    :disabled="nodeIdNow === ''"
  ></transform>
</template>

<script setup>
import Transform from "./Transform3D.vue";
import ConfigItem from "@control/components/Common/ConfigItem.vue";
import { reactive, ref, watch, toRaw } from "vue";
import { useAppStore } from "@control/store/app";
const appStore = useAppStore();
const ipcAPI = window.nodeAPI.ipc;
const props = defineProps({
  transformInfo: Object,
});
const transformObject = reactive({
  position: { x: 0, y: 0, z: 0 },
  rotation: { x: 0, y: 0, z: 0 },
  scale: { x: 1, y: 1, z: 1 },
});
const nodeIdNow = ref("");
// 此处发现,vue的watch对于ref返回原始值,对于reactive返回代理值
watch(nodeIdNow, (newId, oldId) => {
  if (newId === oldId) return;
  ipcAPI.sendToModelManager({
    channel: "control:bind-node-transform",
    data: { nodeId: newId },
  });
});
// 这里和morph不一样,不用watch了,下方对"manager:update-node-transform"事件的处理(出于懒)使用了直接赋值position,rotation,scale,改变了引用对象,因此展示器那边带来的数据更新也会触发watch,带来不必要的消耗(甚至可能导致死循环,不过根据目前monitor的监测机制,应该会在第二重循环上就拦住的)
// watch(transformObject, (newTransform) => {
//      ipcAPI.setNodeTransform(nodeIdNow.value,toRaw(newTransform))
// });
function setNodeTransform() {
  ipcAPI.sendToModelManager({
    channel: "control:set-node-transform",
    data: {
      nodeId: nodeIdNow.value,
      transform: toRaw(transformObject),
    },
  });
}

// 照理来讲,模型控制这一级的组件没用keep-alive,动态组件切换后事件监听也能正确弄过去?(目前已在切换组件时已进行了事件监听清理)
ipcAPI.handleSendToModelControl((event, message) => {
  switch (message.channel) {
    case "manager:update-node-transform": {
      // 直接赋值会完全失去响应性
      transformObject.position = message.data.position;
      transformObject.rotation = message.data.rotation;
      transformObject.scale = message.data.scale;
      break;
    }
  }
});
</script>

<style lang="scss"></style>


================================================
FILE: src/renderer/control/components/Contents/Control/Common/3d/ParameterControl.vue
================================================
<template>
  <config-item :label="$t('control.parameter.morph')" label-position="top">
    <config-item :label="$t('control.parameter.target-select')">
      <el-select
        v-model="selectedMorphName"
        @change="bindMorphTarget"
        filterable
      >
        <el-option
          v-for="morphName in morphInfo"
          :label="morphName"
          :value="morphName"
        />
      </el-select>
    </config-item>
    <config-item
      :label="$t('control.parameter.parameter-control')"
      style="width: 100%"
    >
      <el-slider
        v-model="morphWeight"
        :min="0"
        :max="1"
        :step="0.1"
        style="width: 60%; margin-left: 10px"
        :disabled="selectedMorphName === ''"
      />
    </config-item>
  </config-item>
  <el-divider style="margin: 12px 0" />
  <config-item :label="$t('control.parameter.mouse-focus')">
    <el-switch v-model="trackMouse.value" />
  </config-item>
  <template v-if="modelType == 'VRoid'">
    <config-item :label="$t('control.parameter.vrm-calculate')">
      <el-switch v-model="vrmUpdate.value" />
    </config-item>
  </template>
</template>

<script setup>
import ConfigItem from "@control/components/Common/ConfigItem.vue";
import { ref, watch, reactive, toRaw } from "vue";
import { useAppStore } from "@control/store/app";
const appStore = useAppStore();
const ipcAPI = window.nodeAPI.ipc;
const props = defineProps({
  morphInfo: Object,
  modelType: String,
});
// 若使用morph的index作为传递目标,可能存在难以发现的隐患
const selectedMorphName = ref("");
const morphWeight = ref(0);
function bindMorphTarget() {
  if (selectedMorphName.value === "") return;
  ipcAPI.sendToModelManager({
    channel: "control:bind-morph-target",
    data: {
      morphName: selectedMorphName.value,
    },
  });
}
function setMorphWeight() {
  ipcAPI.sendToModelManager({
    channel: "control:set-morph-weight",
    data: {
      morphName: selectedMorphName.value,
      weight: morphWeight.value,
    },
  });
}
// 这里和live2d的参数控制一样,不再用input事件触发setMorphWeight函数,改为watch了,理由是,el-slider控件设定step参数后,即使参数没有更新,有滑动的操作也可能触发input,这样会导致setMorphWeight函数重复触发,消耗性能,由于这里监听的morphWeight是ref包裹的原始值,所以也不用担心会像ObjectTransform.vue里面那样意外的由于watch触发setMorphWeight函数。
watch(morphWeight, setMorphWeight);
ipcAPI.handleSendToModelControl((event, message) => {
  switch (message.channel) {
    case "manager:update-node-morph": {
      morphWeight.value = message.data.weight;
      break;
    }
  }
});

// 鼠标跟踪
const trackMouse = reactive({
  name: "trackMouse",
  value: true,
});
watch(trackMouse, () => {
  ipcAPI.sendToModelManager({
    channel: "control:change-instant-config",
    data: toRaw(trackMouse),
  });
});

// VRM演算控制
const vrmUpdate = reactive({
  name: "vrmUpdate",
  value: true,
});
watch(vrmUpdate, () => {
  ipcAPI.sendToModelManager({
    channel: "control:change-instant-config",
    data: toRaw(vrmUpdate),
  });
});
</script>

<style lang="scss"></style>


================================================
FILE: src/renderer/control/components/Contents/Control/Common/3d/Transform3D.vue
================================================
<template>
  <!-- 遇到一个坑,如果template下级有多个元素的话,下方的input事件就会无法正确向上传递 -->
  <div class="hime-transform--3d">
    <config-item
      :label="$t('control.transform.position')"
      label-position="top"
      class="hime-transform--3d__item"
    >
      <!-- 多层组件嵌套导致input事件无法从底层的el-input-number向上传递,因此需要在上级组件再次设定事件传递, -->
      <config-item :label="i" v-for="i in xyz">
        <el-input-number
          :precision="2"
          v-model="transformObject.position[i]"
          @input="$emit('input')"
          :disabled="disabled"
        ></el-input-number>
      </config-item>
    </config-item>
    <config-item
      :label="$t('control.transform.rotation')"
      label-position="top"
      class="hime-transform--3d__item"
    >
      <config-item :label="i" v-for="i in xyz">
        <el-input-number
          :precision="2"
          v-model="transformObject.rotation[i]"
          @input="$emit('input')"
          :disabled="disabled"
        ></el-input-number>
      </config-item>
    </config-item>
    <config-item
      :label="$t('control.transform.scale')"
      label-position="top"
      class="hime-transform--3d__item"
    >
      <config-item :label="i" v-for="i in xyz">
        <el-input-number
          :precision="2"
          v-model="transformObject.scale[i]"
          @input="$emit('input')"
          :disabled="disabled"
        ></el-input-number>
      </config-item>
    </config-item>
  </div>
</template>

<script setup>
import ConfigItem from "@control/components/Common/ConfigItem.vue";
// 由于VRoid和MMD的模型大小不在一个量级上,且VRoid模型更改大小会导致模型的物理模拟炸毛,这里根据实际情况改变位置设定步长
const xyz = ["x", "y", "z"];
const props = defineProps({
  positionStep: Number,
  transformObject: Object,
  disabled: Boolean,
});
</script>

<style lang="scss">
.hime-transform--3d {
  display: flex;
  .hime-transform--3d__item {
    margin-right: 20px;
    margin-top: 12px;
  }
}
</style>


================================================
FILE: src/renderer/control/components/Contents/Control/Common/ControlLoadError.vue
================================================
<template>{{ $t("control.control-load-error") }}</template>

<script setup></script>

<style lang="scss"></style>


================================================
FILE: src/renderer/control/components/Contents/Control/Common/ModelDescription.vue
================================================
<template>
  <el-descriptions border size="small" direction="vertical" :column="5">
    <el-descriptions-item
      align="center"
      width="20%"
      :label="$t(`control.description.${descriptionItem.label}`)"
      v-for="descriptionItem in description"
      >{{ descriptionItem.value }}</el-descriptions-item
    >
  </el-descriptions>
</template>

<script setup>
const props = defineProps({
  description: Object,
});
</script>

<style lang="scss"></style>


================================================
FILE: src/renderer/control/components/Contents/Control/Common/MotionCapture.vue
================================================
<template>
  <config-item
    :label="$t('control.capture.capture-type')"
    v-if="modelType == 'MMD' || modelType == 'VRoid'"
  >
    <el-radio-group v-model="motionCaptureType">
      <el-radio-button label="faceMesh">{{
        $t("control.capture.face-capture")
      }}</el-radio-button>
      <el-radio-button label="holistic">{{
        $t("control.capture.holistic-capture")
      }}</el-radio-button>
    </el-radio-group>
  </config-item>
  <config-item :label="$t('control.capture.capture-control')">
    <el-button @click="launchCapture" :disabled="capturing">{{
      $t("control.capture.start-capture")
    }}</el-button>
    <el-button @click="quitCapture" :disabled="!capturing" type="danger">
      {{ $t("control.capture.quit-capture") }}</el-button
    >
  </config-item>
</template>

<script setup>
import { useAppStore } from "@control/store/app";
import ConfigItem from "@control/components/Common/ConfigItem.vue";
import { ref } from "vue";
const props = defineProps({
  modelType: String,
});
const appStore = useAppStore();
const ipcAPI = window.nodeAPI.ipc;
const capturing = ref(false);
const motionCaptureType = ref("faceMesh");
function launchCapture() {
  ipcAPI.sendToModelManager({
    channel: "control:launch-capture",
    data: {
      type: motionCaptureType.value,
    },
  });
  capturing.value = true;
}
function quitCapture() {
  ipcAPI.sendToModelManager({
    channel: "control:quit-capture",
    data: null,
  });
  capturing.value = false;
}
</script>

<style lang="scss"></style>


================================================
FILE: src/renderer/control/components/Contents/Control/Live2DControl/AnimationControl.vue
================================================
<template>
  <el-table
    :data="motions"
    :border="true"
    @current-change="changeCurrentMotion"
    highlight-current-row
    height="200"
    size="small"
    style="margin-bottom: 12px"
    tooltip-effect="light"
  >
    <el-table-column type="index" width="60" align="center" />
    <el-table-column
      :label="$t('control.animation.motion-name')"
      show-overflow-tooltip
      prop="name"
      align="center"
    >
    </el-table-column>
    <el-table-column
      :label="$t('control.animation.motion-group')"
      prop="group"
      width="200"
      align="center"
    >
    </el-table-column>
  </el-table>
  <config-item :label="$t('control.animation.operate')">
    <el-button @click="loadMotionNow">
      {{ $t("control.animation.load-motion") }}
    </el-button>
  </config-item>
  <el-divider style="margin: 12px 0" />
  <event-animation
    :current-motion="currentMotion"
    :motion-table-selected="motiontableSelected"
    model-type="Live2D"
  ></event-animation>
</template>

<script setup>
import { computed, ref, toRaw, reactive } from "vue";
import ConfigItem from "@control/components/Common/ConfigItem.vue";
import EventAnimation from "../Common/2d/EventAnimation.vue";
import { useAppStore } from "@control/store/app";
const appStore = useAppStore();
const ipcAPI = window.nodeAPI.ipc;
// 直接赋值为null在各种响应式需求下会很不妙
const currentMotion = reactive({ value: null });
const motiontableSelected = ref(false);
const props = defineProps({
  motionInfo: Object,
});
const motions = computed(function () {
  const motionList = [];
  Object.keys(props.motionInfo).forEach((motionGroupName) => {
    props.motionInfo[motionGroupName].forEach((motion, index) => {
      motion.group = motionGroupName;
      // moc与moc3的入口文件属性名不同
      motion.name =
        (motion.File || motion.file) &&
        /(?<=\/?)[^\/]+(?=\.(json|mtn))/.exec(motion.File || motion.file)[0];
      motionList.push(motion);
    });
  });
  return motionList;
});
function changeCurrentMotion(currentRow) {
  motiontableSelected.value = true;
  currentMotion.value = currentRow;
}
function loadMotionNow() {
  ipcAPI.sendToModelManager({
    channel: "control:play-motion",
    data: {
      motion: toRaw(currentMotion.value),
    },
  });
}
</script>

<style lang="scss"></style>


================================================
FILE: src/renderer/control/components/Contents/Control/Live2DControl/ParameterControl.vue
================================================
<template>
  <config-item label="Parameter" label-position="top">
    <config-item :label="$t('control.parameter.target-select')">
      <el-select
        v-model="selectedParameterId"
        @change="bindParameterId"
        filterable
      >
        <el-option
          v-for="parameterId in parameterInfo._parameterIds"
          :label="parameterId"
          :value="parameterId"
        />
      </el-select>
    </config-item>
    <config-item
      :label="$t('control.parameter.parameter-control')"
      style="width: 100%"
    >
      <el-slider
        v-model="parameterValue"
        :min="parameterInfo._parameterMinimumValues[selectedParameterIndex]"
        :max="parameterInfo._parameterMaximumValues[selectedParameterIndex]"
        :step="0.1"
        style="width: 60%; margin-left: 10px"
        :disabled="selectedParameterId === ''"
      />
    </config-item>
  </config-item>
  <el-divider style="margin: 12px 0" />
  <config-item
    :label="$t('control.parameter.part-opacity')"
    label-position="top"
  >
    <config-item :label="$t('control.parameter.target-select')">
      <el-select v-model="selectedPartId" @change="bindPartId" filterable>
        <el-option v-for="partId in partInfo" :label="partId" :value="partId" />
      </el-select>
    </config-item>
    <config-item
      :label="$t('control.parameter.parameter-control')"
      style="width: 100%"
    >
      <el-slider
        v-model="partOpacity"
        :min="0"
        :max="1"
        :step="0.05"
        style="width: 60%; margin-left: 10px"
        :disabled="selectedPartId === ''"
        @input="setPartOpacity"
      />
    </config-item>
  </config-item>
  <el-divider style="margin: 12px 0" />
  <config-item :label="$t('control.parameter.mouse-focus')">
    <el-switch v-model="trackMouse.value" />
  </config-item>
  <config-item :label="$t('control.parameter.auto-breath')">
    <el-switch v-model="autoBreath.value" />
  </config-item>
  <config-item :label="$t('control.parameter.auto-eye-blink')">
    <el-switch v-model="autoEyeBlink.value" />
  </config-item>
</template>

<script setup>
import ConfigItem from "@control/components/Common/ConfigItem.vue";
import { computed, ref, watch, reactive, toRaw } from "vue";
import { useAppStore } from "@control/store/app";
const appStore = useAppStore();
const ipcAPI = window.nodeAPI.ipc;
const props = defineProps({
  parameterInfo: Object,
  partInfo: Object,
});
const selectedParameterId = ref("");
const parameterValue = ref(0);
const selectedParameterIndex = computed(() => {
  return props.parameterInfo._parameterIds.indexOf(selectedParameterId.value);
});
function bindParameterId() {
  if (selectedParameterId.value === "") return;
  ipcAPI.sendToModelManager({
    channel: "control:bind-parameter",
    data: {
      parameterId: selectedParameterId.value,
    },
  });
}
function setParameterValue() {
  ipcAPI.sendToModelManager({
    channel: "control:set-parameter",
    data: {
      parameterId: selectedParameterId.value,
      value: parameterValue.value,
    },
  });
}
// 若检测input事件,会在相同的parameterValue下多次触发事件,消耗性能
watch(parameterValue, setParameterValue);
const selectedPartId = ref("");
const partOpacity = ref(0);
function bindPartId() {
  if (selectedPartId.value === "") return;
  ipcAPI.sendToModelManager({
    channel: "control:bind-part",
    data: {
      partId: selectedPartId.value,
    },
  });
}
function setPartOpacity() {
  ipcAPI.sendToModelManager({
    channel: "control:set-part",
    data: {
      partId: selectedPartId.value,
      value: partOpacity.value,
    },
  });
}
watch(partOpacity, setPartOpacity);
ipcAPI.handleSendToModelControl((event, message) => {
  switch (message.channel) {
    case "manager:update-parameter": {
      parameterValue.value = message.data.value;
      break;
    }
    // 虽然没怎么遇到part可见性的动画,但是通过分析live2d的motion文件发现,partOpacity也是可以设定动画帧的
    case "manager:update-part": {
      partOpacity.value = message.data.value;
    }
  }
});
const trackMouse = reactive({
  name: "trackMouse",
  value: true,
});
watch(trackMouse, () => {
  ipcAPI.sendToModelManager({
    channel: "control:change-instant-config",
    data: toRaw(trackMouse),
  });
});
const autoBreath = reactive({
  name: "autoBreath",
  value: true,
});
watch(autoBreath, () => {
  ipcAPI.sendToModelManager({
    channel: "control:change-instant-config",
    data: toRaw(autoBreath),
  });
});
const autoEyeBlink = reactive({
  name: "autoEyeBlink",
  value: true,
});
watch(autoEyeBlink, () => {
  ipcAPI.sendToModelManager({
    channel: "control:change-instant-config",
    data: toRaw(autoEyeBlink),
  });
});
</script>

<style lang="scss"></style>


================================================
FILE: src/renderer/control/components/Contents/Control/Live2DControl/index.vue
================================================
<template>
  <div class="hime-model-control">
    <el-tabs type="border-card">
      <el-tab-pane :label="$t(`control.model-description`)">
        <model-description
          v-if="controlStore.modelControlInfo?.description !== undefined"
          :description="controlStore.modelControlInfo.description"
        >
        </model-description>
        <template v-else>
          <control-load-error></control-load-error>
        </template>
      </el-tab-pane>
      <el-tab-pane :label="$t(`control.object-transform`)">
        <transform></transform>
      </el-tab-pane>
      <el-tab-pane :label="$t(`control.animation-control`)">
        <animation-control
          v-if="controlStore.modelControlInfo?.motion !== undefined"
          :motion-info="controlStore.modelControlInfo.motion"
        >
        </animation-control>
        <template v-else>
          <control-load-error></control-load-error>
        </template>
      </el-tab-pane>
      <el-tab-pane :label="$t(`control.parameter-control`)">
        <parameter-control
          v-if="
            controlStore.modelControlInfo?.parameter !== undefined &&
            controlStore.modelControlInfo?.part !== undefined
          "
          :parameter-info="controlStore.modelControlInfo.parameter"
          :part-info="controlStore.modelControlInfo.part"
        ></parameter-control>
        <template v-else>
          <control-load-error></control-load-error>
        </template>
      </el-tab-pane>
      <el-tab-pane :label="$t(`control.motion-capture`)">
        <motion-capture model-type="Live2D"></motion-capture>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script setup>
import ControlLoadError from "../Common/ControlLoadError.vue";
import ModelDescription from "../Common/ModelDescription.vue";
import Transform from "../Common/2d/Transform2D.vue";
import AnimationControl from "./AnimationControl.vue";
import ParameterControl from "./ParameterControl.vue";
import MotionCapture from "../Common/MotionCapture.vue";
import { useControlStore } from "@control/store/control";
const controlStore = useControlStore();
</script>

<style lang="scss"></style>


================================================
FILE: src/renderer/control/components/Contents/Control/MMDControl/index.vue
================================================
<template>
  <div class="hime-model-control">
    <!-- 弃用方案:使用Menu组件构建 -->
    <!-- <el-menu
      @select="handleSelect"
      mode="horizontal"
      class="hime-el-menu--sub-control"
      :ellipsis="false"
      :default-active="subControlComponentNameNow"
    >
      <el-menu-item index="ModelDescription">模型信息</el-menu-item>
      <el-menu-item index="ObjectTransform">对象变换</el-menu-item>
      <el-menu-item index="AnimationControl">动画播放</el-menu-item>
      <el-menu-item index="MotionCapture">动作捕捉</el-menu-item>
    </el-menu> -->
    <el-tabs type="border-card">
      <!-- 这里用v-for实在是麻烦,还是依次设置 -->
      <el-tab-pane :label="$t(`control.model-description`)">
        <model-description
          v-if="controlStore.modelControlInfo?.description !== undefined"
          :description="controlStore.modelControlInfo.description"
        >
        </model-description>
        <template v-else>
          <control-load-error></control-load-error>
        </template>
      </el-tab-pane>
      <el-tab-pane :label="$t(`control.object-transform`)">
        <object-transform
          v-if="controlStore.modelControlInfo?.transform !== undefined"
          :transform-info="controlStore.modelControlInfo.transform"
        >
        </object-transform>
        <template v-else>
          <control-load-error></control-load-error>
        </template>
      </el-tab-pane>
      <el-tab-pane :label="$t(`control.animation-control`)">
        <animation-control model-type="MMD"> </animation-control>
      </el-tab-pane>
      <el-tab-pane :label="$t(`control.parameter-control`)">
        <parameter-control
          v-if="controlStore.modelControlInfo?.morph !== undefined"
          :morph-info="controlStore.modelControlInfo.morph"
          model-type="MMD"
        >
        </parameter-control>
        <template v-else>
          <control-load-error></control-load-error>
        </template>
      </el-tab-pane>
      <el-tab-pane :label="$t(`control.motion-capture`)">
        <motion-capture model-type="MMD"> </motion-capture>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script setup>
import ControlLoadError from "../Common/ControlLoadError.vue";
import ModelDescription from "../Common/ModelDescription.vue";
import ObjectTransform from "../Common/3d/ObjectTransform3D.vue";
import AnimationControl from "../Common/3d/AnimationControl.vue";
import ParameterControl from "../Common/3d/ParameterControl.vue";
import MotionCapture from "../Common/MotionCapture.vue";
import { useControlStore } from "@control/store/control";
const controlStore = useControlStore();
</script>

<style lang="scss"></style>


================================================
FILE: src/renderer/control/components/Contents/Control/SpineControl/AnimationControl.vue
================================================
<template>
  <el-scrollbar max-height="400px">
    <config-item
      :label="$t('control.animation.motion-db')"
      label-position="top"
    >
      <el-table
        :border="true"
        :data="motionInfo"
        @current-change="changeCurrentMotion"
        highlight-current-row
        height="200"
        size="small"
        tooltip-effect="light"
      >
        <el-table-column type="index" width="60" align="center" />
        <el-table-column
          :label="$t('control.animation.motion-name')"
          prop="name"
          align="center"
        />
        <el-table-column
          :label="$t('control.animation.motion-duration')"
          prop="duration"
          width="200"
          align="center"
        />
      </el-table>
    </config-item>
    <config-item :label="$t('control.animation.loop-play')">
      <el-switch v-model="animationLoop" />
    </config-item>
    <config-item :label="$t('control.animation.operate')">
      <el-button @click="loadMotionNow">
        {{ $t("control.animation.load-motion") }}
      </el-button>
      <el-button @click="quitMotion">
        {{ $t("control.animation.quit-motion") }}
      </el-button>
    </config-item>
    <el-divider style="margin: 12px 0" />
    <event-animation
      :current-motion="currentMotion"
      :motion-table-selected="motionTableSelected"
      modelType="Spine"
    ></event-animation>
  </el-scrollbar>
</template>

<script setup>
import { ref, toRaw, reactive } from "vue";
import ConfigItem from "@control/components/Common/ConfigItem.vue";
import EventAnimation from "../Common/2d/EventAnimation.vue";
import { useAppStore } from "@control/store/app";
const appStore = useAppStore();
const ipcAPI = window.nodeAPI.ipc;
const currentMotion = reactive({ value: null });
const motionTableSelected = ref(false);
const animationLoop = ref(true);
const props = defineProps({
  motionInfo: Object,
});
function changeCurrentMotion(currentRow) {
  motionTableSelected.value = true;
  currentMotion.value = currentRow;
}
function loadMotionNow() {
  ipcAPI.sendToModelManager({
    channel: "control:play-motion",
    data: {
      motion: toRaw(currentMotion.value),
      animationLoop: animationLoop.value,
    },
  });
}
function quitMotion() {
  ipcAPI.sendToModelManager({
    channel: "control:quit-motion",
    data: null,
  });
}
</script>

<style lang="scss"></style>


================================================
FILE: src/renderer/control/components/Contents/Control/SpineControl/ParameterControl.vue
================================================
<template>
  <config-item :label="$t('control.parameter.skin')">
    <el-select v-model="selectedSkin" @change="setSkin" filterable>
      <el-option v-for="skin in skinInfo" :label="skin" :value="skin" />
    </el-select>
  </config-item>
</template>

<script setup>
import ConfigItem from "@control/components/Common/ConfigItem.vue";
import { ref } from "vue";
import { useAppStore } from "@control/store/app";
const appStore = useAppStore();
const ipcAPI = window.nodeAPI.ipc;
const props = defineProps({
  skinInfo: Object,
});
const selectedSkin = ref("default");
function setSkin() {
  ipcAPI.sendToModelManager({
    channel: "control:set-skin",
    data: {
      skin: selectedSkin.value,
    },
  });
}
</script>

<style lang="scss"></style>


================================================
FILE: src/renderer/control/components/Contents/Control/SpineControl/index.vue
================================================
<template>
  <div class="hime-model-control">
    <el-tabs type="border-card">
      <el-tab-pane :label="$t(`control.model-description`)">
        <template
          v-if="controlStore.modelControlInfo?.description !== undefined"
        >
          <model-description
            :description="controlStore.modelControlInfo.description"
          >
          </model-description>
          <div
            style="
              color: var(--el-text-color-secondary);
              margin: 1rem auto 0;
              width: 95%;
            "
          >
            {{ $t(`control.description.spine-license`) }}
          </div>
        </template>
        <template v-else>
          <control-load-error></control-load-error>
        </template>
      </el-tab-pane>
      <el-tab-pane :label="$t(`control.object-transform`)">
        <transform></transform>
      </el-tab-pane>
      <el-tab-pane :label="$t(`control.animation-control`)">
        <animation-control
          v-if="controlStore.modelControlInfo?.motion !== undefined"
          :motion-info="controlStore.modelControlInfo.motion"
        >
        </animation-control>
        <template v-else>
          <control-load-error></control-load-error>
        </template>
      </el-tab-pane>
      <el-tab-pane :label="$t(`control.parameter-control`)">
        <parameter-control
          v-if="controlStore.modelControlInfo?.skin !== undefined"
          :skin-info="controlStore.modelControlInfo.skin"
        ></parameter-control>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script setup>
import ControlLoadError from "../Common/ControlLoadError.vue";
import ModelDescription from "../Common/ModelDescription.vue";
import Transform from "../Common/2d/Transform2D.vue";
import AnimationControl from "./AnimationControl.vue";
import ParameterControl from "./ParameterControl.vue";
import { useControlStore } from "@control/store/control";
const controlStore = useControlStore();
</script>

<style lang="scss"></style>


================================================
FILE: src/renderer/control/components/Contents/Control/VRoidControl/index.vue
================================================
<template>
  <div class="hime-model-control">
    <!-- 弃用方案:使用Menu组件构建 -->
    <!-- <el-menu
      @select="handleSelect"
      mode="horizontal"
      class="hime-el-menu--sub-control"
      :ellipsis="false"
      :default-active="subControlComponentNameNow"
    >
      <el-menu-item index="ModelDescription">模型信息</el-menu-item>
      <el-menu-item index="ObjectTransform">对象变换</el-menu-item>
      <el-menu-item index="AnimationControl">动画播放</el-menu-item>
      <el-menu-item index="MotionCapture">动作捕捉</el-menu-item>
    </el-menu> -->
    <el-tabs type="border-card">
      <!-- 这里用v-for实在是麻烦,还是依次设置 -->
      <el-tab-pane :label="$t(`control.model-description`)">
        <model-description
          v-if="controlStore.modelControlInfo?.description !== undefined"
          :description="controlStore.modelControlInfo.description"
        >
        </model-description>
        <template v-else>
          <control-load-error></control-load-error>
        </template>
      </el-tab-pane>
      <el-tab-pane :label="$t(`control.object-transform`)">
        <object-transform
          v-if="controlStore.modelControlInfo?.transform !== undefined"
          :transform-info="controlStore.modelControlInfo.transform"
        >
        </object-transform>
        <template v-else>
          <control-load-error></control-load-error>
        </template>
      </el-tab-pane>
      <!-- 动画转换遇到较大问题,暂时不去支持动画播放了 -->
      <!-- <el-tab-pane :label="$t(`control.animation-control`)">
        <animation-control model-type="VRoid"> </animation-control>
      </el-tab-pane> -->
      <el-tab-pane :label="$t(`control.parameter-control`)">
        <parameter-control
          v-if="controlStore.modelControlInfo?.morph !== undefined"
          :morph-info="controlStore.modelControlInfo.morph"
          model-type="VRoid"
        >
        </parameter-control>
        <template v-else>
          <control-load-error></control-load-error>
        </template>
      </el-tab-pane>
      <el-tab-pane :label="$t(`control.motion-capture`)">
        <motion-capture model-type="VRoid"> </motion-capture>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script setup>
import ControlLoadError from "../Common/ControlLoadError.vue";
import ModelDescription from "../Common/ModelDescription.vue";
import ObjectTransform from "../Common/3d/ObjectTransform3D.vue";
// import AnimationControl from "../Common/3d/AnimationControl.vue";
import ParameterControl from "../Common/3d/ParameterControl.vue";
import MotionCapture from "../Common/MotionCapture.vue";
import { useControlStore } from "@control/store/control";
const controlStore = useControlStore();
</script>

<style lang="scss"></style>


================================================
FILE: src/renderer/control/components/Contents/Control/index.vue
================================================
<template>
  <div class="hime-content">
    <hime-title-with-divider>{{ $t("menu.control") }}</hime-title-with-divider>
    <!-- <HimeMMDControl></HimeMMDControl> -->
    <template
      v-if="
        controlComponentNow !== undefined &&
        !controlStore.modelControlInfoLoading
      "
    >
      <component :is="controlComponentNow"></component>
    </template>
    <template v-else>
      <div class="hime-model-control--blank">
        {{ $t("control.load-a-model-to-control") }}
      </div>
    </template>
  </div>
</template>

<script setup>
import HimeTitleWithDivider from "@control/components/Common/TitleWithDivider.vue";
import HimeMMDControl from "@control/components/Contents/Control/MMDControl/index.vue";
import HimeSpineControl from "@control/components/Contents/Control/SpineControl/index.vue";
import HimeVRoidControl from "@control/components/Contents/Control/VRoidControl/index.vue";
import HimeLive2DControl from "@control/components/Contents/Control/Live2DControl/index.vue";
import { useControlStore } from "@control/store/control";
import { computed, watch } from "vue";
const controlStore = useControlStore();
const controlComponents = {
  HimeMMDControl,
  HimeSpineControl,
  HimeVRoidControl,
  HimeLive2DControl,
};
const controlComponentNow = computed(() => {
  return controlComponents[`Hime${controlStore.currentModelType}Control`];
});
watch(
  () => controlStore.currentModelType,
  () => {
    // 切换模型类型时,清空事件监听
    nodeAPI.ipc.removeManagerListeners();
  }
);
</script>

<style lang="scss">
.hime-model-control {
  flex: 1;
}
.hime-model-control--blank {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  font-size: 2rem;
  color: var(--el-text-color-placeholder);
  height: 100%;
}
</style>


================================================
FILE: src/renderer/control/components/Contents/Display.vue
================================================
<template>
  <div class="hime-content">
    <!-- <el-form label-position="top" class="hime-el-form--large-label"> -->
    <hime-title-with-divider>{{ $t("menu.display") }}</hime-title-with-divider>
    <el-scrollbar height="100%">
      <el-form label-width="170px" class="hime-el-form--config">
        <el-form-item :label="$t('display.window')">
          <config-item :label="$t('display.window-type')">
            <!-- 由于日语片假名实在太长了,不得不妥协一下换个组件…… -->
            <!-- <el-radio-group v-model="appStore.config.display['display-mode']">
                <el-radio-button label="displayFullScreen">
                {{ $t("display.fullscreen") }}
              </el-radio-button>
              <el-radio-button label="displayWindowed">
                {{ $t("display.windowed") }}
              </el-radio-button>
            </el-radio-group> -->
            <el-select v-model="appStore.config.display['display-mode']">
              <!-- 我感觉这里的element plus给我整懵了,填在label里面的东西其实却是value? -->
              <el-option
                :label="$t('display.fullscreen')"
                value="displayFullScreen"
              />
              <el-option
                :label="$t('display.windowed')"
                value="displayWindowed"
              />
            </el-select>
          </config-item>
        </el-form-item>
        <el-form-item :label="$t('display.show')">
          <config-item :label="$t('display.pixel-ratio')">
            <!-- <el-radio-group v-model="appStore.config.display['pixel-ratio']">
              <el-radio-button label="normal"> Normal </el-radio-button>
              <el-radio-button label="retina"> Retina </el-radio-button>
              <el-radio-button label="system"> Auto </el-radio-button>
            </el-radio-group> -->
            <el-select v-model="appStore.config.display['pixel-ratio']">
              <el-option label="Normal" value="normal" />
              <el-option label="Retina" value="retina" />
              <el-option label="System" value="system" />
            </el-select>
          </config-item>
          <config-item :label="$t('display.show-fps')">
            <el-switch v-model="appStore.config.display['show-fps']" />
          </config-item>
          <config-item :label="$t('display.antialias')">
            <el-switch v-model="appStore.config.display['antialias']" />
          </config-item>
          <config-item :label="$t('display.auto-load-last')">
            <el-switch v-model="appStore.config.display['auto-load-last']" />
          </config-item>
        </el-form-item>
        <el-form-item :label="$t('display.transparent-display')">
          <config-item :label="$t('display.click-through')">
            <!-- <el-radio-group v-model="appStore.config.display['click-through']">
              <el-radio-button label="all">
                {{ $t("display.all-area") }}
              </el-radio-button>
              <el-radio-button label="transparent">
                {{ $t("display.transparent-area") }}
              </el-radio-button>
            </el-radio-group> -->
            <el-select v-model="appStore.config.display['click-through']">
              <el-option :label="$t('display.all-area')" value="all" />
              <el-option
                :label="$t('display.transparent-area')"
                value="transparent"
              />
            </el-select>
          </config-item>
          <config-item :label="$t('display.show-area') + '(macOS)'">
            <!-- <el-radio-group v-model="appStore.config.display['display-range']">
              <el-radio-button label="singleDesktop">
                {{ $t("display.single-desktop") }}
              </el-radio-button>
              <el-radio-button label="allDesktops">
                {{ $t("display.all-desktops") }}
              </el-radio-button>
              <el-radio-button label="allWorkspaces">
                {{ $t("display.all-workspaces") }}
              </el-radio-button>
            </el-radio-group> -->
            <el-select v-model="appStore.config.display['display-range']">
              <!-- 我感觉这里的element plus给我整懵了,填在label里面的东西其实却是value? -->
              <el-option
                :label="$t('display.single-desktop')"
                value="singleDesktop"
              />
              <el-option
                :label="$t('display.all-desktops')"
                value="allDesktops"
              />
              <el-option
                :label="$t('display.all-workspaces')"
                value="allWorkspaces"
              />
            </el-select>
          </config-item>
          <config-item :label="$t('display.always-on-top')">
            <el-switch
              v-model="appStore.config.display['keep-display-at-top']"
            />
          </config-item>
        </el-form-item>
        <el-form-item :label="$t('display.windowed-display')">
          <config-item :label="$t('display.background-color')">
            <el-color-picker
              v-model="appStore.config.display.background"
              color-format="hex"
            />
          </config-item>
        </el-form-item>
        <!-- 虽然3D和2D分别有很多共有的配置,但实际使用时发现不同模型类型的最佳默认值存在较大差异,例如2D的显示范围,一般来讲spine模型更加小巧,而VRoid的默认轮廓线效果也很爆炸,因此这里都改成了独立的设置 -->
        <el-form-item :label="$t('display.live2d-render')">
          <config-item :label="$t('display.width-range')">
            <div class="hime-el-slicder--with-label">
              <span> 0% </span>
              <el-slider
                v-model="appStore.config.display['live2d-initial-width-range']"
                class="hime-el-slider"
                show-tooltip
                :format-tooltip="(value) => value + '%'"
                range
                :min="0"
                :max="100"
              />
              <span> 100% </span>
            </div>
          </config-item>
          <config-item :label="$t('display.height-range')">
            <div class="hime-el-slicder--with-label">
              <span> 0% </span>
              <el-slider
                v-model="appStore.config.display['live2d-initial-height-range']"
                class="hime-el-slider"
                show-tooltip
                :format-tooltip="(value) => value + '%'"
                range
                :min="0"
                :max="100"
              />
              <span> 100% </span>
            </div>
          </config-item>
          <config-item :label="$t('display.drag-to-move')">
            <el-switch v-model="appStore.config.display['live2d-draggable']" />
          </config-item>
        </el-form-item>
        <el-form-item :label="$t('display.spine-render')">
          <config-item :label="$t('display.width-range')">
            <div class="hime-el-slicder--with-label">
              <span> 0% </span>
              <el-slider
                v-model="appStore.config.display['spine-initial-width-range']"
                class="hime-el-slider"
                show-tooltip
                :format-tooltip="(value) => value + '%'"
                range
                :min="0"
                :max="100"
              />
              <span> 100% </span>
            </div>
          </config-item>
          <config-item :label="$t('display.height-range')">
            <div class="hime-el-slicder--with-label">
              <span> 0% </span>
              <el-slider
                v-model="appStore.config.display['spine-initial-height-range']"
                class="hime-el-slider"
                show-tooltip
                :format-tooltip="(value) => value + '%'"
                range
                :min="0"
                :max="100"
              />
              <span> 100% </span>
            </div>
          </config-item>
          <config-item :label="$t('display.drag-to-move')">
            <el-switch v-model="appStore.config.display['spine-draggable']" />
          </config-item>
          <config-item :label="$t('display.premultiply-alpha')">
            <el-switch
              v-model="appStore.config.display['spine-premultiply-alpha']"
            />
          </config-item>
        </el-form-item>
        <el-form-item :label="$t('display.mmd-render')">
          <config-item :label="$t('display.outline-effect')">
            <el-switch
              v-model="appStore.config.display['mmd-outline-effect']"
            />
          </config-item>
          <config-item :label="$t('display.camera-orbit-control')">
            <el-switch
              v-model="appStore.config.display['mmd-orbit-controls']"
            />
          </config-item>
        </el-form-item>
        <el-form-item :label="$t('display.vroid-render')">
          <config-item :label="$t('display.outline-effect')">
            <el-switch
              v-model="appStore.config.display['vroid-outline-effect']"
            />
          </config-item>
          <config-item :label="$t('display.camera-orbit-control')">
            <el-switch
              v-model="appStore.config.display['vroid-orbit-controls']"
            />
          </config-item>
        </el-form-item>
      </el-form>
    </el-scrollbar>
    <el-divider class="hime-el-divider" />
    <div class="display-option">
      <div class="display-option__state">
        <span>{{ $t("display.display-window-state") }}</span>
        <el-tag
          effect="light"
          :type="appStore.displayWindowId === -1 ? 'warning' : 'primary'"
        >
          {{
            appStore.displayWindowId !== -1
              ? $t("display.launched")
              : $t("display.not-launched")
          }}
        </el-tag>
      </div>
      <div class="display-option__control">
        <el-button
          @click="ipcAPI.screenshot"
          :disabled="appStore.displayWindowId === -1"
          plain
        >
          {{ $t("display.screenshot") }}
        </el-button>
        <el-button @click="launchDisplayWindow" plain>{{
          appStore.displayWindowId !== -1
            ? $t("display.reload")
            : $t("display.launch")
        }}</el-button>
        <el-button
          @click="closeDisplayWindow"
          type="danger"
          :disabled="appStore.displayWindowId === -1"
          plain
          >{{ $t("display.close") }}</el-button
        >
      </div>
    </div>
  </div>
</template>

<script setup>
import HimeTitleWithDivider from "@control/components/Common/TitleWithDivider.vue";
import ConfigItem from "@control/components/Common/ConfigItem.vue";
import { watch, toRaw } from "vue";
import { useAppStore } from "@control/store/app";
const appStore = useAppStore();
const ipcAPI = window.nodeAPI.ipc;
watch(appStore.config.display, (newValue) => {
  window.nodeAPI.config.write("display", toRaw(newValue));
});
function launchDisplayWindow() {
  if (appStore.displayWindowId !== -1) {
    ipcAPI.relaunchDisplayWindow();
  } else {
    ipcAPI.launchDisplayWindow();
  }
}
function closeDisplayWindow() {
  ipcAPI.closeDisplayWindow();
}
</script>

<style lang="scss">
.hime-el-slider {
  width: 80%;
  margin-left: 12px;
  margin-right: 12px;
}
.display-option {
  display: flex;
  margin: 0 20px;
  // height: 30px;
  .display-option__state {
    display: flex;
    flex: 1;
    align-items: center;
    > span:nth-child(1) {
      margin-right: 10px;
      font-size: var(--el-font-size-large);
      font-weight: bold;
    }
  }
}
// 弃用布局方案
// .display-option {
//   position: relative;
//   margin: 0 20px;
//   // height: 30px;
//   .display-option__state {
//     display: flex;
//     > span:nth-child(1) {
//       margin-right: 10px;
//       font-size: var(--el-font-size-large);
//       font-weight: bold;
//     }
//   }
//   .display-option__control {
//     position: absolute;
//     right: 0;
//     top: 0;
//   }
// }
</style>


================================================
FILE: src/renderer/control/components/Contents/General.vue
================================================
<template>
  <div class="hime-content">
    <hime-title-with-divider>{{ $t("menu.general") }}</hime-title-with-divider>
    <el-scrollbar height="100%">
      <el-form label-width="170px" class="hime-el-form--config">
        <el-form-item :label="$t('general.when-launch')">
          <config-item :label="$t('general.open-control-panel')">
            <el-switch
              v-model="appStore.config.general['open-control-at-launch']"
            />
          </config-item>
          <config-item :label="$t('general.open-display-window')">
            <el-switch
              v-model="appStore.config.general['open-display-at-launch']"
            />
          </config-item>
        </el-form-item>
        <el-form-item :label="$t('general.language')">
          <config-item>
            <el-select
              v-model="appStore.config.general.language"
              @change="changeLanguage"
            >
              <el-option
                v-for="(value, label) in languageNames"
                :key="label"
                :label="label"
                :value="value"
              />
            </el-select>
          </config-item>
        </el-form-item>
        <el-form-item :label="$t('general.developer-tools')">
          <!-- 配置项的样式被调整过了,这里懒得拉样式,整个div框起来算了 -->
          <config-item>
            <el-button @click="openDevTool('control')">
              {{ $t("general.control-panel") }}
            </el-button>
            <el-button
              @click="openDevTool('display')"
              :disabled="appStore.displayWindowId === -1"
              >{{ $t("general.display-window") }}</el-button
            >
          </config-item>
          <config-item :label="$t('general.alert-error-info')">
            <el-switch v-model="appStore.config.general['error-report']" />
          </config-item>
        </el-form-item>
        <el-form-item :label="$t('general.restore')">
          <el-popconfirm
            :title="$t('general.restore-all-config-confirm')"
            @confirm="resetAllConfig"
          >
            <template #reference>
              <el-button>{{ $t("general.restore-all-config") }}</el-button>
            </template>
          </el-popconfirm>
        </el-form-item>
      </el-form>
    </el-scrollbar>
  </div>
</template>

<script setup>
import HimeTitleWithDivider from "@control/components/Common/TitleWithDivider.vue";
import ConfigItem from "@control/components/Common/ConfigItem.vue";
import { watch, toRaw } from "vue";
import { useAppStore } from "@control/store/app";
import languageNames from "@shared/locales/languageNames";
import { useTranslation } from "i18next-vue";
const ipcAPI = window.nodeAPI.ipc;
const { i18next } = useTranslation();
const appStore = useAppStore();
watch(appStore.config.general, (newValue) => {
  window.nodeAPI.config.write("general", toRaw(newValue));
});
function changeLanguage(language) {
  ipcAPI.changeLanguage(language);
  i18next.changeLanguage(language);
}
function openDevTool(type) {
  ipcAPI.openDevTool(type);
}
function resetAllConfig() {
  window.nodeAPI.config.resetAllConfig();
  appStore.syncConfig();
  // 手动触发语言更改
  changeLanguage(appStore.config.general.language);
}
</script>

<style lang="scss"></style>


================================================
FILE: src/renderer/control/components/Contents/Model.vue
================================================
<template>
  <div class="hime-content">
    <hime-title-with-divider>{{ $t("menu.model") }}</hime-title-with-divider>
    <el-form label-position="top" class="hime-el-form--large-label">
      <el-form-item :label="$t('model.model-db')">
        <el-input
          v-model="searchModelText"
          :placeholder="$t('model.search-model')"
          clearable
          class="hime-el-input--model-search"
        />
        <el-table
          :data="filterModelData"
          @current-change="changeCurrentModelInfo"
          size="small"
          height="350"
          highlight-current-row
          tooltip-effect="light"
          class="hime-current-row--adjust-bg-color hime-el-table--model"
        >
          <el-table-column type="index" width="60" align="center" />
          <el-table-column
            :label="$t('model.name')"
            prop="name"
            width="280"
            show-overflow-tooltip
            sortable
          />
          <el-table-column
            :label="$t('model.version')"
            prop="name"
            align="center"
          >
            <template #default="props">
              {{ calcModelVersion(props.row) }}
            </template>
          </el-table-column>
          <el-table-column
            :label="$t('model.type')"
            :filters="[
              { text: 'Live2D', value: 'Live2D' },
              { text: 'MMD', value: 'MMD' },
              { text: 'VRoid', value: 'VRoid' },
              { text: 'Spine', value: 'Spine' },
            ]"
            :filter-method="
              (value, row) => {
                return row.modelType === value;
              }
            "
            align="center"
          >
            <template #default="props">
              <el-tag
                effect="light"
                :color="props.row.themeColor + '22'"
                :style="{
                  color: props.row.themeColor,
                  'border-color': props.row.themeColor + '44',
                }"
              >
                {{ props.row.modelType }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column
            :label="$t('model.extension')"
            :filters="[
              { text: 'moc', value: 'moc' },
              { text: 'moc3', value: 'moc3' },
              { text: 'pmx', value: 'pmx' },
              { text: 'vrm', value: 'vrm' },
              { text: 'json', value: 'json' },
            ]"
            :filter-method="
              (value, row) => {
                return row.extensionName === value;
              }
            "
            align="center"
          >
            <template #default="props">
              <el-tag effect="light" type="info">
                {{ props.row.extensionName }}
              </el-tag>
            </template>
          </el-table-column>
        </el-table>
        <el-button
          @click="loadModelNow(currentModelInfo.value)"
          :disabled="appStore.displayWindowId === -1 || !modelTableSelected"
          >{{ $t("model.load-selected-model") }}</el-button
        >
      </el-form-item>
    </el-form>
  </div>
</template>

<script setup>
import HimeTitleWithDivider from "@control/components/Common/TitleWithDivider.vue";
import { ref, toRaw, markRaw, reactive, computed, watch } from "vue";
import { useAppStore } from "@control/store/app";
import { useControlStore } from "@control/store/control";
const appStore = useAppStore();
const controlStore = useControlStore();
const currentModelInfo = reactive({ value: null });
const modelTableSelected = ref(false);
const ipcAPI = window.nodeAPI.ipc;
function changeCurrentModelInfo(currentRow) {
  modelTableSelected.value = true;
  currentModelInfo.value = currentRow;
}
function loadModelNow(modelInfo) {
  const rawModelInfo = toRaw(modelInfo);
  controlStore.currentModelType = rawModelInfo.modelType;
  controlStore.modelControlInfoLoading = true;
  controlStore.modelControlInfo = null;
  // 更新数据库中的当前模型信息
  appStore.database.modelNow = rawModelInfo;
  window.nodeAPI.database.write("modelNow", rawModelInfo);
  ipcAPI.loadModel(rawModelInfo);
  console.log(
    `[Hime Display] Load model: name:${rawModelInfo.name}, modelType:${rawModelInfo.modelType}`
  );
  ipcAPI.receiveModelControlInfo((event, modelControlInfo) => {
    // 关键点,使用markRaw包装对象。一些模型,比如MMD的层级结构复杂的离谱,能往下嵌套十几级,涉及到四五百,甚至更多的骨骼,用成响应式对象会直接影响到性能
    // 按现在这种写法,modelControlInfo在发生引用值改变时依旧可以响应式变化,例如设定controlStore.modelControlInfo={}是可以响应式改变UI的,只是改变modelControlInfo内部的东西不会触发UI变化
    controlStore.modelControlInfo = markRaw(modelControlInfo);
    controlStore.modelControlInfoLoading = false;
  });
}
// 如果这个页面没有加载过,这里的watch就不会生效,导致无法在打开应用时自动加载上次的模型
// 默认打开页面一直是这个Model页面,换了一个页面才发现这个问题,后来想了一下,还是就把默认的启动页面设定为model吧
watch(appStore.displayWindowOpened, (value) => {
  console.log("[Hime Display] displayWindowId changed", value.value);
  if (value.value) {
    ipcAPI.queryDisplayWindowState();
    ipcAPI.handleDisplayWindowState((event, message) => {
      console.log("[Hime Display] displayWindowState", message);
      if (
        !message.modelLoaded &&
        appStore.config.display["auto-load-last"] &&
        appStore.database.modelNow !== null
      ) {
        loadModelNow(appStore.database.modelNow);
      }
      // 下方代码用于处理控制面板重新后模型信息清空的问题,但是用这种机制来处理的话,模型控制的instant config难以被同步到控制面板上,目前该用不关闭控制面板,在主进程改为隐藏的操作来解决这个问题
      // else  if (message.modelLoaded) {
      //   controlStore.currentModelType = appStore.database.modelNow.modelType;
      //   controlStore.modelControlInfo = markRaw(message.modelControlInfo);
      //   controlStore.modelControlInfoLoading = false;
      // }
    });
  }
});
const searchModelText = ref("");
const filterModelData = computed(() =>
  appStore.database.model.filter(
    (data) =>
      !searchModelText.value ||
      data.name.toLowerCase().includes(searchModelText.value.toLowerCase())
  )
);
const calcModelVersion = (modelInfo) => {
  if (modelInfo.version) {
    return modelInfo.version;
  } else if (modelInfo.modelType === "Live2D") {
    if (modelInfo.extensionName === "moc") {
      return "2.x";
    } else if (modelInfo.extensionName === "moc3") {
      return "3.x/4.x";
    }
  } else {
    return "--";
  }
};
</script>

<style lang="scss">
.hime-el-table--model {
  margin-bottom: 10px;
}
.hime-current-row--adjust-bg-color {
  // 同时:hover和current应该显示current的效果更合理
  .el-table__body tr:hover.current-row > td.el-table__cell {
    background-color: var(--el-table-current-row-bg-color);
  }
  // 考虑加深强调颜色
  //   --el-table-current-row-bg-color: var(--el-color-primary-light-8);
  // tr {
  //   --el-table-row-hover-bg-color: var(--el-color-primary-light-9);
  // }
}
.hime-el-input--model-search {
  margin-bottom: 8px;
}
</style>


================================================
FILE: src/renderer/control/components/Contents/Source.vue
================================================
<template>
  <div class="hime-content">
    <hime-title-with-divider>{{ $t("menu.source") }}</hime-title-with-divider>
    <el-form label-position="top" class="hime-el-form--large-label">
      <el-form-item :label="$t('source.data-source')">
        <!-- row-key用于辨识row,解决expand输入内容后自动折叠,以及一旦展开就变成全部展开的问题 -->
        <el-table
          :data="appStore.database.sourcePathInfo"
          :border="true"
          row-key="sourcePath"
          ref="sourceTable"
          class="hime-el-table--source-path"
          size="small"
          tooltip-effect="light"
          max-height="160"
        >
          <!-- 使用width="1"隐藏默认小箭头 -->
          <el-table-column type="expand" width="1">
            <template #default="props">
              <div class="hime-el-table__expanded-container">
                <el-form
                  label-position="top"
                  class="hime-el-form--expanded"
                  :inline="true"
                >
                  <el-form-item :label="$t('source.search-type')">
                    <!-- 官方文档里面没有说el-checkbox-button有change事件,但是经过实际测试是有的,然后就拿来用了 -->
                    <el-checkbox-button
                      v-for="sourceType in sourceTypes"
                      v-model="props.row.sourceTypes[sourceType]"
                      :key="sourceType"
                      :label="sourceType"
                      @change="writeSourcePathInfo"
                    />
                  </el-form-item>
                </el-form>
              </div>
            </template>
          </el-table-column>
          <el-table-column
            :label="$t('source.source-path')"
            prop="sourcePath"
            show-overflow-tooltip
          />
          <!-- 备选方案:通过滚动展示过长的路径名
        <el-table-column label="路径" prop="path">
          <template #default="props">
            <el-scrollbar>
              <div style="padding: 0 10px">
                {{ props.row.path }}
              </div>
            </el-scrollbar>
          </template>
        </el-table-column> -->
          <el-table-column
            :label="$t('source.operate')"
            width="210"
            align="center"
          >
            <template #default="props">
              <el-tooltip :show-after="600" effect="light">
                <template #default>
                  <!-- 发现props里有个文档里没说的expanded属性,正好可以拿来用 -->
                  <svg-icon-el-button
                    size="small"
                    :name="'sf-' + (props.expanded ? 'close' : 'edit')"
                    @click="expandRow(props.row)"
                  ></svg-icon-el-button>
                </template>
                <template #content>
                  {{
                    props.expanded
                      ? $t("source.end-edit-search-type")
                      : $t("source.edit-search-type")
                  }}
                </template>
              </el-tooltip>
              <el-tooltip :show-after="600" effect="light">
                <template #default>
                  <svg-icon-el-button
                    size="small"
                    name="sf-source"
                    @click="showInFolder(props.row.sourcePath)"
                  ></svg-icon-el-button>
                </template>
                <template #content>
                  {{ $t("source.show-in-file-browser") }}</template
                >
              </el-tooltip>
              <el-tooltip :show-after="600" effect="light">
                <template #default>
                  <svg-icon-el-button
                    size="small"
                    name="sf-refresh"
                    @click="loadFromSourcePath(props.row)"
                  ></svg-icon-el-button>
                </template>
                <template #content> {{ $t("source.refresh") }} </template>
              </el-tooltip>
              <el-popconfirm
                :title="$t('source.delete-source-confirm')"
                @confirm="deleteSourcePath(props.$index)"
              >
                <template #reference>
                  <!-- 嵌套使用el-popconfirm和el-tooltip需要加一层div包裹,但这会导致样式变化 -->
                  <div style="display: inline-block; margin-left: 12px">
                    <el-tooltip :show-after="600" effect="light">
                      <template #default>
                        <svg-icon-el-button
                          size="small"
                          name="sf-delete"
                        ></svg-icon-el-button>
                      </template>
                      <template #content>
                        {{ $t("source.delete-source") }}
                      </template>
                    </el-tooltip>
                  </div>
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        <el-button @click="addSourePath">{{
          $t("source.add-source")
        }}</el-button>
        <el-button @click="loadFromSourcePathAll">{{
          $t("source.search-all-source")
        }}</el-button>
      </el-form-item>
      <el-form-item :label="$t('source.statistic-info')">
        <el-table :data="totalInfo" size="small" :border="true">
          <el-table-column
            v-for="(totalCount, totalName) in totalInfo[0]"
            :prop="totalName"
            :label="totalName"
            align="center"
          >
          </el-table-column>
        </el-table>
      </el-form-item>
    </el-form>
  </div>
</template>

<script setup>
import { ref, toRaw, computed } from "vue";
import SvgIconElButton from "@control/components/Common/SvgIconElButton.vue";
import HimeTitleWithDivider from "@control/components/Common/TitleWithDivider.vue";
import { useAppStore } from "@control/store/app";
const appStore = useAppStore();
const sourceTypes = ["Live2D", "Spine", "VRoid", "MMD", "motion3D", "audio3D"];
const sourceTable = ref();
const totalInfo = computed(() => [
  {
    Live2D: appStore.database.model.filter((item) => {
      return item.modelType === "Live2D";
    }).length,
    Spine: appStore.database.model.filter((item) => {
      return item.modelType === "Spine";
    }).length,
    VRoid: appStore.database.model.filter((item) => {
      return item.modelType === "VRoid";
    }).length,
    MMD: appStore.database.model.filter((item) => {
      return item.modelType === "MMD";
    }).length,
    motion3D: appStore.database.motion3D.length,
    audio3D: appStore.database.audio3D.length,
  },
]);
// 不能watch了,我人要废了……因为同步数据库也会触发watch的,需要的时候我还是手动写入数据吧
// // 实时更新数据库
// watch(appStore.database.sourcePathInfo, (newValue) => {
//   // 这里没办法只有把整个source数据传过去
//   window.nodeAPI.database.write("sourcePathInfo", toRaw(newValue));
// });
function writeSourcePathInfo() {
  window.nodeAPI.database.write(
    "sourcePathInfo",
    toRaw(appStore.database.sourcePathInfo)
  );
}
function expandRow(row) {
  sourceTable.value.toggleRowExpansion(row);
  // 这不是script setup里的用法
  // console.log(this.$refs);
  // this.$refs.sourceTable.toggleRowExpansion(row);
}
function showInFolder(path) {
  window.nodeAPI.showInFolder(path);
}
function deleteSourcePath(index) {
  // 移除数据源相关的数据条目
  const sourcePath = appStore.database.sourcePathInfo[index].sourcePath;
  window.nodeAPI.database.removeDataFromSourcePath(sourcePath);
  appStore.syncDatabase();
  // 千万别在这条语句下方同步数据库,不然直接把preload里面的旧sourcePathInfo数据弄过来了
  appStore.database.sourcePathInfo.splice(index, 1);
  writeSourcePathInfo();
}
function addSourePath() {
  window.nodeAPI.ipc.selectPath().then((path) => {
    if (path.length > 0) {
      // 这里不自动执行loadFromSourcePath是有深刻原因的,用户或许并不希望载入所有的sourceTypes,因此应当等到筛选sourceTypes后再手动载入
      appStore.database.sourcePathInfo.push({
        sourcePath: path[0],
        tagName: "",
        sourceTypes: {
          Live2D: true,
          Spine: true,
          MMD: true,
          VRoid: true,
          motion3D: true,
          audio3D: true,
        },
      });
      writeSourcePathInfo();
    }
  });
}
function loadFromSourcePath(sourcePathInfo) {
  window.nodeAPI.database
    .loadDataFromSourcePathInfo(toRaw(sourcePathInfo))
    .then(() => {
      appStore.syncDatabase();
    });
}
function loadFromSourcePathAll() {
  const promises = [];
  appStore.database.sourcePathInfo.forEach((sourcePathInfo) => {
    promises.push(
      window.nodeAPI.database.loadDataFromSourcePathInfo(toRaw(sourcePathInfo))
    );
  });
  Promise.all(promises).then(() => {
    appStore.syncDatabase();
  });
}
</script>

<style lang="scss">
.hime-el-table--source-path {
  margin-bottom: 10px;
  .el-table__expand-icon {
    // 配合上方的width="1"使用,可以隐藏默认的小箭头
    color: transparent;
  }
  .el-table__expanded-cell {
    .hime-el-table__expanded-container {
      padding: 5px 0 5px 20px;
    }
    .hime-el-table__expanded-input--tag {
      width: 75px;
      margin-top: 2px;
    }
  }
}

// 直接将size设为small就行了
// .el-table .el-table__cell {
//   padding: 6px 0;
// }
//element plus的样式里有一个.el-form-item .el-form-item选择器会把margin-bottom设为0,这里覆盖一下
// .el-form-item .source--form .el-form-item {
//   margin-bottom: 18px;
// }
// .hime-el-form--expanded input {
//   width: 80px;
// }
</style>


================================================
FILE: src/renderer/control/components/Main.vue
================================================
<template>
  <el-main
    v-loading="
      controlStore.modelControlInfoLoading &&
      contentComponentNow === HimeControl
    "
  >
    <!-- 之前也考虑过采用vue的路由方案,但配置起来较为麻烦,而且似乎做不到保存组件缓存的操作,所以还是采用了动态组件的方案。 -->
    <!-- 使用keep-alive保存组件的缓存,没必要每次都加载 -->
    <!-- 使用了<script setup>后,动态组件的is参数似乎无法直接接收字符串,只能使用组件对象 -->
    <keep-alive>
      <component :is="contentComponentNow"></component>
    </keep-alive>
  </el-main>
</template>

<script setup>
import capitalize from "lodash/capitalize";
import HimeGeneral from "@control/components/Contents/General.vue";
import HimeDisplay from "@control/components/Contents/Display.vue";
import HimeControl from "@control/components/Contents/Control/index.vue";
import HimeModel from "@control/components/Contents/Model.vue";
import HimeSource from "@control/components/Contents/Source.vue";
import HimeAbout from "@control/components/Contents/About.vue";
import { computed } from "vue";
import { useAppStore } from "@control/store/app";
import { useControlStore } from "@control/store/control";
const appStore = useAppStore();
const controlStore = useControlStore();
// 借助对象完成字符串到组件的映射
const contentComponents = {
  HimeGeneral,
  HimeDisplay,
  HimeControl,
  HimeModel,
  HimeSource,
  HimeAbout,
};
const contentComponentNow = computed(() => {
  return contentComponents["Hime" + capitalize(appStore.ui.activeMenuItem)];
});
</script>

<style lang="scss">
.el-main {
  background-color: var(--el-fill-color-lighter);
}
.hime-content {
  width: 100%;
  // 限住高度,让el-scrollbar生效
  height: 100%;
  display: flex;
  flex-direction: column;
}

// 调节config的页面样式,即display页面和general页面

.hime-el-form--config {
  .el-form-item {
    margin-bottom: 12px;
    .el-form-item__label {
      font-size: var(--el-font-size-medium);
      font-weight: bold;
    }
    .el-form-item__content {
      flex-direction: column;
      align-items: flex-start;
      .hime-el-slicder--with-label {
        display: flex;
        width: 300px;
      }
    }
  }
}
.hime-el-form--large-label > .el-form-item > .el-form-item__label {
  font-size: var(--el-font-size-extra-large);
  line-height: initial;
}
</style>


================================================
FILE: src/renderer/control/components/Menu/Index.vue
================================================
<template>
  <el-aside>
    <div class="menu">
      <hime-menu-item
        v-for="menuItem in menuItems"
        :menu-item="menuItem"
      ></hime-menu-item>
    </div>
  </el-aside>
</template>

<script setup>
import HimeMenuItem from "./MenuItem.vue";
const menuItems = ["general", "display", "control", "model", "source", "about"];
</script>

<style lang="scss">
.el-aside {
  width: 72px;
  padding: 40px 8px;
}
</style>


================================================
FILE: src/renderer/control/components/Menu/MenuItem.vue
================================================
<template>
  <div
    class="menu-item"
    :class="{ active: appStore.ui.activeMenuItem === menuItem }"
    @click="appStore.ui.activeMenuItem = menuItem"
  >
    <svg-icon :name="'sf-' + menuItem"></svg-icon>
    <div :style="{ 'font-size': itemNameFontSize }">
      {{ $t("menu." + menuItem) }}
    </div>
  </div>
</template>

<script setup>
import SvgIcon from "@control/components/Common/SvgIcon.vue";
import { useAppStore } from "@control/store/app";
import { useTranslation } from "i18next-vue";
const { i18next } = useTranslation();
// 日语的菜单有部分片假名过长导致折行,本想采用计算是否换行以对字体进行缩小,但是这东西意外的难以获取,所以暂时改为直接判断文本内容的方式吧
// import { ref, onMounted } from "vue";
// const itemNameRef = ref();
// onMounted(() => {
//   console.log(itemNameRef.value.scrollHeight);
// });
import { computed } from "vue";
const props = defineProps({
  menuItem: String,
});
const itemNameFontSize = computed(() => {
  if (
    ["ディスプレイ", "コントロール"].includes(
      i18next.t("menu." + props.menuItem)
    )
  ) {
    return "0.6rem";
  }
  return "0.85rem";
});
const appStore = useAppStore();
</script>

<style lang="scss">
.menu-item {
  display: flex;
  align-items: center;
  flex-direction: column;
  font-weight: bold;
  // font-size: 0.7rem;兼容日语,已改为动态判断
  border-radius: 10px;
  padding: 8px 0;
  div {
    color: var(--el-text-color-regular);
  }
  svg {
    width: 24px;
    height: 24px;
    margin-bottom: 3px;
    use {
      fill: var(--el-text-color-regular);
    }
  }
}
.menu-item.active {
  div {
    color: var(--el-color-primary);
  }
  svg {
    use {
      fill: var(--el-color-primary);
    }
  }
  background-color: $menu-background-color-active;
}
</style>


================================================
FILE: src/renderer/control/i18n.js
================================================
import i18next from "@shared/locales/i18next";
import I18NextVue from "i18next-vue";

export default function (app) {
  app.use(I18NextVue, { i18next });
  return app;
}


================================================
FILE: src/renderer/control/main.js
================================================
import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";
import i18n from "./i18n";
import "virtual:svg-icons-register";
// 在App.vue中采用了手动引入ElMessage的方式后,ElMessage的样式不会被自动加载,只能在这里手动引入一下
import "element-plus/theme-chalk/src/message.scss";
// 以下操作全寄……
// import "element-plus/theme-chalk/src/dark/css-vars.scss";
// import "@control/styles/dark.scss";
// import "@control/styles/el-theme.scss";
// import "element-plus/theme-chalk/dark/css-vars.css";
const app = createApp(App);
app.use(createPinia());
i18n(app);
app.mount("#app");


================================================
FILE: src/renderer/control/store/app.js
================================================
import { defineStore } from "pinia";
export const useAppStore = defineStore("app", {
  state: () => ({
    // initialized: false,
    ui: {
      activeMenuItem: "model",
    },
    database: {
      // 防止下方的splice爆炸
      // sourcePathInfo: [],
    },
    config: {},
    displayWindowId: -1,
    // 上方的原始值无法直接进行监听,此属性用于响应式监听展示器状态
    displayWindowOpened: {
      value: false,
    },
  }),
  actions: {
    syncDatabase() {
      // database直接赋值会失去响应性,如果watch监视了这里的this.database.sourcePathInfo,对this.database直接赋值,watch将直接失效。现在看来pinia对数据的封装应该是等效于reactive的
      // const database = window.nodeAPI.database.value();
      // this.database.sourcePathInfo.splice(0);
      // sourcePathInfo也不能直接赋值,因为到时候是监视sourcePathInfo,反正说来说去就是sourcePathInfo的指向不能变,看到一种方法是在对象下再封装一层数据,但是这样依赖database的结构都变了,因此这里就一点一点的往里面填数据吧
      // database.sourcePathInfo.forEach((source) => {
      //   this.database.sourcePathInfo.push(source);
      // });
      // this.database.model = database.model;
      // this.database.motion3D = database.motion3D;
      // this.database.audio3D = database.audio3D;

      // 好吧目前不用watch了以后,这么搞似乎问题也不大
      this.database = window.nodeAPI.database.value();
    },
    syncConfig() {
      const confingValue = window.nodeAPI.config.value();
      this.config.general = confingValue.general;
      this.config.display = confingValue.display;
    },
  },
});
// export const useAppStore = function () {
//   const appStore = defineAppStore();
//   if (!appStore.initialized) {
//     appStore.initialized = true;
//     appStore.syncDatabase();
//   }
//   return appStore;
// };


================================================
FILE: src/renderer/control/store/control.js
================================================
// 对模型进行控制的Store
import { defineStore } from "pinia";
export const useControlStore = defineStore("control", {
  state: () => ({
    currentModelType: "",
    modelControlInfoLoading: false,
    modelControlInfo: null,
  }),
});


================================================
FILE: src/renderer/control/styles/el-theme.scss
================================================
// 颜色主题配置预留
// $--color
Download .txt
gitextract_hi3z8e4c/

├── .eslintrc.js
├── .github/
│   └── workflows/
│       └── release.yml
├── .gitignore
├── LICENSE
├── README-CN.md
├── README-JP.md
├── README.md
├── build.config.js
├── package.json
├── public/
│   └── background/
│       └── background.tiff
├── scripts/
│   ├── build.js
│   ├── constants.js
│   └── dev-runner.js
└── src/
    ├── main/
    │   ├── Application.js
    │   ├── Launcher.js
    │   ├── core/
    │   │   ├── ExceptionHandler.js
    │   │   └── Logger.js
    │   ├── index.js
    │   ├── menus/
    │   │   └── tray.js
    │   ├── options/
    │   │   ├── paths.js
    │   │   └── windows.js
    │   ├── package.json
    │   ├── ui/
    │   │   ├── ThemeManager.js
    │   │   ├── TrayManager.js
    │   │   └── WindowManager.js
    │   └── vite.config.js
    ├── preload/
    │   ├── control/
    │   │   ├── config.js
    │   │   ├── database.js
    │   │   ├── index.js
    │   │   ├── ipc.js
    │   │   ├── paths.js
    │   │   ├── theme.js
    │   │   ├── utils.js
    │   │   └── vite.config.js
    │   ├── display/
    │   │   ├── index.js
    │   │   ├── ipc.js
    │   │   └── vite.config.js
    │   └── package.json
    ├── renderer/
    │   ├── control/
    │   │   ├── App.vue
    │   │   ├── components/
    │   │   │   ├── Common/
    │   │   │   │   ├── ConfigItem.vue
    │   │   │   │   ├── SvgIcon.vue
    │   │   │   │   ├── SvgIconElButton.vue
    │   │   │   │   └── TitleWithDivider.vue
    │   │   │   ├── Contents/
    │   │   │   │   ├── About.vue
    │   │   │   │   ├── Control/
    │   │   │   │   │   ├── Common/
    │   │   │   │   │   │   ├── 2d/
    │   │   │   │   │   │   │   ├── EventAnimation.vue
    │   │   │   │   │   │   │   └── Transform2D.vue
    │   │   │   │   │   │   ├── 3d/
    │   │   │   │   │   │   │   ├── AnimationControl.vue
    │   │   │   │   │   │   │   ├── ObjectTransform3D.vue
    │   │   │   │   │   │   │   ├── ParameterControl.vue
    │   │   │   │   │   │   │   └── Transform3D.vue
    │   │   │   │   │   │   ├── ControlLoadError.vue
    │   │   │   │   │   │   ├── ModelDescription.vue
    │   │   │   │   │   │   └── MotionCapture.vue
    │   │   │   │   │   ├── Live2DControl/
    │   │   │   │   │   │   ├── AnimationControl.vue
    │   │   │   │   │   │   ├── ParameterControl.vue
    │   │   │   │   │   │   └── index.vue
    │   │   │   │   │   ├── MMDControl/
    │   │   │   │   │   │   └── index.vue
    │   │   │   │   │   ├── SpineControl/
    │   │   │   │   │   │   ├── AnimationControl.vue
    │   │   │   │   │   │   ├── ParameterControl.vue
    │   │   │   │   │   │   └── index.vue
    │   │   │   │   │   ├── VRoidControl/
    │   │   │   │   │   │   └── index.vue
    │   │   │   │   │   └── index.vue
    │   │   │   │   ├── Display.vue
    │   │   │   │   ├── General.vue
    │   │   │   │   ├── Model.vue
    │   │   │   │   └── Source.vue
    │   │   │   ├── Main.vue
    │   │   │   └── Menu/
    │   │   │       ├── Index.vue
    │   │   │       └── MenuItem.vue
    │   │   ├── i18n.js
    │   │   ├── main.js
    │   │   ├── store/
    │   │   │   ├── app.js
    │   │   │   └── control.js
    │   │   └── styles/
    │   │       └── el-theme.scss
    │   ├── control.html
    │   ├── display/
    │   │   ├── Application.js
    │   │   ├── main.js
    │   │   ├── modelManagers/
    │   │   │   ├── Live2dManager.js
    │   │   │   ├── MmdManager.js
    │   │   │   ├── ModelManager.js
    │   │   │   ├── ModelManager3D.js
    │   │   │   ├── SpineManager.js
    │   │   │   ├── SpineManager42.js
    │   │   │   └── VroidManager.js
    │   │   └── utils/
    │   │       ├── 2d/
    │   │       │   └── utils.js
    │   │       ├── 3d/
    │   │       │   ├── AudioManager.js
    │   │       │   ├── Monitor.js
    │   │       │   ├── MouseFocusHelper.js
    │   │       │   └── NodeInfo.js
    │   │       ├── animation/
    │   │       │   ├── Mixamo2MMDAnimationConverter.js
    │   │       │   ├── Mixamo2MMDAnimationConverterNew.js
    │   │       │   └── utils.js
    │   │       ├── capture/
    │   │       │   ├── FaceMeshCaptureManager.js
    │   │       │   ├── HolisticCaptureManager.js
    │   │       │   ├── Live2DFaceMeshCaptureManager.js
    │   │       │   ├── MMDFaceMeshCaptureManager.js
    │   │       │   ├── MMDHolisticCaptureManager.js
    │   │       │   ├── VRoidFaceMeshCaptureManager.js
    │   │       │   ├── VRoidHolisticCaptureManager.js
    │   │       │   ├── parents/
    │   │       │   │   └── parents.js
    │   │       │   └── rig/
    │   │       │       ├── 3DRig.js
    │   │       │       ├── MMDRig.js
    │   │       │       └── VRoidRig.js
    │   │       ├── common.js
    │   │       ├── live2d/
    │   │       │   ├── Cubism2Shim.js
    │   │       │   └── Monitor.js
    │   │       ├── mmd/
    │   │       │   ├── AnimationManager.js
    │   │       │   └── Monitor.js
    │   │       ├── record/
    │   │       │   └── RecordManager.js
    │   │       ├── spine/
    │   │       │   └── premultipliedImageLoader.js
    │   │       └── vroid/
    │   │           └── Monitor.js
    │   ├── display.html
    │   ├── package.json
    │   ├── public/
    │   │   └── lib/
    │   │       ├── @mediapipe/
    │   │       │   ├── cdn/
    │   │       │   │   ├── camera_utils.js
    │   │       │   │   ├── drawing_utils.js
    │   │       │   │   ├── face_mesh.js
    │   │       │   │   └── holistic.js
    │   │       │   ├── face_mesh/
    │   │       │   │   ├── face_mesh.binarypb
    │   │       │   │   ├── face_mesh_solution_packed_assets.data
    │   │       │   │   ├── face_mesh_solution_packed_assets_loader.js
    │   │       │   │   ├── face_mesh_solution_simd_wasm_bin.data
    │   │       │   │   ├── face_mesh_solution_simd_wasm_bin.js
    │   │       │   │   ├── face_mesh_solution_simd_wasm_bin.wasm
    │   │       │   │   ├── face_mesh_solution_wasm_bin.js
    │   │       │   │   └── face_mesh_solution_wasm_bin.wasm
    │   │       │   └── holistic/
    │   │       │       ├── holistic.binarypb
    │   │       │       ├── holistic_solution_packed_assets.data
    │   │       │       ├── holistic_solution_packed_assets_loader.js
    │   │       │       ├── holistic_solution_simd_wasm_bin.data
    │   │       │       ├── holistic_solution_simd_wasm_bin.js
    │   │       │       ├── holistic_solution_simd_wasm_bin.wasm
    │   │       │       ├── holistic_solution_wasm_bin.js
    │   │       │       ├── holistic_solution_wasm_bin.wasm
    │   │       │       ├── pose_landmark_full.tflite
    │   │       │       ├── pose_landmark_heavy.tflite
    │   │       │       └── pose_landmark_lite.tflite
    │   │       ├── spine/
    │   │       │   └── pixi-spine.umd.js
    │   │       └── three/
    │   │           ├── ammo.wasm.js
    │   │           └── ammo.wasm.wasm
    │   └── vite.config.js
    └── shared/
        ├── constants.js
        ├── defaults/
        │   ├── defalutDatabase.js
        │   └── defaultConfig.js
        └── locales/
            ├── en/
            │   ├── control.js
            │   ├── display.js
            │   ├── general.js
            │   ├── index.js
            │   ├── menu.js
            │   ├── message.js
            │   ├── model.js
            │   ├── source.js
            │   └── tray.js
            ├── i18next.js
            ├── jp/
            │   ├── control.js
            │   ├── display.js
            │   ├── general.js
            │   ├── index.js
            │   ├── menu.js
            │   ├── message.js
            │   ├── model.js
            │   ├── source.js
            │   └── tray.js
            ├── languageNames.js
            ├── resources.js
            └── zh-CN/
                ├── control.js
                ├── display.js
                ├── general.js
                ├── index.js
                ├── menu.js
                ├── message.js
                ├── model.js
                ├── source.js
                └── tray.js
Download .txt
Showing preview only (263K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2557 symbols across 66 files)

FILE: scripts/build.js
  function build (line 28) | function build() {
  function buildRenderer (line 64) | async function buildRenderer() {
  function buildMainProcess (line 82) | function buildMainProcess(root) {

FILE: scripts/dev-runner.js
  function startRenderer (line 16) | async function startRenderer() {
  function watchMainProcess (line 30) | async function watchMainProcess(root) {
  function startElectron (line 56) | function startElectron(RENDERER_URL) {
  function start (line 81) | async function start() {

FILE: src/main/Application.js
  class Application (line 19) | class Application extends EventEmitter {
    method constructor (line 20) | constructor() {
    method init (line 25) | init() {
    method startApp (line 34) | startApp() {
    method openWindow (line 45) | openWindow(windowName) {
    method setChromiumPreference (line 48) | setChromiumPreference() {
    method initConfigDB (line 54) | initConfigDB() {
    method initLanguage (line 59) | initLanguage() {
    method initWindowManager (line 62) | initWindowManager() {
    method initThemeManager (line 66) | initThemeManager() {
    method initTrayManager (line 76) | initTrayManager() {
    method handleIpcMessages (line 93) | handleIpcMessages() {
    method askForMediaAccess (line 195) | async askForMediaAccess() {
    method quitApp (line 202) | quitApp() {}

FILE: src/main/Launcher.js
  class Launcher (line 7) | class Launcher extends EventEmitter {
    method constructor (line 8) | constructor() {
    method init (line 14) | init() {
    method handleAppEvents (line 22) | handleAppEvents() {

FILE: src/main/core/ExceptionHandler.js
  class ExceptionHandler (line 4) | class ExceptionHandler {
    method constructor (line 5) | constructor() {
    method init (line 8) | init() {

FILE: src/main/options/paths.js
  constant APP_DATA_PATH (line 3) | const APP_DATA_PATH = app.getPath("userData");
  constant APP_CONFIG_PATH (line 4) | const APP_CONFIG_PATH = resolve(APP_DATA_PATH, "config.json");
  constant APP_DATABASE_PATH (line 5) | const APP_DATABASE_PATH = resolve(APP_DATA_PATH, "database.json");
  constant CHROMIUM_PREFERENCE_PATH (line 6) | const CHROMIUM_PREFERENCE_PATH = resolve(APP_DATA_PATH, "Preferences");

FILE: src/main/ui/ThemeManager.js
  class ThemeManager (line 3) | class ThemeManager extends EventEmitter {
    method constructor (line 4) | constructor() {
    method init (line 8) | init() {
    method handelEvents (line 11) | handelEvents() {
    method getSystemTheme (line 16) | getSystemTheme() {

FILE: src/main/ui/TrayManager.js
  class TrayManager (line 8) | class TrayManager extends EventEmitter {
    method constructor (line 9) | constructor() {
    method translateTemplate (line 20) | translateTemplate() {
    method buildMenu (line 28) | buildMenu() {

FILE: src/main/ui/WindowManager.js
  class WindowManager (line 6) | class WindowManager extends EventEmitter {
    method constructor (line 7) | constructor(configDB) {
    method openWindow (line 19) | openWindow(windowName) {
    method sendMessageToWindow (line 100) | sendMessageToWindow(windowName, message, ...args) {
    method allUpdateWindowIds (line 108) | allUpdateWindowIds() {
    method updateWindowIds (line 113) | updateWindowIds(windowName) {

FILE: src/preload/control/config.js
  constant APP_CONFIG_PATH (line 8) | const APP_CONFIG_PATH = path.join(APP_DATA_PATH, "config.json");
  function value (line 11) | function value() {
  function write (line 14) | function write(value, data) {
  function resetAllConfig (line 19) | function resetAllConfig() {

FILE: src/preload/control/database.js
  constant APP_DATABASE_PATH (line 10) | const APP_DATABASE_PATH = path.join(APP_DATA_PATH, "database.json");
  function value (line 13) | function value() {
  function write (line 16) | function write(value, data) {
  function removeDataFromSourcePath (line 19) | function removeDataFromSourcePath(sourcePath) {
  function loadDataFromSourcePathInfo (line 26) | async function loadDataFromSourcePathInfo(sourcePathInfo) {
  function loadDataFromPath (line 92) | async function loadDataFromPath(dataPath, sourceTypes, sourcePath) {
  function detectDatabaseItem (line 123) | async function detectDatabaseItem(fileDir, sourceTypes, sourcePath) {
  function processLive2dJson (line 188) | function processLive2dJson(fileDir, fileJson, sourcePath) {
  function processPmx (line 211) | function processPmx(fileDir, sourcePath) {
  function processVrm (line 221) | function processVrm(fileDir, sourcePath) {
  function processSkel (line 232) | function processSkel(fileDir, sourcePath, fileData) {
  function processSpineJson (line 244) | function processSpineJson(fileDir, fileJson, sourcePath) {
  function processVmd (line 257) | function processVmd(fileDir, sourcePath) {
  function processFbx (line 266) | function processFbx(fileDir, sourcePath) {
  function processWav (line 274) | function processWav(fileDir, sourcePath) {
  function processMp3 (line 282) | function processMp3(fileDir, sourcePath) {
  function splitDirName (line 291) | function splitDirName(fileDir) {
  function resolveEntrancePath (line 297) | function resolveEntrancePath(fileDir) {
  function writeModelInfo (line 303) | function writeModelInfo(modelInfo) {
  function writeMotion3DInfo (line 315) | function writeMotion3DInfo(motionInfo) {
  function writeAudio3DInfo (line 325) | function writeAudio3DInfo(audioInfo) {

FILE: src/preload/control/index.js
  function showInFolder (line 14) | function showInFolder(path) {
  function openLink (line 17) | function openLink(link) {

FILE: src/preload/control/ipc.js
  function selectPath (line 2) | function selectPath() {
  function launchDisplayWindow (line 5) | function launchDisplayWindow() {
  function relaunchDisplayWindow (line 8) | function relaunchDisplayWindow() {
  function closeDisplayWindow (line 11) | function closeDisplayWindow() {
  function queryWindowIds (line 14) | function queryWindowIds() {
  function handleUpdateWindowIds (line 17) | function handleUpdateWindowIds(callback) {
  function receiveModelControlInfo (line 20) | function receiveModelControlInfo(callback) {
  function handleSendToModelControl (line 23) | function handleSendToModelControl(callback) {
  function removeManagerListeners (line 27) | function removeManagerListeners() {
  function openDevTool (line 30) | function openDevTool(type) {
  function changeLanguage (line 33) | function changeLanguage(language) {
  function handleDisplayWindowState (line 36) | function handleDisplayWindowState(callback) {
  function handleDisplayWindowError (line 39) | function handleDisplayWindowError(callback) {
  function loadModel (line 43) | function loadModel(modelInfo) {
  function sendToModelManager (line 47) | function sendToModelManager(message) {
  function queryDisplayWindowState (line 51) | function queryDisplayWindowState() {
  function screenshot (line 54) | function screenshot() {

FILE: src/preload/control/paths.js
  constant APP_DATA_PATH (line 5) | const APP_DATA_PATH = ipcRenderer.sendSync(

FILE: src/preload/control/theme.js
  function updateTheme (line 19) | function updateTheme(theme) {

FILE: src/preload/control/utils.js
  function detectSpineVersionFromBinary (line 1) | function detectSpineVersionFromBinary(dataToParse) {
  function readSpineVersionOldFormat (line 14) | function readSpineVersionOldFormat(dataToParse) {
  function readSpineVersionNewFormat (line 28) | function readSpineVersionNewFormat(dataToParse) {
  function isSpineValidVersion (line 42) | function isSpineValidVersion(version) {
  class SpineBinaryInput (line 46) | class SpineBinaryInput {
    method constructor (line 47) | constructor(
    method readByte (line 59) | readByte() {
    method readUnsignedByte (line 63) | readUnsignedByte() {
    method readShort (line 67) | readShort() {
    method readInt32 (line 75) | readInt32() {
    method readInt (line 83) | readInt(optimizePositive) {
    method readStringRef (line 107) | readStringRef() {
    method readString (line 113) | readString() {
    method readFloat (line 153) | readFloat() {
    method readBoolean (line 161) | readBoolean() {

FILE: src/preload/display/ipc.js
  function handleLoadModel (line 2) | function handleLoadModel(callback) {
  function queryWindowIds (line 5) | function queryWindowIds() {
  function handleUpdateWindowIds (line 8) | function handleUpdateWindowIds(callback) {
  function queryConfig (line 11) | function queryConfig() {
  function handleSendToModelManager (line 24) | function handleSendToModelManager(callback) {
  function askForMediaAccess (line 27) | function askForMediaAccess() {
  function setIgnoreMouseEvents (line 30) | function setIgnoreMouseEvents(...args) {
  function handleQueryDisplayWindowState (line 34) | function handleQueryDisplayWindowState(callback) {
  function sendModelControlInfo (line 38) | function sendModelControlInfo(modelControlInfo) {
  function sendToModelControl (line 42) | function sendToModelControl(message) {
  function sendDisplayWindowState (line 46) | function sendDisplayWindowState(state) {
  function throwError (line 50) | function throwError(message) {
  function handleScreenshot (line 54) | function handleScreenshot(callback) {

FILE: src/renderer/control/store/app.js
  method syncDatabase (line 20) | syncDatabase() {
  method syncConfig (line 35) | syncConfig() {

FILE: src/renderer/display/Application.js
  class Application (line 8) | class Application {
    method constructor (line 9) | constructor() {
    method init (line 12) | async init() {
    method initControlWindowId (line 43) | initControlWindowId() {
    method initModelManagers (line 55) | initModelManagers() {
    method handleIpcMessages (line 65) | handleIpcMessages() {
    method setBackgroundColor (line 128) | setBackgroundColor() {
    method initStats (line 134) | initStats() {
    method handleWindowResize (line 141) | handleWindowResize() {
    method resetCanvas (line 151) | resetCanvas() {
    method detectClickThrough (line 178) | detectClickThrough() {

FILE: src/renderer/display/modelManagers/Live2dManager.js
  class Live2dManager (line 9) | class Live2dManager extends ModelManager {
    method constructor (line 10) | constructor(parentApp) {
    method switchIn (line 24) | switchIn() {
    method switchOut (line 39) | switchOut() {
    method loadModel (line 59) | async loadModel(modelInfo) {
    method _initInstantConfig (line 96) | _initInstantConfig() {
    method _clearModel (line 148) | _clearModel() {
    method _updateModelTransform (line 157) | _updateModelTransform() {
    method _bindEventAnimation (line 168) | _bindEventAnimation() {
    method _startRender (line 180) | _startRender() {
    method _buildModelControlInfo (line 185) | _buildModelControlInfo(modelInfo) {
    method _render (line 239) | _render(now) {
    method handleMessage (line 280) | handleMessage(message) {
    method _bindParameter (line 334) | _bindParameter(parameterId) {
    method _setParameter (line 337) | _setParameter({ parameterId, value }) {
    method _bindPart (line 345) | _bindPart(partId) {
    method _setPart (line 348) | _setPart({ partId, value }) {
    method _loadMotion (line 353) | _loadMotion(motionInfo) {
    method _quitCapture (line 366) | _quitCapture() {
    method _addEventListeners (line 370) | _addEventListeners() {
    method _removeEventListeners (line 373) | _removeEventListeners() {
    method _loadMotionByPath (line 376) | _loadMotionByPath(motionPath) {

FILE: src/renderer/display/modelManagers/MmdManager.js
  class MmdManager (line 12) | class MmdManager extends ModelManager3D {
    method constructor (line 13) | constructor(parentApp) {
    method switchIn (line 18) | switchIn() {
    method _addLight (line 53) | _addLight() {
    method loadModel (line 70) | loadModel(modelInfo) {
    method _initInstantConfig (line 134) | _initInstantConfig() {
    method _initMouceFocusHelper (line 161) | _initMouceFocusHelper() {
    method _buildModelControlInfo (line 167) | _buildModelControlInfo(modelInfo) {
    method _updateObjects (line 196) | _updateObjects() {
    method handleMessage (line 229) | handleMessage(message) {
    method _setMorphWeight (line 341) | _setMorphWeight({ morphName, weight }) {
    method _resetAnimationManager (line 350) | _resetAnimationManager() {

FILE: src/renderer/display/modelManagers/ModelManager.js
  class ModelManager (line 2) | class ModelManager {
    method constructor (line 3) | constructor(parentApp) {
    method onSendToModelControl (line 9) | onSendToModelControl(callback) {

FILE: src/renderer/display/modelManagers/ModelManager3D.js
  class ModelManager3D (line 5) | class ModelManager3D extends ModelManager {
    method _initOrbitControls (line 6) | _initOrbitControls() {
    method switchOut (line 15) | switchOut() {
    method _initObjects (line 25) | _initObjects() {
    method _bindNodeTransform (line 48) | _bindNodeTransform(nodeId) {
    method _setNodeTransform (line 51) | _setNodeTransform({ nodeId, transform }) {
    method _render (line 63) | _render() {
    method _clearModel (line 71) | _clearModel() {
    method _quitCapture (line 91) | _quitCapture() {
    method _disposeChildren (line 95) | _disposeChildren(parent) {
    method _addEventListeners (line 117) | _addEventListeners() {
    method _removeEventListeners (line 120) | _removeEventListeners() {
    method onWindowResize (line 124) | onWindowResize() {

FILE: src/renderer/display/modelManagers/SpineManager.js
  class SpineManager (line 6) | class SpineManager extends ModelManager {
    method constructor (line 7) | constructor(parentApp) {
    method getApplicationConfig (line 17) | getApplicationConfig() {
    method switchIn (line 31) | switchIn() {
    method switchOut (line 34) | switchOut() {
    method loadModel (line 50) | loadModel(modelInfo) {
    method _setupModel (line 77) | _setupModel() {
    method _initInstantConfig (line 103) | _initInstantConfig() {
    method _clearModel (line 109) | _clearModel() {
    method _updateModelTransform (line 115) | _updateModelTransform() {
    method _bindEventAnimation (line 126) | _bindEventAnimation() {
    method _startRender (line 146) | _startRender() {
    method _buildModelControlInfo (line 150) | _buildModelControlInfo(modelInfo) {
    method _render (line 192) | _render() {
    method handleMessage (line 206) | handleMessage(message) {
    method _loadMotionByPath (line 244) | _loadMotionByPath(motionPath, loop) {

FILE: src/renderer/display/modelManagers/SpineManager42.js
  class SpineManager42 (line 4) | class SpineManager42 extends SpineManager {
    method constructor (line 5) | constructor(parentApp) {
    method switchIn (line 10) | switchIn() {
    method switchOut (line 17) | switchOut() {
    method loadModel (line 35) | loadModel(modelInfo) {
    method _clearModel (line 66) | _clearModel() {

FILE: src/renderer/display/modelManagers/VroidManager.js
  class VroidManager (line 21) | class VroidManager extends ModelManager3D {
    method constructor (line 22) | constructor(parentApp) {
    method switchIn (line 26) | switchIn() {
    method _addLight (line 59) | _addLight() {
    method loadModel (line 64) | loadModel(modelInfo) {
    method _initInstantConfig (line 94) | _initInstantConfig() {
    method _initMouceFocusHelper (line 111) | _initMouceFocusHelper() {
    method _buildModelControlInfo (line 118) | _buildModelControlInfo(modelInfo) {
    method _updateObjects (line 140) | _updateObjects() {
    method handleMessage (line 176) | handleMessage(message) {
    method _setMorphWeight (line 218) | _setMorphWeight({ morphName, weight }) {

FILE: src/renderer/display/utils/2d/utils.js
  function setModelBaseTransfrom (line 1) | function setModelBaseTransfrom(model, displayConfig, type) {
  function draggable (line 22) | function draggable(model) {

FILE: src/renderer/display/utils/3d/AudioManager.js
  class AudioManager (line 2) | class AudioManager {
    method constructor (line 3) | constructor(audio, params) {
    method destroy (line 12) | destroy() {
    method play (line 16) | play() {
    method pause (line 26) | pause() {
    method getCurrentTime (line 30) | getCurrentTime() {}
    method setCurrentTime (line 31) | setCurrentTime(time) {}

FILE: src/renderer/display/utils/3d/Monitor.js
  class TransformMonitor (line 1) | class TransformMonitor {
    method constructor (line 2) | constructor() {
    method bind (line 6) | bind(target) {
    method checkUpdate (line 17) | checkUpdate() {

FILE: src/renderer/display/utils/3d/MouseFocusHelper.js
  class MouseFocusHelper (line 12) | class MouseFocusHelper {
    method constructor (line 13) | constructor(object, camera, ratio = 0.6) {
    method update (line 24) | update(x, y) {
    method focus (line 48) | focus() {

FILE: src/renderer/display/utils/3d/NodeInfo.js
  function buildNodeInfoTree (line 1) | function buildNodeInfoTree(node, tree = {}) {
  function buildNodeInfoTreeAndList (line 20) | function buildNodeInfoTreeAndList(node, tree = {}, list = []) {

FILE: src/renderer/display/utils/animation/Mixamo2MMDAnimationConverter.js
  function convertAnimation (line 159) | function convertAnimation(
  function convertAnimationWithIK (line 245) | function convertAnimationWithIK(
  function getMatrixSomeTime (line 342) | function getMatrixSomeTime(object, time, matrix) {
  function addAnimationTrakInfoToNode (line 371) | function addAnimationTrakInfoToNode(node, animationClip) {

FILE: src/renderer/display/utils/animation/Mixamo2MMDAnimationConverterNew.js
  function counteractRotation (line 153) | function counteractRotation(targetBone, track, direction) {
  function convertAnimation (line 173) | function convertAnimation(
  function convertAnimationWithIK (line 339) | function convertAnimationWithIK(
  function getMatrixSomeTime (line 447) | function getMatrixSomeTime(object, time, matrix) {
  function addAnimationTrakInfoToNode (line 476) | function addAnimationTrakInfoToNode(node, animationClip) {

FILE: src/renderer/display/utils/animation/utils.js
  function createClearPositionTrack (line 17) | function createClearPositionTrack(childNode, parentNode) {
  function buildNodeStack (line 45) | function buildNodeStack(rootNode, mode = "dfs") {
  function trackRotateQuaternion (line 90) | function trackRotateQuaternion(quaternionList, eulerAngle, invert = fals...
  function trackPreRotateQuaternion (line 107) | function trackPreRotateQuaternion(quaternionList, eulerAngle, invert = f...
  function trackRotateQuaternionAxis (line 132) | function trackRotateQuaternionAxis(quaternionList, eulerAngle) {
  function trackRevertXZ (line 145) | function trackRevertXZ(quaternionList) {
  function getRelativeMatrix (line 161) | function getRelativeMatrix(node, targetParentName) {
  function getBaseCenterHeight (line 176) | function getBaseCenterHeight(obj, type) {

FILE: src/renderer/display/utils/capture/FaceMeshCaptureManager.js
  class FaceMeshCaptureManager (line 18) | class FaceMeshCaptureManager {
    method constructor (line 19) | constructor() {
    method start (line 25) | async start() {
    method quitCapture (line 59) | async quitCapture() {
    method drawResults (line 69) | drawResults(results) {
    method animateModel (line 92) | animateModel(results) {
    method onRiggedFace (line 107) | onRiggedFace(callback) {

FILE: src/renderer/display/utils/capture/HolisticCaptureManager.js
  class HolisticCaptureManager (line 17) | class HolisticCaptureManager {
    method constructor (line 18) | constructor() {
    method start (line 23) | async start() {
    method quitCapture (line 57) | async quitCapture() {
    method drawResults (line 67) | drawResults(results) {
    method animateModel (line 133) | animateModel(results) {
    method onRiggedHolistic (line 170) | onRiggedHolistic(callback) {

FILE: src/renderer/display/utils/capture/Live2DFaceMeshCaptureManager.js
  class Live2DFaceMeshCaptureManager (line 4) | class Live2DFaceMeshCaptureManager extends FaceMeshCaptureManager {
    method rigFace (line 5) | rigFace(riggedFace, lerpRatio = 0.5) {

FILE: src/renderer/display/utils/capture/MMDFaceMeshCaptureManager.js
  class MMDFaceMeshCaptureManager (line 10) | class MMDFaceMeshCaptureManager extends FaceMeshCaptureManager {
    method constructor (line 11) | constructor() {
    method readyToRig (line 15) | readyToRig() {
    method rigHead (line 22) | rigHead(rotation, lerpRatio, bodyLinkRatio = 0.2) {

FILE: src/renderer/display/utils/capture/MMDHolisticCaptureManager.js
  class MMDHolisticCaptureManager (line 56) | class MMDHolisticCaptureManager extends HolisticCaptureManager {
    method constructor (line 57) | constructor() {
    method readyToRig (line 61) | readyToRig() {
    method rigHead (line 65) | rigHead(rotation, lerpRatio) {
    method rigPose (line 68) | rigPose(riggedPose, lerpRatio = 0.5) {
    method rigLeftHand (line 93) | rigLeftHand(riggedLeftHand, lerpRatio = 0.5) {
    method rigRightHand (line 102) | rigRightHand(riggedRightHand, lerpRatio = 0.5) {

FILE: src/renderer/display/utils/capture/VRoidFaceMeshCaptureManager.js
  class VRoidFaceMeshCaptureManager (line 8) | class VRoidFaceMeshCaptureManager extends FaceMeshCaptureManager {
    method constructor (line 9) | constructor() {
    method readyToRig (line 13) | readyToRig() {
    method rigHead (line 20) | rigHead(rotation, lerpRatio, bodyLinkRatio = 0.2) {

FILE: src/renderer/display/utils/capture/VRoidHolisticCaptureManager.js
  class VRoidHolisticCaptureManager (line 70) | class VRoidHolisticCaptureManager extends HolisticCaptureManager {
    method constructor (line 71) | constructor() {
    method readyToRig (line 74) | readyToRig() {
    method rigHead (line 78) | rigHead(rotation, lerpRatio) {
    method rigPose (line 83) | rigPose(riggedPose, lerpRatio = 0.5) {
    method rigLeftHand (line 106) | rigLeftHand(riggedLeftHand, lerpRatio = 0.5) {
    method rigRightHand (line 117) | rigRightHand(riggedRightHand, lerpRatio = 0.5) {

FILE: src/renderer/display/utils/capture/parents/parents.js
  function setTarget (line 2) | function setTarget(target) {
  function createVideo (line 5) | function createVideo() {
  function onResults (line 17) | function onResults(results) {
  function askForMediaAccess (line 21) | function askForMediaAccess() {

FILE: src/renderer/display/utils/capture/rig/3DRig.js
  function lerpBoneRotationByBone (line 3) | function lerpBoneRotationByBone(bone, rotation, lerpRatio, dampener = 1) {
  function lerpBonePositionByBone (line 10) | function lerpBonePositionByBone(bone, position, lerpRatio, dampener = 1) {

FILE: src/renderer/display/utils/capture/rig/MMDRig.js
  function rigFace (line 3) | function rigFace(riggedFace, lerpRatio = 0.5) {
  function lerpMorphTargetByName (line 38) | function lerpMorphTargetByName(name, value, lerpRatio) {
  function getBoneNode (line 53) | function getBoneNode(boneName) {

FILE: src/renderer/display/utils/capture/rig/VRoidRig.js
  function rigFace (line 3) | function rigFace(riggedFace, lerpRatio = 0.5) {
  function lerpMorphTargetByName (line 29) | function lerpMorphTargetByName(name, value, lerpRatio) {
  function getBoneNode (line 35) | function getBoneNode(boneName) {

FILE: src/renderer/display/utils/common.js
  function getCurrentDateString (line 1) | function getCurrentDateString() {

FILE: src/renderer/display/utils/live2d/Cubism2Shim.js
  constant LIVE2D_VERSION (line 1) | const LIVE2D_VERSION = {
  constant C2C (line 54) | const C2C = Cubism2ConfusionDict;
  function camelToUpperSnake (line 55) | function camelToUpperSnake(str) {
  function AddCubism2Shim (line 61) | function AddCubism2Shim(coreModel) {

FILE: src/renderer/display/utils/live2d/Monitor.js
  class ParameterMonitor (line 2) | class ParameterMonitor {
    method constructor (line 3) | constructor() {
    method bind (line 8) | bind(target, model = null) {
    method checkUpdate (line 27) | checkUpdate() {
    method clear (line 46) | clear() {
  class PartMonitor (line 52) | class PartMonitor {
    method constructor (line 53) | constructor() {
    method bind (line 58) | bind(target, model = null) {
    method checkUpdate (line 72) | checkUpdate() {
    method clear (line 91) | clear() {

FILE: src/renderer/display/utils/mmd/AnimationManager.js
  class AnimationManager (line 10) | class AnimationManager {
    method constructor (line 12) | constructor(MMDLoader, mixamoLegTranslateMode = "ik") {
    method destroy (line 31) | destroy() {
    method _MMDLoadAnimation (line 47) | _MMDLoadAnimation(model, motionFilePath) {
    method _initAnimation (line 98) | _initAnimation(animation, useIK = true) {
    method _MMDLoadAudio (line 111) | _MMDLoadAudio(audioFilePath, delayTime) {
    method loadAnimation (line 132) | async loadAnimation(model, motionFilePath) {
    method loadAnimationWithAudio (line 137) | async loadAnimationWithAudio(
    method update (line 153) | update() {
    method pose (line 168) | pose() {
    method play (line 171) | play() {
    method pause (line 175) | pause() {
    method setLoop (line 179) | setLoop(loop) {
    method setTime (line 189) | setTime() {
    method updateIK (line 197) | updateIK() {
    method fixPhysics (line 202) | fixPhysics() {

FILE: src/renderer/display/utils/mmd/Monitor.js
  class MorphMonitor (line 1) | class MorphMonitor {
    method constructor (line 2) | constructor() {
    method bind (line 7) | bind(target, model = null) {
    method checkUpdate (line 20) | checkUpdate() {

FILE: src/renderer/display/utils/record/RecordManager.js
  class RecordManager (line 6) | class RecordManager {
    method constructor (line 7) | constructor(app) {
    method takeScreenshot (line 10) | takeScreenshot() {
    method getFileName (line 17) | getFileName() {
    method saveFile (line 20) | saveFile(blob, name) {

FILE: src/renderer/display/utils/spine/premultipliedImageLoader.js
  function imageLoaderAdapter (line 2) | function imageLoaderAdapter(

FILE: src/renderer/display/utils/vroid/Monitor.js
  class MorphMonitor (line 2) | class MorphMonitor {
    method constructor (line 3) | constructor() {
    method bind (line 8) | bind(target, model = null) {
    method checkUpdate (line 19) | checkUpdate() {

FILE: src/renderer/public/lib/@mediapipe/cdn/camera_utils.js
  function n (line 6) | function n(a){var b=0;return function(){return b<a.length?{done:!1,value...
  function t (line 7) | function t(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typ...
  function v (line 7) | function v(a,b){if(b)a:{var e=u;a=a.split(".");for(var f=0;f<a.length-1;...
  function b (line 8) | function b(l){if(this instanceof b)throw new TypeError("Symbol is not a ...
  function e (line 8) | function e(l,c){this.g=l;q(this,"description",{configurable:!0,writable:...
  function w (line 9) | function w(a){a={next:a};a[Symbol.iterator]=function(){return this};retu...
  function x (line 10) | function x(a){var b="undefined"!=typeof Symbol&&Symbol.iterator&&a[Symbo...
  function y (line 10) | function y(){this.i=!1;this.g=null;this.o=void 0;this.j=1;this.m=0;this....
  function z (line 10) | function z(a){if(a.i)throw new TypeError("Generator is already running")...
  function A (line 10) | function A(a,b){a.h={F:b,G:!0};a.j=a.m}
  function B (line 10) | function B(a){this.g=new y;this.h=a}
  function C (line 11) | function C(a,b){z(a.g);var e=a.g.g;if(e)return D(a,"return"in e?e["retur...
  function D (line 11) | function D(a,b,e,f){try{var h=b.call(a.g.g,e);if(!(h instanceof Object))...
  function H (line 12) | function H(a){for(;a.g.j;)try{var b=a.h(a.g);if(b)return a.g.i=!1,{value...
  function I (line 13) | function I(a){this.next=function(b){z(a.g);a.g.g?b=D(a,a.g.g.next,b,a.g....
  function J (line 13) | function J(a){function b(f){return a.next(f)}function e(f){return a.thro...
  function b (line 14) | function b(c){this.h=0;this.i=void 0;this.g=[];this.o=!1;var d=this.j();...
  function e (line 14) | function e(){this.g=null}
  function f (line 14) | function f(c){return c instanceof b?c:new b(function(d){d(c)})}
  function c (line 15) | function c(k){return function(m){g||(g=!0,k.call(d,m))}}
  function g (line 18) | function g(p,r){return"function"==typeof p?function(E){try{k(p(E))}catch...
  function g (line 18) | function g(){switch(k.h){case 1:c(k.i);break;case 2:d(k.i);break;default...
  function G (line 19) | function G(E){return function(F){p[E]=F;r--;0==r&&k(p)}}
  function N (line 20) | function N(a,b){this.video=a;this.i=0;this.h=Object.assign(Object.assign...
  function P (line 22) | function P(a){window.requestAnimationFrame(function(){Q(a)})}
  function O (line 22) | function O(a,b){a.g=b;a.video.srcObject=b;a.video.onloadedmetadata=funct...
  function Q (line 22) | function Q(a){var b=null;a.video.paused||a.video.currentTime===a.i||(a.i...

FILE: src/renderer/public/lib/@mediapipe/cdn/drawing_utils.js
  function h (line 6) | function h(a){var c=0;return function(){return c<a.length?{done:!1,value...
  function m (line 7) | function m(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typ...
  function p (line 7) | function p(a,c){if(c)a:{var b=n;a=a.split(".");for(var d=0;d<a.length-1;...
  function q (line 8) | function q(a){var c="undefined"!=typeof Symbol&&Symbol.iterator&&a[Symbo...
  function t (line 9) | function t(a){return a?a:Array.prototype.fill}
  function v (line 10) | function v(a,c){a=a.split(".");var b=u;a[0]in b||"undefined"==typeof b.e...
  function x (line 10) | function x(a){a=a||{};return Object.assign(Object.assign(Object.assign({...
  function y (line 10) | function y(a,c){return a instanceof Function?a(c):a}
  function z (line 10) | function z(a,c,b){return Math.max(Math.min(c,b),Math.min(Math.max(c,b),a))}

FILE: src/renderer/public/lib/@mediapipe/cdn/face_mesh.js
  function aa (line 6) | function aa(a){var b=0;return function(){return b<a.length?{done:!1,valu...
  function ca (line 7) | function ca(a){a=["object"==typeof globalThis&&globalThis,a,"object"==ty...
  function J (line 7) | function J(a,b){if(b)a:{var c=G;a=a.split(".");for(var d=0;d<a.length-1;...
  function b (line 8) | function b(g){if(this instanceof b)throw new TypeError("Symbol is not a ...
  function c (line 8) | function c(g,f){this.g=g;ba(this,"description",{configurable:!0,writable...
  function da (line 9) | function da(a){a={next:a};a[Symbol.iterator]=function(){return this};ret...
  function K (line 10) | function K(a){var b="undefined"!=typeof Symbol&&Symbol.iterator&&a[Symbo...
  function L (line 10) | function L(a){if(!(a instanceof Array)){a=K(a);for(var b,c=[];!(b=a.next...
  function b (line 10) | function b(){}
  function M (line 12) | function M(a,b){a.prototype=ea(b.prototype);a.prototype.constructor=a;if...
  function ma (line 12) | function ma(){this.l=!1;this.i=null;this.h=void 0;this.g=1;this.s=this.m...
  function na (line 12) | function na(a){if(a.l)throw new TypeError("Generator is already running"...
  function oa (line 13) | function oa(a,b){a.j={U:b,V:!0};a.g=a.m||a.s}
  function N (line 13) | function N(a,b,c){a.g=c;return{value:b}}
  function pa (line 13) | function pa(a){this.g=new ma;this.h=a}
  function qa (line 13) | function qa(a,b){na(a.g);var c=a.g.i;if(c)return ra(a,"return"in c?c["re...
  function ra (line 14) | function ra(a,b,c,d){try{var e=b.call(a.g.i,c);if(!(e instanceof Object)...
  function sa (line 14) | function sa(a){for(;a.g.g;)try{var b=a.h(a.g);if(b)return a.g.l=!1,{valu...
  function ta (line 15) | function ta(a){this.next=function(b){na(a.g);a.g.i?b=ra(a,a.g.i.next,b,a...
  function O (line 15) | function O(a,b){b=new ta(new pa(b));ka&&a.prototype&&ka(b,a.prototype);r...
  function ua (line 16) | function ua(a,b){a instanceof String&&(a+="");var c=0,d=!1,e={next:funct...
  function b (line 17) | function b(f){this.h=0;this.i=void 0;this.g=[];this.o=!1;var h=this.j();...
  function c (line 17) | function c(){this.g=null}
  function d (line 17) | function d(f){return f instanceof b?f:new b(function(h){h(f)})}
  function f (line 18) | function f(l){return function(n){k||(k=!0,l.call(h,n))}}
  function k (line 21) | function k(w,r){return"function"==typeof w?function(y){try{l(w(y))}catch...
  function k (line 21) | function k(){switch(l.h){case 1:f(l.i);break;case 2:h(l.i);break;default...
  function u (line 22) | function u(y){return function(m){w[y]=m;r--;0==r&&l(w)}}
  function P (line 25) | function P(a,b){a=a.split(".");var c=wa;a[0]in c||"undefined"==typeof c....
  function xa (line 25) | function xa(a,b){b=String.fromCharCode.apply(null,b);return null==a?b:a+b}
  function Ca (line 26) | function Ca(a){if(Ba)a=(Aa||(Aa=new TextEncoder)).encode(a);else{var b=v...
  function Fa (line 27) | function Fa(a,b){void 0===b&&(b=0);Ga();b=Da[b];for(var c=Array(Math.flo...
  function Ha (line 28) | function Ha(a){var b=a.length,c=3*b/4;c%3?c=Math.floor(c):-1!="=.".index...
  function Ia (line 29) | function Ia(a,b){function c(k){for(;d<a.length;){var l=a.charAt(d++),n=E...
  function Ga (line 30) | function Ga(){if(!Ea){Ea={};for(var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg...
  function La (line 30) | function La(a,b,c){return b===c?Ka||(Ka=new Uint8Array(0)):Ja?a.slice(b,...
  function Ma (line 30) | function Ma(a,b){b=void 0===b?{}:b;b=void 0===b.v?!1:b.v;this.h=null;thi...
  function Na (line 30) | function Na(a,b){b=b.constructor===Uint8Array?b:b.constructor===ArrayBuf...
  function Oa (line 31) | function Oa(a){for(var b=128,c=0,d=0,e=0;4>e&&128<=b;e++)b=a.h[a.g++],c|...
  function Qa (line 33) | function Qa(){this.g=new Uint8Array(64);this.h=0}
  function Ra (line 33) | function Ra(a,b){for(;127<b;)a.push(b&127|128),b>>>=7;a.push(b)}
  function Sa (line 33) | function Sa(a){var b={},c=void 0===b.N?!1:b.N;this.o={v:void 0===b.v?!1:...
  function S (line 33) | function S(a){var b=a.g;(b=b.g==b.j)||(b=a.j)||(b=a.g,b=b.m||0>b.g||b.g>...
  function Ta (line 34) | function Ta(a){switch(a.h){case 0:if(0!=a.h)Ta(a);else{for(a=a.g;a.h[a.g...
  function Ua (line 35) | function Ua(a,b,c){var d=a.g.j,e=a.g.i(),g=a.g.g+e;a.g.j=g;c(b,a);c=g-a....
  function T (line 35) | function T(a){return a.g.o()}
  function Va (line 36) | function Va(a){var b=a.g.i();a=a.g;var c=a.g;a.g+=b;a=a.h;var d;if(za)(d...
  function Wa (line 37) | function Wa(a,b,c){var d=a.g.i();for(d=a.g.g+d;a.g.g<d;)c.push(b.call(a....
  function Xa (line 37) | function Xa(a,b){2==a.h?Wa(a,Ma.prototype.o,b):b.push(T(a))}
  function Ya (line 37) | function Ya(){this.h=[];this.i=0;this.g=new Qa}
  function Za (line 37) | function Za(a,b){0!==b.length&&(a.h.push(b),a.i+=b.length)}
  function $a (line 37) | function $a(a){var b=a.i+a.g.length();if(0===b)return new Uint8Array(0);...
  function U (line 38) | function U(a,b,c){if(null!=c){Ra(a.g,8*b+5);a=a.g;var d=c;d=(c=0>d?1:0)?...
  function bb (line 38) | function bb(a,b,c){if(null!=a)return"object"===typeof a?ab&&a instanceof...
  function cb (line 38) | function cb(a,b,c){if(Array.isArray(a)){for(var d=Array(a.length),e=0;e<...
  function eb (line 38) | function eb(a){return"number"===typeof a?isFinite(a)?a:String(a):a}
  function db (line 39) | function db(a){Array.isArray(a)&&!Object.isFrozen(a)&&Object.definePrope...
  function V (line 39) | function V(a,b,c){var d=gb;gb=null;a||(a=d);d=this.constructor.ca;a||(a=...
  function ib (line 40) | function ib(a){var b=a.l+a.j;a.h[b]||(a.i=a.h[b]={})}
  function W (line 40) | function W(a,b,c){return-1===b?null:(void 0===c?0:c)||b>=a.l?a.i?a.i[b]:...
  function jb (line 40) | function jb(a,b){var c=void 0===c?!1:c;var d=W(a,b,c);null==d&&(d=hb);d=...
  function kb (line 40) | function kb(a){var b=jb(a,3);a.m||(a.m={});if(!a.m[3]){for(var c=0;c<b.l...
  function lb (line 40) | function lb(a,b,c){a=W(a,b);return null==a?c:a}
  function Y (line 41) | function Y(a,b,c){a=W(a,b);a=null==a?a:+a;return null==a?void 0===c?0:c:a}
  function X (line 41) | function X(a,b,c,d){(void 0===d?0:d)||b>=a.l?(ib(a),a.i[b]=c):a.h[b+a.j]=c}
  function mb (line 41) | function mb(a,b,c){if(-1===c)return null;a.g||(a.g={});if(!a.g[c]){var d...
  function nb (line 41) | function nb(a,b){a.g||(a.g={});var c=a.g[1];if(!c){var d=jb(a,1);c=[];fo...
  function ob (line 41) | function ob(a,b,c){var d=void 0===d?!1:d;a.g||(a.g={});var e=c?pb(c,!1):...
  function qb (line 42) | function qb(a,b,c,d){var e=nb(a,c);b=b?b:new c;a=jb(a,1);void 0!=d?(e.sp...
  function pb (line 42) | function pb(a,b){if(a.g)for(var c in a.g){var d=a.g[c];if(Array.isArray(...
  function rb (line 42) | function rb(a,b){if(a=a.o){Za(b,b.g.end());for(var c=0;c<a.length;c++)Za...
  function sb (line 42) | function sb(a,b){if(4==b.h)return!1;var c=b.m;Ta(b);b.N||(b=La(b.g.h,c,b...
  function tb (line 42) | function tb(a){V.call(this,a,-1,ub)}
  function vb (line 42) | function vb(a,b){for(;S(b);)switch(b.i){case 8:var c=b.g.i();X(a,1,c);br...
  function Z (line 42) | function Z(a,b){var c=void 0;return new (c||(c=Promise))(function(d,e){f...
  function wb (line 42) | function wb(a){V.call(this,a)}
  function xb (line 42) | function xb(a,b){for(;S(b);)switch(b.i){case 8:var c=b.g.i();X(a,1,c);br...
  function yb (line 42) | function yb(a){V.call(this,a,-1,zb)}
  function Ab (line 42) | function Ab(a){V.call(this,a)}
  function Bb (line 42) | function Bb(a,b){for(;S(b);)switch(b.i){case 13:var c=T(b);X(a,1,c);brea...
  function Cb (line 42) | function Cb(a){V.call(this,a,-1,Db)}
  function Eb (line 42) | function Eb(a){a:{var b=new Cb;for(a=new Sa(a);S(a);)switch(a.i){case 10...
  function Fb (line 42) | function Fb(a){V.call(this,a)}
  function Gb (line 42) | function Gb(a){V.call(this,a,-1,Hb)}
  function Ib (line 43) | function Ib(a,b){for(;S(b);)switch(b.i){case 8:var c=Oa(b.g);X(a,1,c);br...
  function Jb (line 43) | function Jb(a){V.call(this,a)}
  function Kb (line 43) | function Kb(a){a:{var b=new Jb;for(a=new Sa(a);S(a);)switch(a.i){case 10...
  function Lb (line 43) | function Lb(a,b,c){c=a.createShader(0===c?a.VERTEX_SHADER:a.FRAGMENT_SHA...
  function Mb (line 43) | function Mb(a){return nb(a,wb).map(function(b){return{index:lb(b,1,0),Y:...
  function Nb (line 43) | function Nb(a){return{x:Y(a,1),y:Y(a,2),z:Y(a,3),visibility:null!=W(a,4)...
  function Ob (line 43) | function Ob(a,b){this.h=a;this.g=b;this.l=0}
  function Pb (line 44) | function Pb(a,b,c){Qb(a,b);if("function"===typeof a.g.canvas.transferToI...
  function Qb (line 45) | function Qb(a,b){var c=a.g;if(void 0===a.m){var d=Lb(c,"\n  attribute ve...
  function Rb (line 48) | function Rb(a){this.g=a}
  function Tb (line 48) | function Tb(a,b){return b+a}
  function Ub (line 48) | function Ub(a,b){window[a]=b}
  function Vb (line 48) | function Vb(a){var b=document.createElement("script");b.setAttribute("sr...
  function Wb (line 49) | function Wb(){return Z(this,function b(){return O(b,function(c){switch(c...
  function Xb (line 50) | function Xb(a){this.g=a;this.listeners={};this.j={};this.F={};this.m={};...
  function Yb (line 51) | function Yb(a,b){return void 0===a.g.files?[]:"function"===typeof a.g.fi...
  function Zb (line 52) | function Zb(a){return Z(a,function c(){var d=this,e,g,f,h,k,l,n,u,w,r,y;...
  function ac (line 56) | function ac(a){return Z(a,function c(){var d=this,e,g,f,h,k,l,n,u;return...
  function cc (line 60) | function cc(a){return Z(a,function c(){var d=this,e,g,f,h,k,l,n;return O...
  function $b (line 61) | function $b(a,b){return Z(a,function d(){var e=this,g,f;return O(d,funct...
  function dc (line 68) | function dc(a,b,c){return Z(a,function e(){var g,f,h,k,l,n,u=this,w,r,y,...
  function ec (line 72) | function ec(a,b,c){return Z(a,function e(){var g=this,f;return O(e,funct...
  function bc (line 73) | function bc(a,b){for(var c=b.name||"$",d=[].concat(L(b.wants)),e=new a.h...
  function fc (line 74) | function fc(a){a=Kb(a);var b=a.getMesh();if(!b)return a;var c=new Float3...
  function oc (line 80) | function oc(a){a=a||{};a=Object.assign(Object.assign({},gc),a);this.g=ne...

FILE: src/renderer/public/lib/@mediapipe/cdn/holistic.js
  function aa (line 6) | function aa(a){var b=0;return function(){return b<a.length?{done:!1,valu...
  function ca (line 7) | function ca(a){a=["object"==typeof globalThis&&globalThis,a,"object"==ty...
  function z (line 7) | function z(a,b){if(b)a:{var c=y;a=a.split(".");for(var d=0;d<a.length-1;...
  function b (line 8) | function b(g){if(this instanceof b)throw new TypeError("Symbol is not a ...
  function c (line 8) | function c(g,f){this.g=g;ba(this,"description",{configurable:!0,writable...
  function da (line 9) | function da(a){a={next:a};a[Symbol.iterator]=function(){return this};ret...
  function B (line 10) | function B(a){var b="undefined"!=typeof Symbol&&Symbol.iterator&&a[Symbo...
  function D (line 10) | function D(a){if(!(a instanceof Array)){a=B(a);for(var b,c=[];!(b=a.next...
  function b (line 10) | function b(){}
  function E (line 12) | function E(a,b){a.prototype=ea(b.prototype);a.prototype.constructor=a;if...
  function la (line 12) | function la(){this.l=!1;this.i=null;this.h=void 0;this.g=1;this.s=this.m...
  function ma (line 12) | function ma(a){if(a.l)throw new TypeError("Generator is already running"...
  function na (line 13) | function na(a,b){a.j={U:b,V:!0};a.g=a.m||a.s}
  function F (line 13) | function F(a,b,c){a.g=c;return{value:b}}
  function oa (line 13) | function oa(a){this.g=new la;this.h=a}
  function pa (line 13) | function pa(a,b){ma(a.g);var c=a.g.i;if(c)return qa(a,"return"in c?c["re...
  function qa (line 14) | function qa(a,b,c,d){try{var e=b.call(a.g.i,c);if(!(e instanceof Object)...
  function ra (line 14) | function ra(a){for(;a.g.g;)try{var b=a.h(a.g);if(b)return a.g.l=!1,{valu...
  function sa (line 15) | function sa(a){this.next=function(b){ma(a.g);a.g.i?b=qa(a,a.g.i.next,b,a...
  function ta (line 15) | function ta(a){function b(d){return a.next(d)}function c(d){return a.thr...
  function H (line 16) | function H(a){return ta(new sa(new oa(a)))}
  function b (line 17) | function b(f){this.h=0;this.i=void 0;this.g=[];this.o=!1;var k=this.j();...
  function c (line 17) | function c(){this.g=null}
  function d (line 17) | function d(f){return f instanceof b?f:new b(function(k){k(f)})}
  function f (line 18) | function f(l){return function(n){h||(h=!0,l.call(k,n))}}
  function h (line 21) | function h(p,m){return"function"==typeof p?function(q){try{l(p(q))}catch...
  function h (line 21) | function h(){switch(l.h){case 1:f(l.i);break;case 2:k(l.i);break;default...
  function r (line 22) | function r(q){return function(t){p[q]=t;m--;0==m&&l(p)}}
  function ua (line 23) | function ua(a,b){a instanceof String&&(a+="");var c=0,d=!1,e={next:funct...
  function I (line 26) | function I(a,b){a=a.split(".");var c=wa;a[0]in c||"undefined"==typeof c....
  function xa (line 26) | function xa(a){wa.setTimeout(function(){throw a;},0)}
  function ya (line 26) | function ya(a){xa(a);return;throw Error("invalid error level: 1");}
  function za (line 26) | function za(a,b){ya(Error("Invalid wire type: "+a+" (at position "+b+")"))}
  function Aa (line 26) | function Aa(){ya(Error("Failed to read varint, encoding is invalid."))}
  function Ba (line 26) | function Ba(a,b){b=String.fromCharCode.apply(null,b);return null==a?b:a+b}
  function Ga (line 27) | function Ga(a){if(Fa)a=(Ea||(Ea=new TextEncoder)).encode(a);else{var b=v...
  function Ja (line 28) | function Ja(a){var b;void 0===b&&(b=0);Ka();b=Ha[b];for(var c=Array(Math...
  function La (line 29) | function La(a){var b=a.length,c=3*b/4;c%3?c=Math.floor(c):-1!="=.".index...
  function Ma (line 30) | function Ma(a,b){function c(h){for(;d<a.length;){var l=a.charAt(d++),n=I...
  function Ka (line 31) | function Ka(){if(!Ia){Ia={};for(var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg...
  function Pa (line 31) | function Pa(a){this.g=a;if(null!==a&&0===a.length)throw Error("ByteStrin...
  function Ra (line 31) | function Ra(a,b,c){return b===c?Oa||(Oa=new Uint8Array(0)):Qa?a.slice(b,...
  function Sa (line 32) | function Sa(a){if(a.constructor===Uint8Array)return a;if(a.constructor==...
  function Ta (line 33) | function Ta(a,b){b=void 0===b?{}:b;b=void 0===b.u?!1:b.u;this.h=null;thi...
  function Ua (line 33) | function Ua(a,b){a.h=Sa(b);a.m=0;a.i=a.h.length;a.g=a.m}
  function Va (line 34) | function Va(a){for(var b=128,c=0,d=0,e=0;4>e&&128<=b;e++)b=a.h[a.g++],c|...
  function M (line 34) | function M(a){a.g>a.i&&(a.l=!0,ya(Error("Tried to read past the end of t...
  function Xa (line 36) | function Xa(){this.g=new Uint8Array(64);this.h=0}
  function N (line 36) | function N(a,b){if(!(a.h+1<a.g.length)){var c=a.g;a.g=new Uint8Array(Mat...
  function Ya (line 36) | function Ya(a,b){for(;127<b;)N(a,b&127|128),b>>>=7;N(a,b)}
  function Za (line 36) | function Za(a){var b={},c=void 0===b.N?!1:b.N;this.m={u:void 0===b.u?!1:...
  function $a (line 36) | function $a(a){var b=a.g;(b=b.g==b.i)||(b=a.j)||(b=a.g,b=b.l||0>b.g||b.g...
  function ab (line 37) | function ab(a){switch(a.h){case 0:if(0!=a.h)ab(a);else a:{a=a.g;for(var ...
  function bb (line 38) | function bb(a,b,c){a.N||(a=Ra(a.g.h,c,a.g.g),(c=b.o)?c.push(a):b.o=[a])}
  function cb (line 38) | function cb(a,b,c){var d=a.g.i,e=a.g.j(),g=a.g.g+e;a.g.i=g;c(b,a);c=g-a....
  function db (line 38) | function db(a,b,c){var d=a.g.j();for(d=a.g.g+d;a.g.g<d;)c.push(b.call(a....
  function fb (line 38) | function fb(){this.h=[];this.i=0;this.g=new Xa}
  function gb (line 38) | function gb(a,b){0!==b.length&&(a.h.push(b),a.i+=b.length)}
  function hb (line 38) | function hb(a,b,c){Ya(a.g,8*b+2);Ya(a.g,c.length);gb(a,a.g.end());gb(a,c)}
  function jb (line 38) | function jb(a,b){Object.isFrozen(a)||(ib?a[ib]|=b:void 0!==a.g?a.g|=b:Ob...
  function kb (line 38) | function kb(a){if(!a)return 0;var b;ib?b=a[ib]:b=a.g;return null==b?0:b}
  function lb (line 38) | function lb(a){if(!Array.isArray(a))return a;jb(a,1);return a}
  function mb (line 38) | function mb(a){if(!Array.isArray(a))throw Error("cannot mark non-array a...
  function nb (line 38) | function nb(a){return null!==a&&"object"===typeof a&&a.constructor===Obj...
  function ob (line 38) | function ob(a){switch(typeof a){case "number":return isFinite(a)?a:Strin...
  function pb (line 38) | function pb(a,b){if(null!=a)return Array.isArray(a)||nb(a)?qb(a,b):b(a)}
  function qb (line 38) | function qb(a,b){if(Array.isArray(a)){for(var c=Array(a.length),d=0;d<a....
  function O (line 38) | function O(a,b,c){var d=rb;rb=null;a||(a=d);d=this.constructor.ba;a||(a=...
  function tb (line 39) | function tb(a){var b=a.l+a.j;a.h[b]||(a.i=a.h[b]={})}
  function P (line 39) | function P(a,b,c){return-1===b?null:(void 0===c?0:c)||b>=a.l?a.i?a.i[b]:...
  function ub (line 39) | function ub(a,b,c){c=void 0===c?!0:c;var d=void 0===d?!1:d;var e=P(a,b,d...
  function vb (line 39) | function vb(a){var b=ub(a,3,!1);a.m||(a.m={});if(!a.m[3]){for(var c=0;c<...
  function R (line 39) | function R(a,b,c){a=P(a,b);return null==a?c:a}
  function S (line 40) | function S(a,b,c){a=P(a,b);a=null==a?a:+a;return null==a?void 0===c?0:c:a}
  function Q (line 40) | function Q(a,b,c,d){(void 0===d?0:d)||b>=a.l?(tb(a),a.i[b]=c):a.h[b+a.j]=c}
  function wb (line 40) | function wb(a,b,c){if(-1===c)return null;a.g||(a.g={});var d=a.g[c];if(d...
  function xb (line 41) | function xb(a,b,c){a.g||(a.g={});var d=a.g[c];if(!d){var e=ub(a,c,!1);d=...
  function yb (line 41) | function yb(a,b,c,d,e){var g=xb(a,d,b);c=c?c:new d;a=ub(a,b);void 0!=e?(...
  function T (line 42) | function T(a){if(a.g)for(var b in a.g){var c=a.g[b];if(Array.isArray(c))...
  function zb (line 42) | function zb(a,b){if(a=a.o){gb(b,b.g.end());for(var c=0;c<a.length;c++)gb...
  function Ab (line 42) | function Ab(a){var b=a[0];switch(a.length){case 2:var c=a[1];return func...
  function U (line 43) | function U(a,b,c){for(;$a(b)&&4!=b.h;){var d=b.i,e=c[d];if(e){if(Array.i...
  function Bb (line 43) | function Bb(a,b){var c=new fb;b(a,c);a=c.i+c.g.length();if(0===a)c=new U...
  function Cb (line 44) | function Cb(a,b,c){if(eb.length){var d=eb.pop();a&&(Ua(d.g,a),d.i=-1,d.h...
  function W (line 45) | function W(a,b,c){b=P(b,c);if(null!=b){Ya(a.g,8*c+5);a=a.g;var d=b;d=(c=...
  function X (line 46) | function X(a,b,c){if(5!==a.h)return!1;Q(b,c,a.g.o());return!0}
  function Db (line 46) | function Db(a,b,c){if(5!==a.h&&2!==a.h)return!1;b=ub(b,c);2==a.h?db(a,Ta...
  function Eb (line 46) | function Eb(a,b,c){if(0!==a.h)return!1;Q(b,c,Va(a.g));return!0}
  function Fb (line 46) | function Fb(a,b,c){if(0!==a.h)return!1;Q(b,c,a.g.j());return!0}
  function Gb (line 47) | function Gb(a,b,c){if(2!==a.h)return!1;var d=a.g.j();a=a.g;var e=a.g;a.g...
  function Hb (line 48) | function Hb(a,b,c,d,e){if(2!==a.h)return!1;a=cb(a,new d,e);var g=void 0=...
  function Ib (line 49) | function Ib(a,b,c,d,e){if(2!==a.h)return!1;a=cb(a,new d,e);yb(b,c,a,d,vo...
  function Jb (line 49) | function Jb(a,b,c){if(0!==a.h&&2!==a.h)return!1;b=ub(b,c);2==a.h?db(a,Ta...
  function Kb (line 49) | function Kb(a,b,c){if(0!==a.h)return!1;Q(b,c,Va(a.g));return!0}
  function Y (line 49) | function Y(a){O.call(this,a,-1,Lb)}
  function Nb (line 49) | function Nb(a,b){return U(a,b,Mb||(Mb={1:Fb,2:Fb,3:Db,4:Kb}))}
  function Ob (line 49) | function Ob(a){O.call(this,a)}
  function Qb (line 49) | function Qb(a,b){var c=P(a,1);if(null!=c&&null!=c){Ya(b.g,8);var d=b.g;i...
  function Rb (line 49) | function Rb(a,b){return U(a,b,Pb||(Pb={1:Fb,2:X,3:Gb,4:Gb}))}
  function Sb (line 49) | function Sb(a){O.call(this,a,-1,Tb)}
  function Vb (line 49) | function Vb(a,b){return U(a,b,Ub||(Ub={1:[Ib,Ob,Rb]}))}
  function Wb (line 49) | function Wb(a){O.call(this,a)}
  function Yb (line 49) | function Yb(a,b){W(b,a,1);W(b,a,2);W(b,a,3);W(b,a,4);W(b,a,5);zb(a,b)}
  function Zb (line 49) | function Zb(a,b){return U(a,b,Xb||(Xb={1:X,2:X,3:X,4:X,5:X}))}
  function $b (line 49) | function $b(a){O.call(this,a,-1,ac)}
  function cc (line 49) | function cc(a,b){return U(a,b,bc||(bc={1:[Ib,Wb,Zb]}))}
  function dc (line 49) | function dc(a){O.call(this,a)}
  function fc (line 49) | function fc(a,b){W(b,a,1);W(b,a,2);W(b,a,3);W(b,a,4);W(b,a,5);var c=P(a,...
  function gc (line 49) | function gc(a,b){return U(a,b,ec||(ec={1:X,2:X,3:X,4:X,5:X,6:Eb}))}
  function Z (line 49) | function Z(a){O.call(this,a,-1,hc)}
  function jc (line 49) | function jc(a,b){return U(a,b,ic||(ic={1:Kb,2:Kb,3:Db,4:Jb}))}
  function kc (line 49) | function kc(a){O.call(this,a)}
  function mc (line 49) | function mc(a,b){return U(a,b,lc||(lc={1:[Hb,Z,jc],2:[Hb,Y,Nb]}))}
  function uc (line 51) | function uc(a,b,c){c=a.createShader(0===c?a.VERTEX_SHADER:a.FRAGMENT_SHA...
  function vc (line 51) | function vc(a){return xb(a,Ob,1).map(function(b){return{index:R(b,1,0),s...
  function wc (line 51) | function wc(a){return{x:S(a,1),y:S(a,2),z:S(a,3),visibility:null!=P(a,4)...
  function xc (line 51) | function xc(a){return xb(Cb(a,$b,cc),Wb,1).map(wc)}
  function yc (line 51) | function yc(a,b){this.h=a;this.g=b;this.l=0}
  function zc (line 52) | function zc(a,b,c){Ac(a,b);if("function"===typeof a.g.canvas.transferToI...
  function Ac (line 53) | function Ac(a,b){var c=a.g;if(void 0===a.m){var d=uc(c,"\n  attribute ve...
  function Bc (line 56) | function Bc(a){this.g=a}
  function Dc (line 56) | function Dc(a,b){return b+a}
  function Ec (line 56) | function Ec(a,b){window[a]=b}
  function Fc (line 56) | function Fc(a){var b=document.createElement("script");b.setAttribute("sr...
  function Gc (line 57) | function Gc(){return H(function(a){switch(a.g){case 1:return a.m=2,F(a,W...
  function Hc (line 58) | function Hc(a){this.g=a;this.listeners={};this.j={};this.F={};this.m={};...
  function Ic (line 60) | function Ic(a){var b,c,d,e,g,f,k,h,l,n,r;return H(function(p){switch(p.g...
  function Kc (line 64) | function Kc(a){var b,c,d,e,g,f,k,h;return H(function(l){if(1==l.g){if(a....
  function Mc (line 68) | function Mc(a){var b,c,d,e,g,f,k;return H(function(h){switch(h.g){case 1...
  function Jc (line 69) | function Jc(a,b){var c,d;return H(function(e){if(b in a.F)return e.retur...
  function Nc (line 75) | function Nc(a,b,c){var d,e,g,f,k,h,l,n,r,p,m,q,t,w;return H(function(v){...
  function Oc (line 77) | function Oc(a,b,c){var d;return H(function(e){return"number"===typeof c|...
  function Lc (line 78) | function Lc(a,b){for(var c=b.name||"$",d=[].concat(D(b.wants)),e=new a.h...
  function Pc (line 79) | function Pc(a){return a.map(Qc)}
  function Qc (line 79) | function Qc(a){a=Cb(a,kc,mc);var b=a.getMesh();if(!b)return a;var c=new ...
  function Rc (line 79) | function Rc(a){var b=this;a=a||{};this.g=new Hc({locateFile:a.locateFile...

FILE: src/renderer/public/lib/@mediapipe/face_mesh/face_mesh_solution_packed_assets_loader.js
  function fetchRemotePackage (line 29) | function fetchRemotePackage(packageName, packageSize, callback, errback) {
  function handleError (line 89) | function handleError(error) {
  function runWithFS (line 105) | function runWithFS() {

FILE: src/renderer/public/lib/@mediapipe/face_mesh/face_mesh_solution_simd_wasm_bin.js
  function locateFile (line 9) | function locateFile(path){if(Module["locateFile"]){return Module["locate...
  function warnOnce (line 9) | function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnc...
  function convertJsFunctionToWasm (line 9) | function convertJsFunctionToWasm(func,sig){if(typeof WebAssembly.Functio...
  function getEmptyTableSlot (line 9) | function getEmptyTableSlot(){if(freeTableIndexes.length){return freeTabl...
  function addFunctionWasm (line 9) | function addFunctionWasm(func,sig){if(!functionsInTableMap){functionsInT...
  function assert (line 9) | function assert(condition,text){if(!condition){abort("Assertion failed: ...
  function getCFunc (line 9) | function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot ...
  function ccall (line 9) | function ccall(ident,returnType,argTypes,args,opts){var toC={"string":fu...
  function UTF8ArrayToString (line 9) | function UTF8ArrayToString(heap,idx,maxBytesToRead){var endIdx=idx+maxBy...
  function UTF8ToString (line 9) | function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(H...
  function stringToUTF8Array (line 9) | function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxByte...
  function stringToUTF8 (line 9) | function stringToUTF8(str,outPtr,maxBytesToWrite){assert(typeof maxBytes...
  function lengthBytesUTF8 (line 9) | function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){va...
  function UTF16ToString (line 9) | function UTF16ToString(ptr,maxBytesToRead){assert(ptr%2==0,"Pointer pass...
  function stringToUTF16 (line 9) | function stringToUTF16(str,outPtr,maxBytesToWrite){assert(outPtr%2==0,"P...
  function lengthBytesUTF16 (line 9) | function lengthBytesUTF16(str){return str.length*2}
  function UTF32ToString (line 9) | function UTF32ToString(ptr,maxBytesToRead){assert(ptr%4==0,"Pointer pass...
  function stringToUTF32 (line 9) | function stringToUTF32(str,outPtr,maxBytesToWrite){assert(outPtr%4==0,"P...
  function lengthBytesUTF32 (line 9) | function lengthBytesUTF32(str){var len=0;for(var i=0;i<str.length;++i){v...
  function allocateUTF8 (line 9) | function allocateUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_mall...
  function writeArrayToMemory (line 9) | function writeArrayToMemory(array,buffer){assert(array.length>=0,"writeA...
  function writeAsciiToMemory (line 9) | function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i<str.le...
  function alignUp (line 9) | function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}ret...
  function updateGlobalBufferAndViews (line 9) | function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP...
  function writeStackCookie (line 9) | function writeStackCookie(){var max=_emscripten_stack_get_end();assert((...
  function checkStackCookie (line 9) | function checkStackCookie(){if(ABORT)return;var max=_emscripten_stack_ge...
  function keepRuntimeAlive (line 9) | function keepRuntimeAlive(){return noExitRuntime||runtimeKeepaliveCounte...
  function preRun (line 9) | function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="func...
  function initRuntime (line 9) | function initRuntime(){checkStackCookie();assert(!runtimeInitialized);ru...
  function exitRuntime (line 9) | function exitRuntime(){checkStackCookie();runtimeExited=true}
  function postRun (line 9) | function postRun(){checkStackCookie();if(Module["postRun"]){if(typeof Mo...
  function addOnPreRun (line 9) | function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}
  function addOnInit (line 9) | function addOnInit(cb){__ATINIT__.unshift(cb)}
  function addOnPostRun (line 9) | function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}
  function getUniqueRunDependency (line 9) | function getUniqueRunDependency(id){var orig=id;while(1){if(!runDependen...
  function addRunDependency (line 9) | function addRunDependency(id){runDependencies++;if(Module["monitorRunDep...
  function removeRunDependency (line 9) | function removeRunDependency(id){runDependencies--;if(Module["monitorRun...
  function abort (line 9) | function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+...
  function isDataURI (line 9) | function isDataURI(filename){return filename.startsWith(dataURIPrefix)}
  function isFileURI (line 9) | function isFileURI(filename){return filename.startsWith("file://")}
  function createExportWrapper (line 9) | function createExportWrapper(name,fixedasm){return function(){var displa...
  function getBinary (line 9) | function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return...
  function getBinaryPromise (line 9) | function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRON...
  function createWasm (line 9) | function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_previ...
  function HaveOffsetConverter (line 9) | function HaveOffsetConverter(){return typeof wasmOffsetConverter!=="unde...
  function _emscripten_set_main_loop_timing (line 9) | function _emscripten_set_main_loop_timing(mode,value){Browser.mainLoop.t...
  function _emscripten_webgl_do_commit_frame (line 9) | function _emscripten_webgl_do_commit_frame(){if(!GL.currentContext||!GL....
  function _exit (line 9) | function _exit(status){exit(status)}
  function maybeExit (line 9) | function maybeExit(){if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch...
  function setMainLoop (line 9) | function setMainLoop(browserIterationFunc,fps,simulateInfiniteLoop,arg,n...
  function callUserCallback (line 9) | function callUserCallback(func,synchronous){if(ABORT){err("user callback...
  function safeSetTimeout (line 9) | function safeSetTimeout(func,timeout){return setTimeout(function(){callU...
  function finish (line 9) | function finish(audio){if(done)return;done=true;Module["preloadedAudios"...
  function fail (line 9) | function fail(){if(done)return;done=true;Module["preloadedAudios"][name]...
  function encode64 (line 9) | function encode64(data){var BASE="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkl...
  function pointerLockChange (line 9) | function pointerLockChange(){Browser.pointerLock=document["pointerLockEl...
  function fullscreenChange (line 9) | function fullscreenChange(){Browser.isFullscreen=false;var canvasContain...
  function callRuntimeCallbacks (line 9) | function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var c...
  function demangle (line 9) | function demangle(func){warnOnce("warning: build with  -s DEMANGLE_SUPPO...
  function demangleAll (line 9) | function demangleAll(text){var regex=/\b_Z[\w\d_]+/g;return text.replace...
  function jsStackTrace (line 9) | function jsStackTrace(){var error=new Error;if(!error.stack){try{throw n...
  function stackTrace (line 9) | function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"]...
  function ___cxa_allocate_exception (line 9) | function ___cxa_allocate_exception(size){return _malloc(size+16)+16}
  function _atexit (line 9) | function _atexit(func,arg){}
  function ___cxa_atexit (line 9) | function ___cxa_atexit(a0,a1){return _atexit(a0,a1)}
  function ExceptionInfo (line 9) | function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-16;thi...
  function CatchInfo (line 9) | function CatchInfo(ptr){this.free=function(){_free(this.ptr);this.ptr=0}...
  function exception_addRef (line 9) | function exception_addRef(info){info.add_ref()}
  function ___cxa_begin_catch (line 9) | function ___cxa_begin_catch(ptr){var catchInfo=new CatchInfo(ptr);var in...
  function ___cxa_free_exception (line 9) | function ___cxa_free_exception(ptr){try{return _free(new ExceptionInfo(p...
  function exception_decRef (line 9) | function exception_decRef(info){if(info.release_ref()&&!info.get_rethrow...
  function ___cxa_end_catch (line 9) | function ___cxa_end_catch(){_setThrew(0);assert(exceptionCaught.length>0...
  function ___resumeException (line 9) | function ___resumeException(catchInfoPtr){var catchInfo=new CatchInfo(ca...
  function ___cxa_find_matching_catch_2 (line 9) | function ___cxa_find_matching_catch_2(){var thrown=exceptionLast;if(!thr...
  function ___cxa_find_matching_catch_3 (line 9) | function ___cxa_find_matching_catch_3(){var thrown=exceptionLast;if(!thr...
  function ___cxa_rethrow (line 9) | function ___cxa_rethrow(){var catchInfo=exceptionCaught.pop();if(!catchI...
  function ___cxa_thread_atexit (line 9) | function ___cxa_thread_atexit(a0,a1){return _atexit(a0,a1)}
  function ___cxa_throw (line 9) | function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(pt...
  function setErrNo (line 9) | function setErrNo(value){HEAP32[___errno_location()>>2]=value;return value}
  function getRandomDevice (line 9) | function getRandomDevice(){if(typeof crypto==="object"&&typeof crypto["g...
  function trim (line 9) | function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[sta...
  function zeroMemory (line 9) | function zeroMemory(address,size){HEAPU8.fill(0,address,address+size)}
  function alignMemory (line 9) | function alignMemory(size,alignment){assert(alignment,"alignment argumen...
  function mmapAlloc (line 9) | function mmapAlloc(size){size=alignMemory(size,65536);var ptr=_memalign(...
  function asyncLoad (line 9) | function asyncLoad(url,onload,onerror,noRunDep){var dep=!noRunDep?getUni...
  function doCallback (line 9) | function doCallback(errCode){assert(FS.syncFSRequests>0);FS.syncFSReques...
  function done (line 9) | function done(errCode){if(errCode){if(!done.errored){done.errored=true;r...
  function LazyUint8Array (line 9) | function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}
  function processData (line 9) | function processData(byteArray){function finish(byteArray){if(preFinish)...
  function finish (line 9) | function finish(){if(fail==0)onload();else onerror()}
  function finish (line 9) | function finish(){if(fail==0)onload();else onerror()}
  function ___sys_fcntl64 (line 9) | function ___sys_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var...
  function ___sys_ioctl (line 9) | function ___sys_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var st...
  function syscallMmap2 (line 9) | function syscallMmap2(addr,len,prot,flags,fd,off){off<<=12;var ptr;var a...
  function ___sys_mmap2 (line 9) | function ___sys_mmap2(addr,len,prot,flags,fd,off){try{return syscallMmap...
  function ___sys_open (line 9) | function ___sys_open(path,flags,varargs){SYSCALLS.varargs=varargs;try{va...
  function ___sys_stat64 (line 9) | function ___sys_stat64(path,buf){try{path=SYSCALLS.getStr(path);return S...
  function makeLegalFunctionName (line 9) | function makeLegalFunctionName(name){if(undefined===name){return"_unknow...
  function createNamedFunction (line 9) | function createNamedFunction(name,body){name=makeLegalFunctionName(name)...
  function count_emval_handles (line 9) | function count_emval_handles(){var count=0;for(var i=5;i<emval_handle_ar...
  function get_first_emval (line 9) | function get_first_emval(){for(var i=5;i<emval_handle_array.length;++i){...
  function init_emval (line 9) | function init_emval(){Module["count_emval_handles"]=count_emval_handles;...
  function __emval_register (line 9) | function __emval_register(value){switch(value){case undefined:{return 1}...
  function extendError (line 9) | function extendError(baseErrorType,errorName){var errorClass=createNamed...
  function embind_init_charCodes (line 9) | function embind_init_charCodes(){var codes=new Array(256);for(var i=0;i<...
  function readLatin1String (line 9) | function readLatin1String(ptr){var ret="";var c=ptr;while(HEAPU8[c]){ret...
  function getInheritedInstanceCount (line 9) | function getInheritedInstanceCount(){return Object.keys(registeredInstan...
  function getLiveInheritedInstances (line 9) | function getLiveInheritedInstances(){var rv=[];for(var k in registeredIn...
  function flushPendingDeletes (line 9) | function flushPendingDeletes(){while(deletionQueue.length){var obj=delet...
  function setDelayFunction (line 9) | function setDelayFunction(fn){delayFunction=fn;if(deletionQueue.length&&...
  function init_embind (line 9) | function init_embind(){Module["getInheritedInstanceCount"]=getInheritedI...
  function throwBindingError (line 9) | function throwBindingError(message){throw new BindingError(message)}
  function getBasestPointer (line 9) | function getBasestPointer(class_,ptr){if(ptr===undefined){throwBindingEr...
  function registerInheritedInstance (line 9) | function registerInheritedInstance(class_,ptr,instance){ptr=getBasestPoi...
  function requireHandle (line 9) | function requireHandle(handle){if(!handle){throwBindingError("Cannot use...
  function getTypeName (line 9) | function getTypeName(type){var ptr=___getTypeName(type);var rv=readLatin...
  function requireRegisteredType (line 9) | function requireRegisteredType(rawType,humanName){var impl=registeredTyp...
  function unregisterInheritedInstance (line 9) | function unregisterInheritedInstance(class_,ptr){ptr=getBasestPointer(cl...
  function detachFinalizer (line 9) | function detachFinalizer(handle){}
  function runDestructor (line 9) | function runDestructor($$){if($$.smartPtr){$$.smartPtrType.rawDestructor...
  function releaseClassHandle (line 9) | function releaseClassHandle($$){$$.count.value-=1;var toDelete=0===$$.co...
  function attachFinalizer (line 9) | function attachFinalizer(handle){if("undefined"===typeof FinalizationGro...
  function __embind_create_inheriting_constructor (line 9) | function __embind_create_inheriting_constructor(constructorName,wrapperT...
  function runDestructors (line 9) | function runDestructors(destructors){while(destructors.length){var ptr=d...
  function simpleReadValueFromPointer (line 9) | function simpleReadValueFromPointer(pointer){return this["fromWireType"]...
  function throwInternalError (line 9) | function throwInternalError(message){throw new InternalError(message)}
  function whenDependentTypesAreResolved (line 9) | function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeCon...
  function __embind_finalize_value_object (line 9) | function __embind_finalize_value_object(structType){var reg=structRegist...
  function __embind_register_bigint (line 9) | function __embind_register_bigint(primitiveType,name,size,minRange,maxRa...
  function getShiftFromSize (line 9) | function getShiftFromSize(size){switch(size){case 1:return 0;case 2:retu...
  function registerType (line 9) | function registerType(rawType,registeredInstance,options){options=option...
  function __embind_register_bool (line 9) | function __embind_register_bool(rawType,name,size,trueValue,falseValue){...
  function ClassHandle_isAliasOf (line 9) | function ClassHandle_isAliasOf(other){if(!(this instanceof ClassHandle))...
  function shallowCopyInternalPointer (line 9) | function shallowCopyInternalPointer(o){return{count:o.count,deleteSchedu...
  function throwInstanceAlreadyDeleted (line 9) | function throwInstanceAlreadyDeleted(obj){function getInstanceTypeName(h...
  function ClassHandle_clone (line 9) | function ClassHandle_clone(){if(!this.$$.ptr){throwInstanceAlreadyDelete...
  function ClassHandle_delete (line 9) | function ClassHandle_delete(){if(!this.$$.ptr){throwInstanceAlreadyDelet...
  function ClassHandle_isDeleted (line 9) | function ClassHandle_isDeleted(){return!this.$$.ptr}
  function ClassHandle_deleteLater (line 9) | function ClassHandle_deleteLater(){if(!this.$$.ptr){throwInstanceAlready...
  function init_ClassHandle (line 9) | function init_ClassHandle(){ClassHandle.prototype["isAliasOf"]=ClassHand...
  function ClassHandle (line 9) | function ClassHandle(){}
  function ensureOverloadTable (line 9) | function ensureOverloadTable(proto,methodName,humanName){if(undefined===...
  function exposePublicSymbol (line 9) | function exposePublicSymbol(name,value,numArguments){if(Module.hasOwnPro...
  function RegisteredClass (line 9) | function RegisteredClass(name,constructor,instancePrototype,rawDestructo...
  function upcastPointer (line 9) | function upcastPointer(ptr,ptrClass,desiredClass){while(ptrClass!==desir...
  function constNoSmartPtrRawPointerToWireType (line 9) | function constNoSmartPtrRawPointerToWireType(destructors,handle){if(hand...
  function genericPointerToWireType (line 9) | function genericPointerToWireType(destructors,handle){var ptr;if(handle=...
  function nonConstNoSmartPtrRawPointerToWireType (line 9) | function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(h...
  function RegisteredPointer_getPointee (line 9) | function RegisteredPointer_getPointee(ptr){if(this.rawGetPointee){ptr=th...
  function RegisteredPointer_destructor (line 9) | function RegisteredPointer_destructor(ptr){if(this.rawDestructor){this.r...
  function RegisteredPointer_deleteObject (line 9) | function RegisteredPointer_deleteObject(handle){if(handle!==null){handle...
  function downcastPointer (line 9) | function downcastPointer(ptr,ptrClass,desiredClass){if(ptrClass===desire...
  function getInheritedInstance (line 9) | function getInheritedInstance(class_,ptr){ptr=getBasestPointer(class_,pt...
  function makeClassHandle (line 9) | function makeClassHandle(prototype,record){if(!record.ptrType||!record.p...
  function RegisteredPointer_fromWireType (line 9) | function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPoin...
  function init_RegisteredPointer (line 9) | function init_RegisteredPointer(){RegisteredPointer.prototype.getPointee...
  function RegisteredPointer (line 9) | function RegisteredPointer(name,registeredClass,isReference,isConst,isSm...
  function replacePublicSymbol (line 9) | function replacePublicSymbol(name,value,numArguments){if(!Module.hasOwnP...
  function dynCallLegacy (line 9) | function dynCallLegacy(sig,ptr,args){assert("dynCall_"+sig in Module,"ba...
  function dynCall (line 9) | function dynCall(sig,ptr,args){if(sig.includes("j")){return dynCallLegac...
  function getDynCaller (line 9) | function getDynCaller(sig,ptr){assert(sig.includes("j"),"getDynCaller sh...
  function embind__requireFunction (line 9) | function embind__requireFunction(signature,rawFunction){signature=readLa...
  function throwUnboundTypeError (line 9) | function throwUnboundTypeError(message,types){var unboundTypes=[];var se...
  function __embind_register_class (line 9) | function __embind_register_class(rawType,rawPointerType,rawConstPointerT...
  function new_ (line 9) | function new_(constructor,argumentList){if(!(constructor instanceof Func...
  function craftInvokerFunction (line 9) | function craftInvokerFunction(humanName,argTypes,classType,cppInvokerFun...
  function heap32VectorToArray (line 9) | function heap32VectorToArray(count,firstElement){var array=[];for(var i=...
  function __embind_register_class_class_function (line 9) | function __embind_register_class_class_function(rawClassType,methodName,...
  function __embind_register_class_constructor (line 9) | function __embind_register_class_constructor(rawClassType,argCount,rawAr...
  function __embind_register_class_function (line 9) | function __embind_register_class_function(rawClassType,methodName,argCou...
  function validateThis (line 9) | function validateThis(this_,classType,humanName){if(!(this_ instanceof O...
  function __embind_register_class_property (line 9) | function __embind_register_class_property(classType,fieldName,getterRetu...
  function __emval_decref (line 9) | function __emval_decref(handle){if(handle>4&&0===--emval_handle_array[ha...
  function __embind_register_emval (line 9) | function __embind_register_emval(rawType,name){name=readLatin1String(nam...
  function _embind_repr (line 9) | function _embind_repr(v){if(v===null){return"null"}var t=typeof v;if(t==...
  function floatReadValueFromPointer (line 9) | function floatReadValueFromPointer(name,shift){switch(shift){case 2:retu...
  function __embind_register_float (line 9) | function __embind_register_float(rawType,name,size){var shift=getShiftFr...
  function __embind_register_function (line 9) | function __embind_register_function(name,argCount,rawArgTypesAddr,signat...
  function integerReadValueFromPointer (line 9) | function integerReadValueFromPointer(name,shift,signed){switch(shift){ca...
  function __embind_register_integer (line 9) | function __embind_register_integer(primitiveType,name,size,minRange,maxR...
  function __embind_register_memory_view (line 9) | function __embind_register_memory_view(rawType,dataTypeIndex,name){var t...
  function __embind_register_std_string (line 9) | function __embind_register_std_string(rawType,name){name=readLatin1Strin...
  function __embind_register_std_wstring (line 9) | function __embind_register_std_wstring(rawType,charSize,name){name=readL...
  function __embind_register_value_object (line 9) | function __embind_register_value_object(rawType,name,constructorSignatur...
  function __embind_register_value_object_field (line 9) | function __embind_register_value_object_field(structType,fieldName,gette...
  function __embind_register_void (line 9) | function __embind_register_void(rawType,name){name=readLatin1String(name...
  function getStringOrSymbol (line 9) | function getStringOrSymbol(address){var symbol=emval_symbols[address];if...
  function __emval_call_void_method (line 9) | function __emval_call_void_method(caller,handle,methodName,args){caller=...
  function __emval_addMethodCaller (line 9) | function __emval_addMethodCaller(caller){var id=emval_methodCallers.leng...
  function __emval_lookupTypes (line 9) | function __emval_lookupTypes(argCount,argTypes){var a=new Array(argCount...
  function __emval_get_method_caller (line 9) | function __emval_get_method_caller(argCount,argTypes){var types=__emval_...
  function __emval_incref (line 9) | function __emval_incref(handle){if(handle>4){emval_handle_array[handle]....
  function __emval_take_value (line 9) | function __emval_take_value(type,argv){type=requireRegisteredType(type,"...
  function _abort (line 9) | function _abort(){abort()}
  function _clock_gettime (line 9) | function _clock_gettime(clk_id,tp){var now;if(clk_id===0){now=Date.now()...
  function _dlopen (line 9) | function _dlopen(filename,flag){abort("To use dlopen, you need to use Em...
  function _dlsym (line 9) | function _dlsym(handle,symbol){abort("To use dlopen, you need to use Ems...
  function readAsmConstArgs (line 9) | function readAsmConstArgs(sigPtr,buf){assert(Array.isArray(readAsmConstA...
  function _emscripten_asm_const_int (line 9) | function _emscripten_asm_const_int(code,sigPtr,argbuf){var args=readAsmC...
  function _emscripten_get_heap_max (line 9) | function _emscripten_get_heap_max(){return 2147483648}
  function _emscripten_memcpy_big (line 9) | function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src...
  function _emscripten_pc_get_function (line 9) | function _emscripten_pc_get_function(pc){abort("Cannot use emscripten_pc...
  function emscripten_realloc_buffer (line 9) | function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer...
  function _emscripten_resize_heap (line 9) | function _emscripten_resize_heap(requestedSize){var oldSize=HEAPU8.lengt...
  function _emscripten_generate_pc (line 9) | function _emscripten_generate_pc(frame){abort("Cannot use emscripten_gen...
  function __emscripten_save_in_unwind_cache (line 9) | function __emscripten_save_in_unwind_cache(callstack){callstack.forEach(...
  function _emscripten_stack_snapshot (line 9) | function _emscripten_stack_snapshot(){var callstack=(new Error).stack.sp...
  function _emscripten_stack_unwind_buffer (line 9) | function _emscripten_stack_unwind_buffer(addr,buffer,count){var stack;if...
  function _emscripten_thread_sleep (line 9) | function _emscripten_thread_sleep(msecs){var start=_emscripten_get_now()...
  function __webgl_enable_ANGLE_instanced_arrays (line 9) | function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExten...
  function __webgl_enable_OES_vertex_array_object (line 9) | function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExte...
  function __webgl_enable_WEBGL_draw_buffers (line 9) | function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension...
  function __webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance (line 9) | function __webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(c...
  function __webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance (line 9) | function __webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_inst...
  function __webgl_enable_WEBGL_multi_draw (line 9) | function __webgl_enable_WEBGL_multi_draw(ctx){return!!(ctx.multiDrawWebg...
  function draw (line 9) | function draw(){gl.vertexAttribPointer(context.blitPosLoc,2,5126,false,0...
  function arraysHaveEqualContent (line 9) | function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)r...
  function findEventTarget (line 9) | function findEventTarget(target){warnOnce("Rules for selecting event tar...
  function findCanvasEventTarget (line 9) | function findCanvasEventTarget(target){if(typeof target==="number")targe...
  function _emscripten_webgl_do_create_context (line 9) | function _emscripten_webgl_do_create_context(target,attributes){assert(a...
  function _emscripten_webgl_create_context (line 9) | function _emscripten_webgl_create_context(a0,a1){return _emscripten_webg...
  function _emscripten_webgl_do_get_current_context (line 9) | function _emscripten_webgl_do_get_current_context(){return GL.currentCon...
  function _emscripten_webgl_get_current_context (line 9) | function _emscripten_webgl_get_current_context(){return _emscripten_webg...
  function _emscripten_webgl_make_context_current (line 9) | function _emscripten_webgl_make_context_current(contextHandle){var succe...
  function _emscripten_webgl_destroy_context (line 9) | function _emscripten_webgl_destroy_context(contextHandle){if(GL.currentC...
  function _emscripten_webgl_get_context_attributes (line 9) | function _emscripten_webgl_get_context_attributes(c,a){if(!a)return-5;c=...
  function _emscripten_webgl_init_context_attributes (line 9) | function _emscripten_webgl_init_context_attributes(attributes){assert(at...
  function getExecutableName (line 9) | function getExecutableName(){return thisProgram||"./this.program"}
  function getEnvStrings (line 9) | function getEnvStrings(){if(!getEnvStrings.strings){var lang=(typeof nav...
  function _environ_get (line 9) | function _environ_get(__environ,environ_buf){var bufSize=0;getEnvStrings...
  function _environ_sizes_get (line 9) | function _environ_sizes_get(penviron_count,penviron_buf_size){var string...
  function _fd_close (line 9) | function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.cl...
  function _fd_read (line 9) | function _fd_read(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamF...
  function _fd_seek (line 9) | function _fd_seek(fd,offset_low,offset_high,whence,newOffset){try{var st...
  function _fd_write (line 9) | function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStream...
  function _getTempRet0 (line 9) | function _getTempRet0(){return getTempRet0()}
  function _getentropy (line 9) | function _getentropy(buffer,size){if(!_getentropy.randomDevice){_getentr...
  function _glActiveTexture (line 9) | function _glActiveTexture(x0){GLctx["activeTexture"](x0)}
  function _glAttachShader (line 9) | function _glAttachShader(program,shader){GLctx.attachShader(GL.programs[...
  function _glBindAttribLocation (line 9) | function _glBindAttribLocation(program,index,name){GLctx.bindAttribLocat...
  function _glBindBuffer (line 9) | function _glBindBuffer(target,buffer){if(target==34962){GLctx.currentArr...
  function _glBindBufferBase (line 9) | function _glBindBufferBase(target,index,buffer){GLctx["bindBufferBase"](...
  function _glBindFramebuffer (line 9) | function _glBindFramebuffer(target,framebuffer){GLctx.bindFramebuffer(ta...
  function _glBindTexture (line 9) | function _glBindTexture(target,texture){GLctx.bindTexture(target,GL.text...
  function _glBindVertexArray (line 9) | function _glBindVertexArray(vao){GLctx["bindVertexArray"](GL.vaos[vao]);...
  function _glBufferData (line 9) | function _glBufferData(target,size,data,usage){if(GL.currentContext.vers...
  function convertI32PairToI53 (line 9) | function convertI32PairToI53(lo,hi){assert(hi===(hi|0));return(lo>>>0)+h...
  function _glClientWaitSync (line 9) | function _glClientWaitSync(sync,flags,timeoutLo,timeoutHi){return GLctx....
  function _glCompileShader (line 9) | function _glCompileShader(shader){GLctx.compileShader(GL.shaders[shader])}
  function _glCreateProgram (line 9) | function _glCreateProgram(){var id=GL.getNewId(GL.programs);var program=...
  function _glCreateShader (line 9) | function _glCreateShader(shaderType){var id=GL.getNewId(GL.shaders);GL.s...
  function _glDeleteBuffers (line 9) | function _glDeleteBuffers(n,buffers){for(var i=0;i<n;i++){var id=HEAP32[...
  function _glDeleteFramebuffers (line 9) | function _glDeleteFramebuffers(n,framebuffers){for(var i=0;i<n;++i){var ...
  function _glDeleteProgram (line 9) | function _glDeleteProgram(id){if(!id)return;var program=GL.programs[id];...
  function _glDeleteShader (line 9) | function _glDeleteShader(id){if(!id)return;var shader=GL.shaders[id];if(...
  function _glDeleteSync (line 9) | function _glDeleteSync(id){if(!id)return;var sync=GL.syncs[id];if(!sync)...
  function _glDeleteTextures (line 9) | function _glDeleteTextures(n,textures){for(var i=0;i<n;i++){var id=HEAP3...
  function _glDeleteVertexArrays (line 9) | function _glDeleteVertexArrays(n,vaos){for(var i=0;i<n;i++){var id=HEAP3...
  function _glDisable (line 9) | function _glDisable(x0){GLctx["disable"](x0)}
  function _glDisableVertexAttribArray (line 9) | function _glDisableVertexAttribArray(index){var cb=GL.currentContext.cli...
  function _glDrawArrays (line 9) | function _glDrawArrays(mode,first,count){GL.preDrawHandleClientVertexAtt...
  function _glDrawBuffers (line 9) | function _glDrawBuffers(n,bufs){var bufArray=tempFixedLengthArray[n];for...
  function _glEnableVertexAttribArray (line 9) | function _glEnableVertexAttribArray(index){var cb=GL.currentContext.clie...
  function _glFenceSync (line 9) | function _glFenceSync(condition,flags){var sync=GLctx.fenceSync(conditio...
  function _glFinish (line 9) | function _glFinish(){GLctx["finish"]()}
  function _glFlush (line 9) | function _glFlush(){GLctx["flush"]()}
  function _glFramebufferTexture2D (line 9) | function _glFramebufferTexture2D(target,attachment,textarget,texture,lev...
  function _glFramebufferTextureLayer (line 9) | function _glFramebufferTextureLayer(target,attachment,texture,level,laye...
  function __glGenObject (line 9) | function __glGenObject(n,buffers,createFunction,objectTable){for(var i=0...
  function _glGenBuffers (line 9) | function _glGenBuffers(n,buffers){__glGenObject(n,buffers,"createBuffer"...
  function _glGenFramebuffers (line 9) | function _glGenFramebuffers(n,ids){__glGenObject(n,ids,"createFramebuffe...
  function _glGenTextures (line 9) | function _glGenTextures(n,textures){__glGenObject(n,textures,"createText...
  function _glGenVertexArrays (line 9) | function _glGenVertexArrays(n,arrays){__glGenObject(n,arrays,"createVert...
  function _glGetAttribLocation (line 9) | function _glGetAttribLocation(program,name){return GLctx.getAttribLocati...
  function _glGetError (line 9) | function _glGetError(){var error=GLctx.getError()||GL.lastError;GL.lastE...
  function readI53FromI64 (line 9) | function readI53FromI64(ptr){return HEAPU32[ptr>>2]+HEAP32[ptr+4>>2]*429...
  function readI53FromU64 (line 9) | function readI53FromU64(ptr){return HEAPU32[ptr>>2]+HEAPU32[ptr+4>>2]*42...
  function writeI53ToI64 (line 9) | function writeI53ToI64(ptr,num){HEAPU32[ptr>>2]=num;HEAPU32[ptr+4>>2]=(n...
  function emscriptenWebGLGet (line 9) | function emscriptenWebGLGet(name_,p,type){if(!p){GL.recordError(1281);re...
  function _glGetIntegerv (line 9) | function _glGetIntegerv(name_,p){emscriptenWebGLGet(name_,p,0)}
  function stringToNewUTF8 (line 9) | function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+...
  function _glGetString (line 9) | function _glGetString(name_){var ret=GL.stringCache[name_];if(!ret){swit...
  function _glGetUniformBlockIndex (line 9) | function _glGetUniformBlockIndex(program,uniformBlockName){return GLctx[...
  function jstoi_q (line 9) | function jstoi_q(str){return parseInt(str)}
  function webglGetLeftBracePos (line 9) | function webglGetLeftBracePos(name){return name.slice(-1)=="]"&&name.las...
  function webglPrepareUniformLocationsBeforeFirstUse (line 9) | function webglPrepareUniformLocationsBeforeFirstUse(program){var uniform...
  function _glGetUniformLocation (line 9) | function _glGetUniformLocation(program,name){name=UTF8ToString(name);if(...
  function _glLinkProgram (line 9) | function _glLinkProgram(program){program=GL.programs[program];GLctx.link...
  function _glPixelStorei (line 9) | function _glPixelStorei(pname,param){if(pname==3317){GL.unpackAlignment=...
  function computeUnpackAlignedImageSize (line 9) | function computeUnpackAlignedImageSize(width,height,sizePerPixel,alignme...
  function __colorChannelsInGlTextureFormat (line 9) | function __colorChannelsInGlTextureFormat(format){var colorChannels={5:3...
  function heapObjectForWebGLType (line 9) | function heapObjectForWebGLType(type){type-=5120;if(type==0)return HEAP8...
  function heapAccessShiftForWebGLHeap (line 9) | function heapAccessShiftForWebGLHeap(heap){return 31-Math.clz32(heap.BYT...
  function emscriptenWebGLGetTexPixelData (line 9) | function emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,...
  function _glReadPixels (line 9) | function _glReadPixels(x,y,width,height,format,type,pixels){if(GL.curren...
  function _glShaderSource (line 9) | function _glShaderSource(shader,count,string,length){var source=GL.getSo...
  function _glTexImage2D (line 9) | function _glTexImage2D(target,level,internalFormat,width,height,border,f...
  function _glTexParameterfv (line 9) | function _glTexParameterfv(target,pname,params){var param=HEAPF32[params...
  function _glTexParameteri (line 9) | function _glTexParameteri(x0,x1,x2){GLctx["texParameteri"](x0,x1,x2)}
  function _glTexStorage2D (line 9) | function _glTexStorage2D(x0,x1,x2,x3,x4){GLctx["texStorage2D"](x0,x1,x2,...
  function _glTexStorage3D (line 9) | function _glTexStorage3D(x0,x1,x2,x3,x4,x5){GLctx["texStorage3D"](x0,x1,...
  function _glTexSubImage2D (line 9) | function _glTexSubImage2D(target,level,xoffset,yoffset,width,height,form...
  function _glTexSubImage3D (line 9) | function _glTexSubImage3D(target,level,xoffset,yoffset,zoffset,width,hei...
  function webglGetUniformLocation (line 9) | function webglGetUniformLocation(location){var p=GLctx.currentProgram;if...
  function _glUniform1f (line 9) | function _glUniform1f(location,v0){GLctx.uniform1f(webglGetUniformLocati...
  function _glUniform1i (line 9) | function _glUniform1i(location,v0){GLctx.uniform1i(webglGetUniformLocati...
  function _glUniform2fv (line 9) | function _glUniform2fv(location,count,value){if(GL.currentContext.versio...
  function _glUniform4fv (line 9) | function _glUniform4fv(location,count,value){if(GL.currentContext.versio...
  function _glUniform4iv (line 9) | function _glUniform4iv(location,count,value){if(GL.currentContext.versio...
  function _glUniformBlockBinding (line 9) | function _glUniformBlockBinding(program,uniformBlockIndex,uniformBlockBi...
  function _glUniformMatrix4fv (line 9) | function _glUniformMatrix4fv(location,count,transpose,value){if(GL.curre...
  function _glUseProgram (line 9) | function _glUseProgram(program){program=GL.programs[program];GLctx.usePr...
  function _glVertexAttribPointer (line 9) | function _glVertexAttribPointer(index,size,type,normalized,stride,ptr){v...
  function _glViewport (line 9) | function _glViewport(x0,x1,x2,x3){GLctx["viewport"](x0,x1,x2,x3)}
  function _gmtime_r (line 9) | function _gmtime_r(time,tmPtr){var date=new Date(HEAP32[time>>2]*1e3);HE...
  function _llvm_eh_typeid_for (line 9) | function _llvm_eh_typeid_for(type){return type}
  function _tzset (line 9) | function _tzset(){if(_tzset.called)return;_tzset.called=true;var current...
  function _localtime_r (line 9) | function _localtime_r(time,tmPtr){_tzset();var date=new Date(HEAP32[time...
  function _mktime (line 9) | function _mktime(tmPtr){_tzset();var date=new Date(HEAP32[tmPtr+20>>2]+1...
  function _proc_exit (line 9) | function _proc_exit(code){procExit(code)}
  function _setTempRet0 (line 9) | function _setTempRet0(val){setTempRet0(val)}
  function __isLeapYear (line 9) | function __isLeapYear(year){return year%4===0&&(year%100!==0||year%400==...
  function __arraySum (line 9) | function __arraySum(array,index){var sum=0;for(var i=0;i<=index;sum+=arr...
  function __addDays (line 9) | function __addDays(date,days){var newDate=new Date(date.getTime());while...
  function _strftime (line 9) | function _strftime(s,maxsize,format,tm){var tm_zone=HEAP32[tm+40>>2];var...
  function _strftime_l (line 9) | function _strftime_l(s,maxsize,format,tm){return _strftime(s,maxsize,for...
  function intArrayFromString (line 9) | function intArrayFromString(stringy,dontAddNull,length){var len=length>0...
  function intArrayFromBase64 (line 9) | function intArrayFromBase64(s){if(typeof ENVIRONMENT_IS_NODE==="boolean"...
  function invoke_viid (line 9) | function invoke_viid(index,a1,a2,a3){var sp=stackSave();try{wasmTable.ge...
  function invoke_vi (line 9) | function invoke_vi(index,a1){var sp=stackSave();try{wasmTable.get(index)...
  function invoke_iii (line 9) | function invoke_iii(index,a1,a2){var sp=stackSave();try{return wasmTable...
  function invoke_viiiii (line 9) | function invoke_viiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{wasm...
  function invoke_iiiiiii (line 9) | function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_v (line 9) | function invoke_v(index){var sp=stackSave();try{wasmTable.get(index)()}c...
  function invoke_viiiiiiiiii (line 9) | function invoke_viiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp...
  function invoke_vii (line 9) | function invoke_vii(index,a1,a2){var sp=stackSave();try{wasmTable.get(in...
  function invoke_ii (line 9) | function invoke_ii(index,a1){var sp=stackSave();try{return wasmTable.get...
  function invoke_viii (line 9) | function invoke_viii(index,a1,a2,a3){var sp=stackSave();try{wasmTable.ge...
  function invoke_viiiiii (line 9) | function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_viiiiiii (line 9) | function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_viiiiiiii (line 9) | function invoke_viiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSav...
  function invoke_viiiiiiiii (line 9) | function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stac...
  function invoke_viiii (line 9) | function invoke_viiii(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTabl...
  function invoke_iiiii (line 9) | function invoke_iiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return w...
  function invoke_viiiiiiiiiii (line 9) | function invoke_viiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){v...
  function invoke_viiidd (line 9) | function invoke_viiidd(index,a1,a2,a3,a4,a5){var sp=stackSave();try{wasm...
  function invoke_iiiiii (line 9) | function invoke_iiiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{retu...
  function invoke_viiiiiiiiiiiii (line 9) | function invoke_viiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,...
  function invoke_iiiiiiii (line 9) | function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_diii (line 9) | function invoke_diii(index,a1,a2,a3){var sp=stackSave();try{return wasmT...
  function invoke_iiii (line 9) | function invoke_iiii(index,a1,a2,a3){var sp=stackSave();try{return wasmT...
  function invoke_i (line 9) | function invoke_i(index){var sp=stackSave();try{return wasmTable.get(ind...
  function invoke_viiidi (line 9) | function invoke_viiidi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{wasm...
  function invoke_viiiidi (line 9) | function invoke_viiiidi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_viididii (line 9) | function invoke_viididii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_iiiiiiiii (line 9) | function invoke_iiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSav...
  function invoke_viiiiiiiidf (line 9) | function invoke_viiiiiiiidf(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp...
  function invoke_viiiiiiiidd (line 9) | function invoke_viiiiiiiidd(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp...
  function invoke_viiiiid (line 9) | function invoke_viiiiid(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_viiiiiid (line 9) | function invoke_viiiiiid(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_viiiiiiiiiiii (line 9) | function invoke_viiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a...
  function invoke_viiiiiiidiiii (line 9) | function invoke_viiiiiiidiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a...
  function invoke_viiiiif (line 9) | function invoke_viiiiif(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_viiiiiif (line 9) | function invoke_viiiiiif(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_viiiiiiifiiii (line 9) | function invoke_viiiiiiifiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a...
  function invoke_viiiifiifiiiiiii (line 9) | function invoke_viiiifiifiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a1...
  function invoke_viiiidiidiiiiiii (line 9) | function invoke_viiiidiidiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a1...
  function invoke_vididdii (line 9) | function invoke_vididdii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_viiid (line 9) | function invoke_viiid(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTabl...
  function invoke_vidii (line 9) | function invoke_vidii(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTabl...
  function invoke_viiiiiiiiiiddi (line 9) | function invoke_viiiiiiiiiiddi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,...
  function invoke_viiiiiiiddi (line 9) | function invoke_viiiiiiiddi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp...
  function invoke_iiiiiiiddi (line 9) | function invoke_iiiiiiiddi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stac...
  function invoke_viiiddi (line 9) | function invoke_viiiddi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_viiiid (line 9) | function invoke_viiiid(index,a1,a2,a3,a4,a5){var sp=stackSave();try{wasm...
  function invoke_viiiidid (line 9) | function invoke_viiiidid(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_viidi (line 9) | function invoke_viidi(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTabl...
  function invoke_vdiii (line 9) | function invoke_vdiii(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTabl...
  function ExitStatus (line 9) | function ExitStatus(status){this.name="ExitStatus";this.message="Program...
  function stackCheckInit (line 9) | function stackCheckInit(){_emscripten_stack_init();writeStackCookie()}
  function run (line 9) | function run(args){args=args||arguments_;if(runDependencies>0){return}st...
  function checkUnflushedContent (line 9) | function checkUnflushedContent(){var oldOut=out;var oldErr=err;var has=f...
  function exit (line 9) | function exit(status,implicit){EXITSTATUS=status;checkUnflushedContent()...
  function procExit (line 9) | function procExit(code){EXITSTATUS=code;if(!keepRuntimeAlive()){if(Modul...

FILE: src/renderer/public/lib/@mediapipe/face_mesh/face_mesh_solution_wasm_bin.js
  function locateFile (line 9) | function locateFile(path){if(Module["locateFile"]){return Module["locate...
  function warnOnce (line 9) | function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnc...
  function convertJsFunctionToWasm (line 9) | function convertJsFunctionToWasm(func,sig){if(typeof WebAssembly.Functio...
  function getEmptyTableSlot (line 9) | function getEmptyTableSlot(){if(freeTableIndexes.length){return freeTabl...
  function addFunctionWasm (line 9) | function addFunctionWasm(func,sig){if(!functionsInTableMap){functionsInT...
  function assert (line 9) | function assert(condition,text){if(!condition){abort("Assertion failed: ...
  function getCFunc (line 9) | function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot ...
  function ccall (line 9) | function ccall(ident,returnType,argTypes,args,opts){var toC={"string":fu...
  function UTF8ArrayToString (line 9) | function UTF8ArrayToString(heap,idx,maxBytesToRead){var endIdx=idx+maxBy...
  function UTF8ToString (line 9) | function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(H...
  function stringToUTF8Array (line 9) | function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxByte...
  function stringToUTF8 (line 9) | function stringToUTF8(str,outPtr,maxBytesToWrite){assert(typeof maxBytes...
  function lengthBytesUTF8 (line 9) | function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){va...
  function UTF16ToString (line 9) | function UTF16ToString(ptr,maxBytesToRead){assert(ptr%2==0,"Pointer pass...
  function stringToUTF16 (line 9) | function stringToUTF16(str,outPtr,maxBytesToWrite){assert(outPtr%2==0,"P...
  function lengthBytesUTF16 (line 9) | function lengthBytesUTF16(str){return str.length*2}
  function UTF32ToString (line 9) | function UTF32ToString(ptr,maxBytesToRead){assert(ptr%4==0,"Pointer pass...
  function stringToUTF32 (line 9) | function stringToUTF32(str,outPtr,maxBytesToWrite){assert(outPtr%4==0,"P...
  function lengthBytesUTF32 (line 9) | function lengthBytesUTF32(str){var len=0;for(var i=0;i<str.length;++i){v...
  function allocateUTF8 (line 9) | function allocateUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_mall...
  function writeArrayToMemory (line 9) | function writeArrayToMemory(array,buffer){assert(array.length>=0,"writeA...
  function writeAsciiToMemory (line 9) | function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i<str.le...
  function alignUp (line 9) | function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}ret...
  function updateGlobalBufferAndViews (line 9) | function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP...
  function writeStackCookie (line 9) | function writeStackCookie(){var max=_emscripten_stack_get_end();assert((...
  function checkStackCookie (line 9) | function checkStackCookie(){if(ABORT)return;var max=_emscripten_stack_ge...
  function keepRuntimeAlive (line 9) | function keepRuntimeAlive(){return noExitRuntime||runtimeKeepaliveCounte...
  function preRun (line 9) | function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="func...
  function initRuntime (line 9) | function initRuntime(){checkStackCookie();assert(!runtimeInitialized);ru...
  function exitRuntime (line 9) | function exitRuntime(){checkStackCookie();runtimeExited=true}
  function postRun (line 9) | function postRun(){checkStackCookie();if(Module["postRun"]){if(typeof Mo...
  function addOnPreRun (line 9) | function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}
  function addOnInit (line 9) | function addOnInit(cb){__ATINIT__.unshift(cb)}
  function addOnPostRun (line 9) | function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}
  function getUniqueRunDependency (line 9) | function getUniqueRunDependency(id){var orig=id;while(1){if(!runDependen...
  function addRunDependency (line 9) | function addRunDependency(id){runDependencies++;if(Module["monitorRunDep...
  function removeRunDependency (line 9) | function removeRunDependency(id){runDependencies--;if(Module["monitorRun...
  function abort (line 9) | function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+...
  function isDataURI (line 9) | function isDataURI(filename){return filename.startsWith(dataURIPrefix)}
  function isFileURI (line 9) | function isFileURI(filename){return filename.startsWith("file://")}
  function createExportWrapper (line 9) | function createExportWrapper(name,fixedasm){return function(){var displa...
  function getBinary (line 9) | function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return...
  function getBinaryPromise (line 9) | function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRON...
  function createWasm (line 9) | function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_previ...
  function HaveOffsetConverter (line 9) | function HaveOffsetConverter(){return typeof wasmOffsetConverter!=="unde...
  function _emscripten_set_main_loop_timing (line 9) | function _emscripten_set_main_loop_timing(mode,value){Browser.mainLoop.t...
  function _emscripten_webgl_do_commit_frame (line 9) | function _emscripten_webgl_do_commit_frame(){if(!GL.currentContext||!GL....
  function _exit (line 9) | function _exit(status){exit(status)}
  function maybeExit (line 9) | function maybeExit(){if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch...
  function setMainLoop (line 9) | function setMainLoop(browserIterationFunc,fps,simulateInfiniteLoop,arg,n...
  function callUserCallback (line 9) | function callUserCallback(func,synchronous){if(ABORT){err("user callback...
  function safeSetTimeout (line 9) | function safeSetTimeout(func,timeout){return setTimeout(function(){callU...
  function finish (line 9) | function finish(audio){if(done)return;done=true;Module["preloadedAudios"...
  function fail (line 9) | function fail(){if(done)return;done=true;Module["preloadedAudios"][name]...
  function encode64 (line 9) | function encode64(data){var BASE="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkl...
  function pointerLockChange (line 9) | function pointerLockChange(){Browser.pointerLock=document["pointerLockEl...
  function fullscreenChange (line 9) | function fullscreenChange(){Browser.isFullscreen=false;var canvasContain...
  function callRuntimeCallbacks (line 9) | function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var c...
  function demangle (line 9) | function demangle(func){warnOnce("warning: build with  -s DEMANGLE_SUPPO...
  function demangleAll (line 9) | function demangleAll(text){var regex=/\b_Z[\w\d_]+/g;return text.replace...
  function jsStackTrace (line 9) | function jsStackTrace(){var error=new Error;if(!error.stack){try{throw n...
  function stackTrace (line 9) | function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"]...
  function ___cxa_allocate_exception (line 9) | function ___cxa_allocate_exception(size){return _malloc(size+16)+16}
  function _atexit (line 9) | function _atexit(func,arg){}
  function ___cxa_atexit (line 9) | function ___cxa_atexit(a0,a1){return _atexit(a0,a1)}
  function ExceptionInfo (line 9) | function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-16;thi...
  function CatchInfo (line 9) | function CatchInfo(ptr){this.free=function(){_free(this.ptr);this.ptr=0}...
  function exception_addRef (line 9) | function exception_addRef(info){info.add_ref()}
  function ___cxa_begin_catch (line 9) | function ___cxa_begin_catch(ptr){var catchInfo=new CatchInfo(ptr);var in...
  function ___cxa_free_exception (line 9) | function ___cxa_free_exception(ptr){try{return _free(new ExceptionInfo(p...
  function exception_decRef (line 9) | function exception_decRef(info){if(info.release_ref()&&!info.get_rethrow...
  function ___cxa_end_catch (line 9) | function ___cxa_end_catch(){_setThrew(0);assert(exceptionCaught.length>0...
  function ___resumeException (line 9) | function ___resumeException(catchInfoPtr){var catchInfo=new CatchInfo(ca...
  function ___cxa_find_matching_catch_2 (line 9) | function ___cxa_find_matching_catch_2(){var thrown=exceptionLast;if(!thr...
  function ___cxa_find_matching_catch_3 (line 9) | function ___cxa_find_matching_catch_3(){var thrown=exceptionLast;if(!thr...
  function ___cxa_rethrow (line 9) | function ___cxa_rethrow(){var catchInfo=exceptionCaught.pop();if(!catchI...
  function ___cxa_thread_atexit (line 9) | function ___cxa_thread_atexit(a0,a1){return _atexit(a0,a1)}
  function ___cxa_throw (line 9) | function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(pt...
  function setErrNo (line 9) | function setErrNo(value){HEAP32[___errno_location()>>2]=value;return value}
  function getRandomDevice (line 9) | function getRandomDevice(){if(typeof crypto==="object"&&typeof crypto["g...
  function trim (line 9) | function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[sta...
  function zeroMemory (line 9) | function zeroMemory(address,size){HEAPU8.fill(0,address,address+size)}
  function alignMemory (line 9) | function alignMemory(size,alignment){assert(alignment,"alignment argumen...
  function mmapAlloc (line 9) | function mmapAlloc(size){size=alignMemory(size,65536);var ptr=_memalign(...
  function asyncLoad (line 9) | function asyncLoad(url,onload,onerror,noRunDep){var dep=!noRunDep?getUni...
  function doCallback (line 9) | function doCallback(errCode){assert(FS.syncFSRequests>0);FS.syncFSReques...
  function done (line 9) | function done(errCode){if(errCode){if(!done.errored){done.errored=true;r...
  function LazyUint8Array (line 9) | function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}
  function processData (line 9) | function processData(byteArray){function finish(byteArray){if(preFinish)...
  function finish (line 9) | function finish(){if(fail==0)onload();else onerror()}
  function finish (line 9) | function finish(){if(fail==0)onload();else onerror()}
  function ___sys_fcntl64 (line 9) | function ___sys_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var...
  function ___sys_ioctl (line 9) | function ___sys_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var st...
  function syscallMmap2 (line 9) | function syscallMmap2(addr,len,prot,flags,fd,off){off<<=12;var ptr;var a...
  function ___sys_mmap2 (line 9) | function ___sys_mmap2(addr,len,prot,flags,fd,off){try{return syscallMmap...
  function ___sys_open (line 9) | function ___sys_open(path,flags,varargs){SYSCALLS.varargs=varargs;try{va...
  function ___sys_stat64 (line 9) | function ___sys_stat64(path,buf){try{path=SYSCALLS.getStr(path);return S...
  function makeLegalFunctionName (line 9) | function makeLegalFunctionName(name){if(undefined===name){return"_unknow...
  function createNamedFunction (line 9) | function createNamedFunction(name,body){name=makeLegalFunctionName(name)...
  function count_emval_handles (line 9) | function count_emval_handles(){var count=0;for(var i=5;i<emval_handle_ar...
  function get_first_emval (line 9) | function get_first_emval(){for(var i=5;i<emval_handle_array.length;++i){...
  function init_emval (line 9) | function init_emval(){Module["count_emval_handles"]=count_emval_handles;...
  function __emval_register (line 9) | function __emval_register(value){switch(value){case undefined:{return 1}...
  function extendError (line 9) | function extendError(baseErrorType,errorName){var errorClass=createNamed...
  function embind_init_charCodes (line 9) | function embind_init_charCodes(){var codes=new Array(256);for(var i=0;i<...
  function readLatin1String (line 9) | function readLatin1String(ptr){var ret="";var c=ptr;while(HEAPU8[c]){ret...
  function getInheritedInstanceCount (line 9) | function getInheritedInstanceCount(){return Object.keys(registeredInstan...
  function getLiveInheritedInstances (line 9) | function getLiveInheritedInstances(){var rv=[];for(var k in registeredIn...
  function flushPendingDeletes (line 9) | function flushPendingDeletes(){while(deletionQueue.length){var obj=delet...
  function setDelayFunction (line 9) | function setDelayFunction(fn){delayFunction=fn;if(deletionQueue.length&&...
  function init_embind (line 9) | function init_embind(){Module["getInheritedInstanceCount"]=getInheritedI...
  function throwBindingError (line 9) | function throwBindingError(message){throw new BindingError(message)}
  function getBasestPointer (line 9) | function getBasestPointer(class_,ptr){if(ptr===undefined){throwBindingEr...
  function registerInheritedInstance (line 9) | function registerInheritedInstance(class_,ptr,instance){ptr=getBasestPoi...
  function requireHandle (line 9) | function requireHandle(handle){if(!handle){throwBindingError("Cannot use...
  function getTypeName (line 9) | function getTypeName(type){var ptr=___getTypeName(type);var rv=readLatin...
  function requireRegisteredType (line 9) | function requireRegisteredType(rawType,humanName){var impl=registeredTyp...
  function unregisterInheritedInstance (line 9) | function unregisterInheritedInstance(class_,ptr){ptr=getBasestPointer(cl...
  function detachFinalizer (line 9) | function detachFinalizer(handle){}
  function runDestructor (line 9) | function runDestructor($$){if($$.smartPtr){$$.smartPtrType.rawDestructor...
  function releaseClassHandle (line 9) | function releaseClassHandle($$){$$.count.value-=1;var toDelete=0===$$.co...
  function attachFinalizer (line 9) | function attachFinalizer(handle){if("undefined"===typeof FinalizationGro...
  function __embind_create_inheriting_constructor (line 9) | function __embind_create_inheriting_constructor(constructorName,wrapperT...
  function runDestructors (line 9) | function runDestructors(destructors){while(destructors.length){var ptr=d...
  function simpleReadValueFromPointer (line 9) | function simpleReadValueFromPointer(pointer){return this["fromWireType"]...
  function throwInternalError (line 9) | function throwInternalError(message){throw new InternalError(message)}
  function whenDependentTypesAreResolved (line 9) | function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeCon...
  function __embind_finalize_value_object (line 9) | function __embind_finalize_value_object(structType){var reg=structRegist...
  function __embind_register_bigint (line 9) | function __embind_register_bigint(primitiveType,name,size,minRange,maxRa...
  function getShiftFromSize (line 9) | function getShiftFromSize(size){switch(size){case 1:return 0;case 2:retu...
  function registerType (line 9) | function registerType(rawType,registeredInstance,options){options=option...
  function __embind_register_bool (line 9) | function __embind_register_bool(rawType,name,size,trueValue,falseValue){...
  function ClassHandle_isAliasOf (line 9) | function ClassHandle_isAliasOf(other){if(!(this instanceof ClassHandle))...
  function shallowCopyInternalPointer (line 9) | function shallowCopyInternalPointer(o){return{count:o.count,deleteSchedu...
  function throwInstanceAlreadyDeleted (line 9) | function throwInstanceAlreadyDeleted(obj){function getInstanceTypeName(h...
  function ClassHandle_clone (line 9) | function ClassHandle_clone(){if(!this.$$.ptr){throwInstanceAlreadyDelete...
  function ClassHandle_delete (line 9) | function ClassHandle_delete(){if(!this.$$.ptr){throwInstanceAlreadyDelet...
  function ClassHandle_isDeleted (line 9) | function ClassHandle_isDeleted(){return!this.$$.ptr}
  function ClassHandle_deleteLater (line 9) | function ClassHandle_deleteLater(){if(!this.$$.ptr){throwInstanceAlready...
  function init_ClassHandle (line 9) | function init_ClassHandle(){ClassHandle.prototype["isAliasOf"]=ClassHand...
  function ClassHandle (line 9) | function ClassHandle(){}
  function ensureOverloadTable (line 9) | function ensureOverloadTable(proto,methodName,humanName){if(undefined===...
  function exposePublicSymbol (line 9) | function exposePublicSymbol(name,value,numArguments){if(Module.hasOwnPro...
  function RegisteredClass (line 9) | function RegisteredClass(name,constructor,instancePrototype,rawDestructo...
  function upcastPointer (line 9) | function upcastPointer(ptr,ptrClass,desiredClass){while(ptrClass!==desir...
  function constNoSmartPtrRawPointerToWireType (line 9) | function constNoSmartPtrRawPointerToWireType(destructors,handle){if(hand...
  function genericPointerToWireType (line 9) | function genericPointerToWireType(destructors,handle){var ptr;if(handle=...
  function nonConstNoSmartPtrRawPointerToWireType (line 9) | function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(h...
  function RegisteredPointer_getPointee (line 9) | function RegisteredPointer_getPointee(ptr){if(this.rawGetPointee){ptr=th...
  function RegisteredPointer_destructor (line 9) | function RegisteredPointer_destructor(ptr){if(this.rawDestructor){this.r...
  function RegisteredPointer_deleteObject (line 9) | function RegisteredPointer_deleteObject(handle){if(handle!==null){handle...
  function downcastPointer (line 9) | function downcastPointer(ptr,ptrClass,desiredClass){if(ptrClass===desire...
  function getInheritedInstance (line 9) | function getInheritedInstance(class_,ptr){ptr=getBasestPointer(class_,pt...
  function makeClassHandle (line 9) | function makeClassHandle(prototype,record){if(!record.ptrType||!record.p...
  function RegisteredPointer_fromWireType (line 9) | function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPoin...
  function init_RegisteredPointer (line 9) | function init_RegisteredPointer(){RegisteredPointer.prototype.getPointee...
  function RegisteredPointer (line 9) | function RegisteredPointer(name,registeredClass,isReference,isConst,isSm...
  function replacePublicSymbol (line 9) | function replacePublicSymbol(name,value,numArguments){if(!Module.hasOwnP...
  function dynCallLegacy (line 9) | function dynCallLegacy(sig,ptr,args){assert("dynCall_"+sig in Module,"ba...
  function dynCall (line 9) | function dynCall(sig,ptr,args){if(sig.includes("j")){return dynCallLegac...
  function getDynCaller (line 9) | function getDynCaller(sig,ptr){assert(sig.includes("j"),"getDynCaller sh...
  function embind__requireFunction (line 9) | function embind__requireFunction(signature,rawFunction){signature=readLa...
  function throwUnboundTypeError (line 9) | function throwUnboundTypeError(message,types){var unboundTypes=[];var se...
  function __embind_register_class (line 9) | function __embind_register_class(rawType,rawPointerType,rawConstPointerT...
  function new_ (line 9) | function new_(constructor,argumentList){if(!(constructor instanceof Func...
  function craftInvokerFunction (line 9) | function craftInvokerFunction(humanName,argTypes,classType,cppInvokerFun...
  function heap32VectorToArray (line 9) | function heap32VectorToArray(count,firstElement){var array=[];for(var i=...
  function __embind_register_class_class_function (line 9) | function __embind_register_class_class_function(rawClassType,methodName,...
  function __embind_register_class_constructor (line 9) | function __embind_register_class_constructor(rawClassType,argCount,rawAr...
  function __embind_register_class_function (line 9) | function __embind_register_class_function(rawClassType,methodName,argCou...
  function validateThis (line 9) | function validateThis(this_,classType,humanName){if(!(this_ instanceof O...
  function __embind_register_class_property (line 9) | function __embind_register_class_property(classType,fieldName,getterRetu...
  function __emval_decref (line 9) | function __emval_decref(handle){if(handle>4&&0===--emval_handle_array[ha...
  function __embind_register_emval (line 9) | function __embind_register_emval(rawType,name){name=readLatin1String(nam...
  function _embind_repr (line 9) | function _embind_repr(v){if(v===null){return"null"}var t=typeof v;if(t==...
  function floatReadValueFromPointer (line 9) | function floatReadValueFromPointer(name,shift){switch(shift){case 2:retu...
  function __embind_register_float (line 9) | function __embind_register_float(rawType,name,size){var shift=getShiftFr...
  function __embind_register_function (line 9) | function __embind_register_function(name,argCount,rawArgTypesAddr,signat...
  function integerReadValueFromPointer (line 9) | function integerReadValueFromPointer(name,shift,signed){switch(shift){ca...
  function __embind_register_integer (line 9) | function __embind_register_integer(primitiveType,name,size,minRange,maxR...
  function __embind_register_memory_view (line 9) | function __embind_register_memory_view(rawType,dataTypeIndex,name){var t...
  function __embind_register_std_string (line 9) | function __embind_register_std_string(rawType,name){name=readLatin1Strin...
  function __embind_register_std_wstring (line 9) | function __embind_register_std_wstring(rawType,charSize,name){name=readL...
  function __embind_register_value_object (line 9) | function __embind_register_value_object(rawType,name,constructorSignatur...
  function __embind_register_value_object_field (line 9) | function __embind_register_value_object_field(structType,fieldName,gette...
  function __embind_register_void (line 9) | function __embind_register_void(rawType,name){name=readLatin1String(name...
  function getStringOrSymbol (line 9) | function getStringOrSymbol(address){var symbol=emval_symbols[address];if...
  function __emval_call_void_method (line 9) | function __emval_call_void_method(caller,handle,methodName,args){caller=...
  function __emval_addMethodCaller (line 9) | function __emval_addMethodCaller(caller){var id=emval_methodCallers.leng...
  function __emval_lookupTypes (line 9) | function __emval_lookupTypes(argCount,argTypes){var a=new Array(argCount...
  function __emval_get_method_caller (line 9) | function __emval_get_method_caller(argCount,argTypes){var types=__emval_...
  function __emval_incref (line 9) | function __emval_incref(handle){if(handle>4){emval_handle_array[handle]....
  function __emval_take_value (line 9) | function __emval_take_value(type,argv){type=requireRegisteredType(type,"...
  function _abort (line 9) | function _abort(){abort()}
  function _clock_gettime (line 9) | function _clock_gettime(clk_id,tp){var now;if(clk_id===0){now=Date.now()...
  function _dlopen (line 9) | function _dlopen(filename,flag){abort("To use dlopen, you need to use Em...
  function _dlsym (line 9) | function _dlsym(handle,symbol){abort("To use dlopen, you need to use Ems...
  function readAsmConstArgs (line 9) | function readAsmConstArgs(sigPtr,buf){assert(Array.isArray(readAsmConstA...
  function _emscripten_asm_const_int (line 9) | function _emscripten_asm_const_int(code,sigPtr,argbuf){var args=readAsmC...
  function _emscripten_get_heap_max (line 9) | function _emscripten_get_heap_max(){return 2147483648}
  function _emscripten_memcpy_big (line 9) | function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src...
  function _emscripten_pc_get_function (line 9) | function _emscripten_pc_get_function(pc){abort("Cannot use emscripten_pc...
  function emscripten_realloc_buffer (line 9) | function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer...
  function _emscripten_resize_heap (line 9) | function _emscripten_resize_heap(requestedSize){var oldSize=HEAPU8.lengt...
  function _emscripten_generate_pc (line 9) | function _emscripten_generate_pc(frame){abort("Cannot use emscripten_gen...
  function __emscripten_save_in_unwind_cache (line 9) | function __emscripten_save_in_unwind_cache(callstack){callstack.forEach(...
  function _emscripten_stack_snapshot (line 9) | function _emscripten_stack_snapshot(){var callstack=(new Error).stack.sp...
  function _emscripten_stack_unwind_buffer (line 9) | function _emscripten_stack_unwind_buffer(addr,buffer,count){var stack;if...
  function _emscripten_thread_sleep (line 9) | function _emscripten_thread_sleep(msecs){var start=_emscripten_get_now()...
  function __webgl_enable_ANGLE_instanced_arrays (line 9) | function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExten...
  function __webgl_enable_OES_vertex_array_object (line 9) | function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExte...
  function __webgl_enable_WEBGL_draw_buffers (line 9) | function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension...
  function __webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance (line 9) | function __webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(c...
  function __webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance (line 9) | function __webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_inst...
  function __webgl_enable_WEBGL_multi_draw (line 9) | function __webgl_enable_WEBGL_multi_draw(ctx){return!!(ctx.multiDrawWebg...
  function draw (line 9) | function draw(){gl.vertexAttribPointer(context.blitPosLoc,2,5126,false,0...
  function arraysHaveEqualContent (line 9) | function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)r...
  function findEventTarget (line 9) | function findEventTarget(target){warnOnce("Rules for selecting event tar...
  function findCanvasEventTarget (line 9) | function findCanvasEventTarget(target){if(typeof target==="number")targe...
  function _emscripten_webgl_do_create_context (line 9) | function _emscripten_webgl_do_create_context(target,attributes){assert(a...
  function _emscripten_webgl_create_context (line 9) | function _emscripten_webgl_create_context(a0,a1){return _emscripten_webg...
  function _emscripten_webgl_do_get_current_context (line 9) | function _emscripten_webgl_do_get_current_context(){return GL.currentCon...
  function _emscripten_webgl_get_current_context (line 9) | function _emscripten_webgl_get_current_context(){return _emscripten_webg...
  function _emscripten_webgl_make_context_current (line 9) | function _emscripten_webgl_make_context_current(contextHandle){var succe...
  function _emscripten_webgl_destroy_context (line 9) | function _emscripten_webgl_destroy_context(contextHandle){if(GL.currentC...
  function _emscripten_webgl_get_context_attributes (line 9) | function _emscripten_webgl_get_context_attributes(c,a){if(!a)return-5;c=...
  function _emscripten_webgl_init_context_attributes (line 9) | function _emscripten_webgl_init_context_attributes(attributes){assert(at...
  function getExecutableName (line 9) | function getExecutableName(){return thisProgram||"./this.program"}
  function getEnvStrings (line 9) | function getEnvStrings(){if(!getEnvStrings.strings){var lang=(typeof nav...
  function _environ_get (line 9) | function _environ_get(__environ,environ_buf){var bufSize=0;getEnvStrings...
  function _environ_sizes_get (line 9) | function _environ_sizes_get(penviron_count,penviron_buf_size){var string...
  function _fd_close (line 9) | function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.cl...
  function _fd_read (line 9) | function _fd_read(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamF...
  function _fd_seek (line 9) | function _fd_seek(fd,offset_low,offset_high,whence,newOffset){try{var st...
  function _fd_write (line 9) | function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStream...
  function _getTempRet0 (line 9) | function _getTempRet0(){return getTempRet0()}
  function _getentropy (line 9) | function _getentropy(buffer,size){if(!_getentropy.randomDevice){_getentr...
  function _glActiveTexture (line 9) | function _glActiveTexture(x0){GLctx["activeTexture"](x0)}
  function _glAttachShader (line 9) | function _glAttachShader(program,shader){GLctx.attachShader(GL.programs[...
  function _glBindAttribLocation (line 9) | function _glBindAttribLocation(program,index,name){GLctx.bindAttribLocat...
  function _glBindBuffer (line 9) | function _glBindBuffer(target,buffer){if(target==34962){GLctx.currentArr...
  function _glBindBufferBase (line 9) | function _glBindBufferBase(target,index,buffer){GLctx["bindBufferBase"](...
  function _glBindFramebuffer (line 9) | function _glBindFramebuffer(target,framebuffer){GLctx.bindFramebuffer(ta...
  function _glBindTexture (line 9) | function _glBindTexture(target,texture){GLctx.bindTexture(target,GL.text...
  function _glBindVertexArray (line 9) | function _glBindVertexArray(vao){GLctx["bindVertexArray"](GL.vaos[vao]);...
  function _glBufferData (line 9) | function _glBufferData(target,size,data,usage){if(GL.currentContext.vers...
  function convertI32PairToI53 (line 9) | function convertI32PairToI53(lo,hi){assert(hi===(hi|0));return(lo>>>0)+h...
  function _glClientWaitSync (line 9) | function _glClientWaitSync(sync,flags,timeoutLo,timeoutHi){return GLctx....
  function _glCompileShader (line 9) | function _glCompileShader(shader){GLctx.compileShader(GL.shaders[shader])}
  function _glCreateProgram (line 9) | function _glCreateProgram(){var id=GL.getNewId(GL.programs);var program=...
  function _glCreateShader (line 9) | function _glCreateShader(shaderType){var id=GL.getNewId(GL.shaders);GL.s...
  function _glDeleteBuffers (line 9) | function _glDeleteBuffers(n,buffers){for(var i=0;i<n;i++){var id=HEAP32[...
  function _glDeleteFramebuffers (line 9) | function _glDeleteFramebuffers(n,framebuffers){for(var i=0;i<n;++i){var ...
  function _glDeleteProgram (line 9) | function _glDeleteProgram(id){if(!id)return;var program=GL.programs[id];...
  function _glDeleteShader (line 9) | function _glDeleteShader(id){if(!id)return;var shader=GL.shaders[id];if(...
  function _glDeleteSync (line 9) | function _glDeleteSync(id){if(!id)return;var sync=GL.syncs[id];if(!sync)...
  function _glDeleteTextures (line 9) | function _glDeleteTextures(n,textures){for(var i=0;i<n;i++){var id=HEAP3...
  function _glDeleteVertexArrays (line 9) | function _glDeleteVertexArrays(n,vaos){for(var i=0;i<n;i++){var id=HEAP3...
  function _glDisable (line 9) | function _glDisable(x0){GLctx["disable"](x0)}
  function _glDisableVertexAttribArray (line 9) | function _glDisableVertexAttribArray(index){var cb=GL.currentContext.cli...
  function _glDrawArrays (line 9) | function _glDrawArrays(mode,first,count){GL.preDrawHandleClientVertexAtt...
  function _glDrawBuffers (line 9) | function _glDrawBuffers(n,bufs){var bufArray=tempFixedLengthArray[n];for...
  function _glEnableVertexAttribArray (line 9) | function _glEnableVertexAttribArray(index){var cb=GL.currentContext.clie...
  function _glFenceSync (line 9) | function _glFenceSync(condition,flags){var sync=GLctx.fenceSync(conditio...
  function _glFinish (line 9) | function _glFinish(){GLctx["finish"]()}
  function _glFlush (line 9) | function _glFlush(){GLctx["flush"]()}
  function _glFramebufferTexture2D (line 9) | function _glFramebufferTexture2D(target,attachment,textarget,texture,lev...
  function _glFramebufferTextureLayer (line 9) | function _glFramebufferTextureLayer(target,attachment,texture,level,laye...
  function __glGenObject (line 9) | function __glGenObject(n,buffers,createFunction,objectTable){for(var i=0...
  function _glGenBuffers (line 9) | function _glGenBuffers(n,buffers){__glGenObject(n,buffers,"createBuffer"...
  function _glGenFramebuffers (line 9) | function _glGenFramebuffers(n,ids){__glGenObject(n,ids,"createFramebuffe...
  function _glGenTextures (line 9) | function _glGenTextures(n,textures){__glGenObject(n,textures,"createText...
  function _glGenVertexArrays (line 9) | function _glGenVertexArrays(n,arrays){__glGenObject(n,arrays,"createVert...
  function _glGetAttribLocation (line 9) | function _glGetAttribLocation(program,name){return GLctx.getAttribLocati...
  function _glGetError (line 9) | function _glGetError(){var error=GLctx.getError()||GL.lastError;GL.lastE...
  function readI53FromI64 (line 9) | function readI53FromI64(ptr){return HEAPU32[ptr>>2]+HEAP32[ptr+4>>2]*429...
  function readI53FromU64 (line 9) | function readI53FromU64(ptr){return HEAPU32[ptr>>2]+HEAPU32[ptr+4>>2]*42...
  function writeI53ToI64 (line 9) | function writeI53ToI64(ptr,num){HEAPU32[ptr>>2]=num;HEAPU32[ptr+4>>2]=(n...
  function emscriptenWebGLGet (line 9) | function emscriptenWebGLGet(name_,p,type){if(!p){GL.recordError(1281);re...
  function _glGetIntegerv (line 9) | function _glGetIntegerv(name_,p){emscriptenWebGLGet(name_,p,0)}
  function stringToNewUTF8 (line 9) | function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+...
  function _glGetString (line 9) | function _glGetString(name_){var ret=GL.stringCache[name_];if(!ret){swit...
  function _glGetUniformBlockIndex (line 9) | function _glGetUniformBlockIndex(program,uniformBlockName){return GLctx[...
  function jstoi_q (line 9) | function jstoi_q(str){return parseInt(str)}
  function webglGetLeftBracePos (line 9) | function webglGetLeftBracePos(name){return name.slice(-1)=="]"&&name.las...
  function webglPrepareUniformLocationsBeforeFirstUse (line 9) | function webglPrepareUniformLocationsBeforeFirstUse(program){var uniform...
  function _glGetUniformLocation (line 9) | function _glGetUniformLocation(program,name){name=UTF8ToString(name);if(...
  function _glLinkProgram (line 9) | function _glLinkProgram(program){program=GL.programs[program];GLctx.link...
  function _glPixelStorei (line 9) | function _glPixelStorei(pname,param){if(pname==3317){GL.unpackAlignment=...
  function computeUnpackAlignedImageSize (line 9) | function computeUnpackAlignedImageSize(width,height,sizePerPixel,alignme...
  function __colorChannelsInGlTextureFormat (line 9) | function __colorChannelsInGlTextureFormat(format){var colorChannels={5:3...
  function heapObjectForWebGLType (line 9) | function heapObjectForWebGLType(type){type-=5120;if(type==0)return HEAP8...
  function heapAccessShiftForWebGLHeap (line 9) | function heapAccessShiftForWebGLHeap(heap){return 31-Math.clz32(heap.BYT...
  function emscriptenWebGLGetTexPixelData (line 9) | function emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,...
  function _glReadPixels (line 9) | function _glReadPixels(x,y,width,height,format,type,pixels){if(GL.curren...
  function _glShaderSource (line 9) | function _glShaderSource(shader,count,string,length){var source=GL.getSo...
  function _glTexImage2D (line 9) | function _glTexImage2D(target,level,internalFormat,width,height,border,f...
  function _glTexParameterfv (line 9) | function _glTexParameterfv(target,pname,params){var param=HEAPF32[params...
  function _glTexParameteri (line 9) | function _glTexParameteri(x0,x1,x2){GLctx["texParameteri"](x0,x1,x2)}
  function _glTexStorage2D (line 9) | function _glTexStorage2D(x0,x1,x2,x3,x4){GLctx["texStorage2D"](x0,x1,x2,...
  function _glTexStorage3D (line 9) | function _glTexStorage3D(x0,x1,x2,x3,x4,x5){GLctx["texStorage3D"](x0,x1,...
  function _glTexSubImage2D (line 9) | function _glTexSubImage2D(target,level,xoffset,yoffset,width,height,form...
  function _glTexSubImage3D (line 9) | function _glTexSubImage3D(target,level,xoffset,yoffset,zoffset,width,hei...
  function webglGetUniformLocation (line 9) | function webglGetUniformLocation(location){var p=GLctx.currentProgram;if...
  function _glUniform1f (line 9) | function _glUniform1f(location,v0){GLctx.uniform1f(webglGetUniformLocati...
  function _glUniform1i (line 9) | function _glUniform1i(location,v0){GLctx.uniform1i(webglGetUniformLocati...
  function _glUniform2fv (line 9) | function _glUniform2fv(location,count,value){if(GL.currentContext.versio...
  function _glUniform4fv (line 9) | function _glUniform4fv(location,count,value){if(GL.currentContext.versio...
  function _glUniform4iv (line 9) | function _glUniform4iv(location,count,value){if(GL.currentContext.versio...
  function _glUniformBlockBinding (line 9) | function _glUniformBlockBinding(program,uniformBlockIndex,uniformBlockBi...
  function _glUniformMatrix4fv (line 9) | function _glUniformMatrix4fv(location,count,transpose,value){if(GL.curre...
  function _glUseProgram (line 9) | function _glUseProgram(program){program=GL.programs[program];GLctx.usePr...
  function _glVertexAttribPointer (line 9) | function _glVertexAttribPointer(index,size,type,normalized,stride,ptr){v...
  function _glViewport (line 9) | function _glViewport(x0,x1,x2,x3){GLctx["viewport"](x0,x1,x2,x3)}
  function _gmtime_r (line 9) | function _gmtime_r(time,tmPtr){var date=new Date(HEAP32[time>>2]*1e3);HE...
  function _llvm_eh_typeid_for (line 9) | function _llvm_eh_typeid_for(type){return type}
  function _tzset (line 9) | function _tzset(){if(_tzset.called)return;_tzset.called=true;var current...
  function _localtime_r (line 9) | function _localtime_r(time,tmPtr){_tzset();var date=new Date(HEAP32[time...
  function _mktime (line 9) | function _mktime(tmPtr){_tzset();var date=new Date(HEAP32[tmPtr+20>>2]+1...
  function _proc_exit (line 9) | function _proc_exit(code){procExit(code)}
  function _setTempRet0 (line 9) | function _setTempRet0(val){setTempRet0(val)}
  function __isLeapYear (line 9) | function __isLeapYear(year){return year%4===0&&(year%100!==0||year%400==...
  function __arraySum (line 9) | function __arraySum(array,index){var sum=0;for(var i=0;i<=index;sum+=arr...
  function __addDays (line 9) | function __addDays(date,days){var newDate=new Date(date.getTime());while...
  function _strftime (line 9) | function _strftime(s,maxsize,format,tm){var tm_zone=HEAP32[tm+40>>2];var...
  function _strftime_l (line 9) | function _strftime_l(s,maxsize,format,tm){return _strftime(s,maxsize,for...
  function intArrayFromString (line 9) | function intArrayFromString(stringy,dontAddNull,length){var len=length>0...
  function intArrayFromBase64 (line 9) | function intArrayFromBase64(s){if(typeof ENVIRONMENT_IS_NODE==="boolean"...
  function invoke_viid (line 9) | function invoke_viid(index,a1,a2,a3){var sp=stackSave();try{wasmTable.ge...
  function invoke_vi (line 9) | function invoke_vi(index,a1){var sp=stackSave();try{wasmTable.get(index)...
  function invoke_iii (line 9) | function invoke_iii(index,a1,a2){var sp=stackSave();try{return wasmTable...
  function invoke_viiiii (line 9) | function invoke_viiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{wasm...
  function invoke_iiiiiii (line 9) | function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_v (line 9) | function invoke_v(index){var sp=stackSave();try{wasmTable.get(index)()}c...
  function invoke_viiiiiiiiii (line 9) | function invoke_viiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp...
  function invoke_vii (line 9) | function invoke_vii(index,a1,a2){var sp=stackSave();try{wasmTable.get(in...
  function invoke_ii (line 9) | function invoke_ii(index,a1){var sp=stackSave();try{return wasmTable.get...
  function invoke_viii (line 9) | function invoke_viii(index,a1,a2,a3){var sp=stackSave();try{wasmTable.ge...
  function invoke_viiiiii (line 9) | function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_viiiiiii (line 9) | function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_viiiiiiii (line 9) | function invoke_viiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSav...
  function invoke_viiiiiiiii (line 9) | function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stac...
  function invoke_viiii (line 9) | function invoke_viiii(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTabl...
  function invoke_iiiii (line 9) | function invoke_iiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return w...
  function invoke_viiiiiiiiiii (line 9) | function invoke_viiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){v...
  function invoke_viiidd (line 9) | function invoke_viiidd(index,a1,a2,a3,a4,a5){var sp=stackSave();try{wasm...
  function invoke_iiiiii (line 9) | function invoke_iiiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{retu...
  function invoke_viiiiiiiiiiiii (line 9) | function invoke_viiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,...
  function invoke_iiiiiiii (line 9) | function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_diii (line 9) | function invoke_diii(index,a1,a2,a3){var sp=stackSave();try{return wasmT...
  function invoke_iiii (line 9) | function invoke_iiii(index,a1,a2,a3){var sp=stackSave();try{return wasmT...
  function invoke_i (line 9) | function invoke_i(index){var sp=stackSave();try{return wasmTable.get(ind...
  function invoke_viiidi (line 9) | function invoke_viiidi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{wasm...
  function invoke_viiiidi (line 9) | function invoke_viiiidi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_viididii (line 9) | function invoke_viididii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_iiiiiiiii (line 9) | function invoke_iiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSav...
  function invoke_viiiiiiiidf (line 9) | function invoke_viiiiiiiidf(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp...
  function invoke_viiiiiiiidd (line 9) | function invoke_viiiiiiiidd(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp...
  function invoke_viiiiid (line 9) | function invoke_viiiiid(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_viiiiiid (line 9) | function invoke_viiiiiid(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_viiiiiiiiiiii (line 9) | function invoke_viiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a...
  function invoke_viiiiiiidiiii (line 9) | function invoke_viiiiiiidiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a...
  function invoke_viiiiif (line 9) | function invoke_viiiiif(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_viiiiiif (line 9) | function invoke_viiiiiif(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_viiiiiiifiiii (line 9) | function invoke_viiiiiiifiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a...
  function invoke_viiiifiifiiiiiii (line 9) | function invoke_viiiifiifiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a1...
  function invoke_viiiidiidiiiiiii (line 9) | function invoke_viiiidiidiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a1...
  function invoke_vididdii (line 9) | function invoke_vididdii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_viiid (line 9) | function invoke_viiid(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTabl...
  function invoke_vidii (line 9) | function invoke_vidii(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTabl...
  function invoke_viiiiiiiiiiddi (line 9) | function invoke_viiiiiiiiiiddi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,...
  function invoke_viiiiiiiddi (line 9) | function invoke_viiiiiiiddi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp...
  function invoke_iiiiiiiddi (line 9) | function invoke_iiiiiiiddi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stac...
  function invoke_viiiddi (line 9) | function invoke_viiiddi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_viiiid (line 9) | function invoke_viiiid(index,a1,a2,a3,a4,a5){var sp=stackSave();try{wasm...
  function invoke_viiiidid (line 9) | function invoke_viiiidid(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_viidi (line 9) | function invoke_viidi(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTabl...
  function invoke_vdiii (line 9) | function invoke_vdiii(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTabl...
  function ExitStatus (line 9) | function ExitStatus(status){this.name="ExitStatus";this.message="Program...
  function stackCheckInit (line 9) | function stackCheckInit(){_emscripten_stack_init();writeStackCookie()}
  function run (line 9) | function run(args){args=args||arguments_;if(runDependencies>0){return}st...
  function checkUnflushedContent (line 9) | function checkUnflushedContent(){var oldOut=out;var oldErr=err;var has=f...
  function exit (line 9) | function exit(status,implicit){EXITSTATUS=status;checkUnflushedContent()...
  function procExit (line 9) | function procExit(code){EXITSTATUS=code;if(!keepRuntimeAlive()){if(Modul...

FILE: src/renderer/public/lib/@mediapipe/holistic/holistic_solution_packed_assets_loader.js
  function fetchRemotePackage (line 29) | function fetchRemotePackage(packageName, packageSize, callback, errback) {
  function handleError (line 89) | function handleError(error) {
  function runWithFS (line 105) | function runWithFS() {

FILE: src/renderer/public/lib/@mediapipe/holistic/holistic_solution_simd_wasm_bin.js
  function locateFile (line 9) | function locateFile(path){if(Module["locateFile"]){return Module["locate...
  function warnOnce (line 9) | function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnc...
  function convertJsFunctionToWasm (line 9) | function convertJsFunctionToWasm(func,sig){if(typeof WebAssembly.Functio...
  function getEmptyTableSlot (line 9) | function getEmptyTableSlot(){if(freeTableIndexes.length){return freeTabl...
  function addFunctionWasm (line 9) | function addFunctionWasm(func,sig){if(!functionsInTableMap){functionsInT...
  function assert (line 9) | function assert(condition,text){if(!condition){abort("Assertion failed: ...
  function getCFunc (line 9) | function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot ...
  function ccall (line 9) | function ccall(ident,returnType,argTypes,args,opts){var toC={"string":fu...
  function UTF8ArrayToString (line 9) | function UTF8ArrayToString(heap,idx,maxBytesToRead){var endIdx=idx+maxBy...
  function UTF8ToString (line 9) | function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(H...
  function stringToUTF8Array (line 9) | function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxByte...
  function stringToUTF8 (line 9) | function stringToUTF8(str,outPtr,maxBytesToWrite){assert(typeof maxBytes...
  function lengthBytesUTF8 (line 9) | function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){va...
  function UTF16ToString (line 9) | function UTF16ToString(ptr,maxBytesToRead){assert(ptr%2==0,"Pointer pass...
  function stringToUTF16 (line 9) | function stringToUTF16(str,outPtr,maxBytesToWrite){assert(outPtr%2==0,"P...
  function lengthBytesUTF16 (line 9) | function lengthBytesUTF16(str){return str.length*2}
  function UTF32ToString (line 9) | function UTF32ToString(ptr,maxBytesToRead){assert(ptr%4==0,"Pointer pass...
  function stringToUTF32 (line 9) | function stringToUTF32(str,outPtr,maxBytesToWrite){assert(outPtr%4==0,"P...
  function lengthBytesUTF32 (line 9) | function lengthBytesUTF32(str){var len=0;for(var i=0;i<str.length;++i){v...
  function allocateUTF8 (line 9) | function allocateUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_mall...
  function writeArrayToMemory (line 9) | function writeArrayToMemory(array,buffer){assert(array.length>=0,"writeA...
  function writeAsciiToMemory (line 9) | function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i<str.le...
  function alignUp (line 9) | function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}ret...
  function updateGlobalBufferAndViews (line 9) | function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP...
  function writeStackCookie (line 9) | function writeStackCookie(){var max=_emscripten_stack_get_end();assert((...
  function checkStackCookie (line 9) | function checkStackCookie(){if(ABORT)return;var max=_emscripten_stack_ge...
  function keepRuntimeAlive (line 9) | function keepRuntimeAlive(){return noExitRuntime||runtimeKeepaliveCounte...
  function preRun (line 9) | function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="func...
  function initRuntime (line 9) | function initRuntime(){checkStackCookie();assert(!runtimeInitialized);ru...
  function exitRuntime (line 9) | function exitRuntime(){checkStackCookie();runtimeExited=true}
  function postRun (line 9) | function postRun(){checkStackCookie();if(Module["postRun"]){if(typeof Mo...
  function addOnPreRun (line 9) | function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}
  function addOnInit (line 9) | function addOnInit(cb){__ATINIT__.unshift(cb)}
  function addOnPostRun (line 9) | function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}
  function getUniqueRunDependency (line 9) | function getUniqueRunDependency(id){var orig=id;while(1){if(!runDependen...
  function addRunDependency (line 9) | function addRunDependency(id){runDependencies++;if(Module["monitorRunDep...
  function removeRunDependency (line 9) | function removeRunDependency(id){runDependencies--;if(Module["monitorRun...
  function abort (line 9) | function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+...
  function isDataURI (line 9) | function isDataURI(filename){return filename.startsWith(dataURIPrefix)}
  function isFileURI (line 9) | function isFileURI(filename){return filename.startsWith("file://")}
  function createExportWrapper (line 9) | function createExportWrapper(name,fixedasm){return function(){var displa...
  function getBinary (line 9) | function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return...
  function getBinaryPromise (line 9) | function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRON...
  function createWasm (line 9) | function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_previ...
  function HaveOffsetConverter (line 9) | function HaveOffsetConverter(){return typeof wasmOffsetConverter!=="unde...
  function _emscripten_set_main_loop_timing (line 9) | function _emscripten_set_main_loop_timing(mode,value){Browser.mainLoop.t...
  function _emscripten_webgl_do_commit_frame (line 9) | function _emscripten_webgl_do_commit_frame(){if(!GL.currentContext||!GL....
  function _exit (line 9) | function _exit(status){exit(status)}
  function handleException (line 9) | function handleException(e){if(e instanceof ExitStatus||e==="unwind"){re...
  function maybeExit (line 9) | function maybeExit(){if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch...
  function setMainLoop (line 9) | function setMainLoop(browserIterationFunc,fps,simulateInfiniteLoop,arg,n...
  function callUserCallback (line 9) | function callUserCallback(func,synchronous){if(ABORT){err("user callback...
  function safeSetTimeout (line 9) | function safeSetTimeout(func,timeout){return setTimeout(function(){callU...
  function finish (line 9) | function finish(audio){if(done)return;done=true;Module["preloadedAudios"...
  function fail (line 9) | function fail(){if(done)return;done=true;Module["preloadedAudios"][name]...
  function encode64 (line 9) | function encode64(data){var BASE="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkl...
  function pointerLockChange (line 9) | function pointerLockChange(){Browser.pointerLock=document["pointerLockEl...
  function fullscreenChange (line 9) | function fullscreenChange(){Browser.isFullscreen=false;var canvasContain...
  function callRuntimeCallbacks (line 9) | function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var c...
  function demangle (line 9) | function demangle(func){warnOnce("warning: build with  -s DEMANGLE_SUPPO...
  function demangleAll (line 9) | function demangleAll(text){var regex=/\b_Z[\w\d_]+/g;return text.replace...
  function jsStackTrace (line 9) | function jsStackTrace(){var error=new Error;if(!error.stack){try{throw n...
  function stackTrace (line 9) | function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"]...
  function ___cxa_allocate_exception (line 9) | function ___cxa_allocate_exception(size){return _malloc(size+16)+16}
  function _atexit (line 9) | function _atexit(func,arg){}
  function ___cxa_atexit (line 9) | function ___cxa_atexit(a0,a1){return _atexit(a0,a1)}
  function ExceptionInfo (line 9) | function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-16;thi...
  function CatchInfo (line 9) | function CatchInfo(ptr){this.free=function(){_free(this.ptr);this.ptr=0}...
  function exception_addRef (line 9) | function exception_addRef(info){info.add_ref()}
  function ___cxa_begin_catch (line 9) | function ___cxa_begin_catch(ptr){var catchInfo=new CatchInfo(ptr);var in...
  function ___cxa_free_exception (line 9) | function ___cxa_free_exception(ptr){try{return _free(new ExceptionInfo(p...
  function exception_decRef (line 9) | function exception_decRef(info){if(info.release_ref()&&!info.get_rethrow...
  function ___cxa_end_catch (line 9) | function ___cxa_end_catch(){_setThrew(0);assert(exceptionCaught.length>0...
  function ___resumeException (line 9) | function ___resumeException(catchInfoPtr){var catchInfo=new CatchInfo(ca...
  function ___cxa_find_matching_catch_2 (line 9) | function ___cxa_find_matching_catch_2(){var thrown=exceptionLast;if(!thr...
  function ___cxa_find_matching_catch_3 (line 9) | function ___cxa_find_matching_catch_3(){var thrown=exceptionLast;if(!thr...
  function ___cxa_rethrow (line 9) | function ___cxa_rethrow(){var catchInfo=exceptionCaught.pop();if(!catchI...
  function ___cxa_thread_atexit (line 9) | function ___cxa_thread_atexit(a0,a1){return _atexit(a0,a1)}
  function ___cxa_throw (line 9) | function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(pt...
  function setErrNo (line 9) | function setErrNo(value){HEAP32[___errno_location()>>2]=value;return value}
  function getRandomDevice (line 9) | function getRandomDevice(){if(typeof crypto==="object"&&typeof crypto["g...
  function trim (line 9) | function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[sta...
  function zeroMemory (line 9) | function zeroMemory(address,size){HEAPU8.fill(0,address,address+size)}
  function alignMemory (line 9) | function alignMemory(size,alignment){assert(alignment,"alignment argumen...
  function mmapAlloc (line 9) | function mmapAlloc(size){size=alignMemory(size,65536);var ptr=_memalign(...
  function asyncLoad (line 9) | function asyncLoad(url,onload,onerror,noRunDep){var dep=!noRunDep?getUni...
  function doCallback (line 9) | function doCallback(errCode){assert(FS.syncFSRequests>0);FS.syncFSReques...
  function done (line 9) | function done(errCode){if(errCode){if(!done.errored){done.errored=true;r...
  function LazyUint8Array (line 9) | function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}
  function processData (line 9) | function processData(byteArray){function finish(byteArray){if(preFinish)...
  function finish (line 9) | function finish(){if(fail==0)onload();else onerror()}
  function finish (line 9) | function finish(){if(fail==0)onload();else onerror()}
  function ___sys_fcntl64 (line 9) | function ___sys_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var...
  function ___sys_ioctl (line 9) | function ___sys_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var st...
  function syscallMmap2 (line 9) | function syscallMmap2(addr,len,prot,flags,fd,off){off<<=12;var ptr;var a...
  function ___sys_mmap2 (line 9) | function ___sys_mmap2(addr,len,prot,flags,fd,off){try{return syscallMmap...
  function ___sys_open (line 9) | function ___sys_open(path,flags,varargs){SYSCALLS.varargs=varargs;try{va...
  function ___sys_stat64 (line 9) | function ___sys_stat64(path,buf){try{path=SYSCALLS.getStr(path);return S...
  function makeLegalFunctionName (line 9) | function makeLegalFunctionName(name){if(undefined===name){return"_unknow...
  function createNamedFunction (line 9) | function createNamedFunction(name,body){name=makeLegalFunctionName(name)...
  function count_emval_handles (line 9) | function count_emval_handles(){var count=0;for(var i=5;i<emval_handle_ar...
  function get_first_emval (line 9) | function get_first_emval(){for(var i=5;i<emval_handle_array.length;++i){...
  function init_emval (line 9) | function init_emval(){Module["count_emval_handles"]=count_emval_handles;...
  function __emval_register (line 9) | function __emval_register(value){switch(value){case undefined:{return 1}...
  function extendError (line 9) | function extendError(baseErrorType,errorName){var errorClass=createNamed...
  function embind_init_charCodes (line 9) | function embind_init_charCodes(){var codes=new Array(256);for(var i=0;i<...
  function readLatin1String (line 9) | function readLatin1String(ptr){var ret="";var c=ptr;while(HEAPU8[c]){ret...
  function getInheritedInstanceCount (line 9) | function getInheritedInstanceCount(){return Object.keys(registeredInstan...
  function getLiveInheritedInstances (line 9) | function getLiveInheritedInstances(){var rv=[];for(var k in registeredIn...
  function flushPendingDeletes (line 9) | function flushPendingDeletes(){while(deletionQueue.length){var obj=delet...
  function setDelayFunction (line 9) | function setDelayFunction(fn){delayFunction=fn;if(deletionQueue.length&&...
  function init_embind (line 9) | function init_embind(){Module["getInheritedInstanceCount"]=getInheritedI...
  function throwBindingError (line 9) | function throwBindingError(message){throw new BindingError(message)}
  function getBasestPointer (line 9) | function getBasestPointer(class_,ptr){if(ptr===undefined){throwBindingEr...
  function registerInheritedInstance (line 9) | function registerInheritedInstance(class_,ptr,instance){ptr=getBasestPoi...
  function requireHandle (line 9) | function requireHandle(handle){if(!handle){throwBindingError("Cannot use...
  function getTypeName (line 9) | function getTypeName(type){var ptr=___getTypeName(type);var rv=readLatin...
  function requireRegisteredType (line 9) | function requireRegisteredType(rawType,humanName){var impl=registeredTyp...
  function unregisterInheritedInstance (line 9) | function unregisterInheritedInstance(class_,ptr){ptr=getBasestPointer(cl...
  function detachFinalizer (line 9) | function detachFinalizer(handle){}
  function runDestructor (line 9) | function runDestructor($$){if($$.smartPtr){$$.smartPtrType.rawDestructor...
  function releaseClassHandle (line 9) | function releaseClassHandle($$){$$.count.value-=1;var toDelete=0===$$.co...
  function attachFinalizer (line 9) | function attachFinalizer(handle){if("undefined"===typeof FinalizationGro...
  function __embind_create_inheriting_constructor (line 9) | function __embind_create_inheriting_constructor(constructorName,wrapperT...
  function runDestructors (line 9) | function runDestructors(destructors){while(destructors.length){var ptr=d...
  function simpleReadValueFromPointer (line 9) | function simpleReadValueFromPointer(pointer){return this["fromWireType"]...
  function throwInternalError (line 9) | function throwInternalError(message){throw new InternalError(message)}
  function whenDependentTypesAreResolved (line 9) | function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeCon...
  function __embind_finalize_value_object (line 9) | function __embind_finalize_value_object(structType){var reg=structRegist...
  function __embind_register_bigint (line 9) | function __embind_register_bigint(primitiveType,name,size,minRange,maxRa...
  function getShiftFromSize (line 9) | function getShiftFromSize(size){switch(size){case 1:return 0;case 2:retu...
  function registerType (line 9) | function registerType(rawType,registeredInstance,options){options=option...
  function __embind_register_bool (line 9) | function __embind_register_bool(rawType,name,size,trueValue,falseValue){...
  function ClassHandle_isAliasOf (line 9) | function ClassHandle_isAliasOf(other){if(!(this instanceof ClassHandle))...
  function shallowCopyInternalPointer (line 9) | function shallowCopyInternalPointer(o){return{count:o.count,deleteSchedu...
  function throwInstanceAlreadyDeleted (line 9) | function throwInstanceAlreadyDeleted(obj){function getInstanceTypeName(h...
  function ClassHandle_clone (line 9) | function ClassHandle_clone(){if(!this.$$.ptr){throwInstanceAlreadyDelete...
  function ClassHandle_delete (line 9) | function ClassHandle_delete(){if(!this.$$.ptr){throwInstanceAlreadyDelet...
  function ClassHandle_isDeleted (line 9) | function ClassHandle_isDeleted(){return!this.$$.ptr}
  function ClassHandle_deleteLater (line 9) | function ClassHandle_deleteLater(){if(!this.$$.ptr){throwInstanceAlready...
  function init_ClassHandle (line 9) | function init_ClassHandle(){ClassHandle.prototype["isAliasOf"]=ClassHand...
  function ClassHandle (line 9) | function ClassHandle(){}
  function ensureOverloadTable (line 9) | function ensureOverloadTable(proto,methodName,humanName){if(undefined===...
  function exposePublicSymbol (line 9) | function exposePublicSymbol(name,value,numArguments){if(Module.hasOwnPro...
  function RegisteredClass (line 9) | function RegisteredClass(name,constructor,instancePrototype,rawDestructo...
  function upcastPointer (line 9) | function upcastPointer(ptr,ptrClass,desiredClass){while(ptrClass!==desir...
  function constNoSmartPtrRawPointerToWireType (line 9) | function constNoSmartPtrRawPointerToWireType(destructors,handle){if(hand...
  function genericPointerToWireType (line 9) | function genericPointerToWireType(destructors,handle){var ptr;if(handle=...
  function nonConstNoSmartPtrRawPointerToWireType (line 9) | function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(h...
  function RegisteredPointer_getPointee (line 9) | function RegisteredPointer_getPointee(ptr){if(this.rawGetPointee){ptr=th...
  function RegisteredPointer_destructor (line 9) | function RegisteredPointer_destructor(ptr){if(this.rawDestructor){this.r...
  function RegisteredPointer_deleteObject (line 9) | function RegisteredPointer_deleteObject(handle){if(handle!==null){handle...
  function downcastPointer (line 9) | function downcastPointer(ptr,ptrClass,desiredClass){if(ptrClass===desire...
  function getInheritedInstance (line 9) | function getInheritedInstance(class_,ptr){ptr=getBasestPointer(class_,pt...
  function makeClassHandle (line 9) | function makeClassHandle(prototype,record){if(!record.ptrType||!record.p...
  function RegisteredPointer_fromWireType (line 9) | function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPoin...
  function init_RegisteredPointer (line 9) | function init_RegisteredPointer(){RegisteredPointer.prototype.getPointee...
  function RegisteredPointer (line 9) | function RegisteredPointer(name,registeredClass,isReference,isConst,isSm...
  function replacePublicSymbol (line 9) | function replacePublicSymbol(name,value,numArguments){if(!Module.hasOwnP...
  function dynCallLegacy (line 9) | function dynCallLegacy(sig,ptr,args){assert("dynCall_"+sig in Module,"ba...
  function dynCall (line 9) | function dynCall(sig,ptr,args){if(sig.includes("j")){return dynCallLegac...
  function getDynCaller (line 9) | function getDynCaller(sig,ptr){assert(sig.includes("j"),"getDynCaller sh...
  function embind__requireFunction (line 9) | function embind__requireFunction(signature,rawFunction){signature=readLa...
  function throwUnboundTypeError (line 9) | function throwUnboundTypeError(message,types){var unboundTypes=[];var se...
  function __embind_register_class (line 9) | function __embind_register_class(rawType,rawPointerType,rawConstPointerT...
  function new_ (line 9) | function new_(constructor,argumentList){if(!(constructor instanceof Func...
  function craftInvokerFunction (line 9) | function craftInvokerFunction(humanName,argTypes,classType,cppInvokerFun...
  function heap32VectorToArray (line 9) | function heap32VectorToArray(count,firstElement){var array=[];for(var i=...
  function __embind_register_class_class_function (line 9) | function __embind_register_class_class_function(rawClassType,methodName,...
  function __embind_register_class_constructor (line 9) | function __embind_register_class_constructor(rawClassType,argCount,rawAr...
  function __embind_register_class_function (line 9) | function __embind_register_class_function(rawClassType,methodName,argCou...
  function validateThis (line 9) | function validateThis(this_,classType,humanName){if(!(this_ instanceof O...
  function __embind_register_class_property (line 9) | function __embind_register_class_property(classType,fieldName,getterRetu...
  function __emval_decref (line 9) | function __emval_decref(handle){if(handle>4&&0===--emval_handle_array[ha...
  function __embind_register_emval (line 9) | function __embind_register_emval(rawType,name){name=readLatin1String(nam...
  function _embind_repr (line 9) | function _embind_repr(v){if(v===null){return"null"}var t=typeof v;if(t==...
  function floatReadValueFromPointer (line 9) | function floatReadValueFromPointer(name,shift){switch(shift){case 2:retu...
  function __embind_register_float (line 9) | function __embind_register_float(rawType,name,size){var shift=getShiftFr...
  function __embind_register_function (line 9) | function __embind_register_function(name,argCount,rawArgTypesAddr,signat...
  function integerReadValueFromPointer (line 9) | function integerReadValueFromPointer(name,shift,signed){switch(shift){ca...
  function __embind_register_integer (line 9) | function __embind_register_integer(primitiveType,name,size,minRange,maxR...
  function __embind_register_memory_view (line 9) | function __embind_register_memory_view(rawType,dataTypeIndex,name){var t...
  function __embind_register_std_string (line 9) | function __embind_register_std_string(rawType,name){name=readLatin1Strin...
  function __embind_register_std_wstring (line 9) | function __embind_register_std_wstring(rawType,charSize,name){name=readL...
  function __embind_register_value_object (line 9) | function __embind_register_value_object(rawType,name,constructorSignatur...
  function __embind_register_value_object_field (line 9) | function __embind_register_value_object_field(structType,fieldName,gette...
  function __embind_register_void (line 9) | function __embind_register_void(rawType,name){name=readLatin1String(name...
  function getStringOrSymbol (line 9) | function getStringOrSymbol(address){var symbol=emval_symbols[address];if...
  function __emval_call_void_method (line 9) | function __emval_call_void_method(caller,handle,methodName,args){caller=...
  function __emval_addMethodCaller (line 9) | function __emval_addMethodCaller(caller){var id=emval_methodCallers.leng...
  function __emval_lookupTypes (line 9) | function __emval_lookupTypes(argCount,argTypes){var a=new Array(argCount...
  function __emval_get_method_caller (line 9) | function __emval_get_method_caller(argCount,argTypes){var types=__emval_...
  function __emval_incref (line 9) | function __emval_incref(handle){if(handle>4){emval_handle_array[handle]....
  function __emval_take_value (line 9) | function __emval_take_value(type,argv){type=requireRegisteredType(type,"...
  function _abort (line 9) | function _abort(){abort()}
  function _clock_gettime (line 9) | function _clock_gettime(clk_id,tp){var now;if(clk_id===0){now=Date.now()...
  function _dlopen (line 9) | function _dlopen(filename,flag){abort("To use dlopen, you need to use Em...
  function _dlsym (line 9) | function _dlsym(handle,symbol){abort("To use dlopen, you need to use Ems...
  function readAsmConstArgs (line 9) | function readAsmConstArgs(sigPtr,buf){assert(Array.isArray(readAsmConstA...
  function _emscripten_asm_const_int (line 9) | function _emscripten_asm_const_int(code,sigPtr,argbuf){var args=readAsmC...
  function _emscripten_get_heap_max (line 9) | function _emscripten_get_heap_max(){return 2147483648}
  function _emscripten_memcpy_big (line 9) | function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src...
  function _emscripten_pc_get_function (line 9) | function _emscripten_pc_get_function(pc){abort("Cannot use emscripten_pc...
  function emscripten_realloc_buffer (line 9) | function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer...
  function _emscripten_resize_heap (line 9) | function _emscripten_resize_heap(requestedSize){var oldSize=HEAPU8.lengt...
  function _emscripten_generate_pc (line 9) | function _emscripten_generate_pc(frame){abort("Cannot use emscripten_gen...
  function __emscripten_save_in_unwind_cache (line 9) | function __emscripten_save_in_unwind_cache(callstack){callstack.forEach(...
  function _emscripten_stack_snapshot (line 9) | function _emscripten_stack_snapshot(){var callstack=(new Error).stack.sp...
  function _emscripten_stack_unwind_buffer (line 9) | function _emscripten_stack_unwind_buffer(addr,buffer,count){var stack;if...
  function _emscripten_thread_sleep (line 9) | function _emscripten_thread_sleep(msecs){var start=_emscripten_get_now()...
  function __webgl_enable_ANGLE_instanced_arrays (line 9) | function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExten...
  function __webgl_enable_OES_vertex_array_object (line 9) | function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExte...
  function __webgl_enable_WEBGL_draw_buffers (line 9) | function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension...
  function __webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance (line 9) | function __webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(c...
  function __webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance (line 9) | function __webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_inst...
  function __webgl_enable_WEBGL_multi_draw (line 9) | function __webgl_enable_WEBGL_multi_draw(ctx){return!!(ctx.multiDrawWebg...
  function draw (line 9) | function draw(){gl.vertexAttribPointer(context.blitPosLoc,2,5126,false,0...
  function arraysHaveEqualContent (line 9) | function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)r...
  function findEventTarget (line 9) | function findEventTarget(target){warnOnce("Rules for selecting event tar...
  function findCanvasEventTarget (line 9) | function findCanvasEventTarget(target){if(typeof target==="number")targe...
  function _emscripten_webgl_do_create_context (line 9) | function _emscripten_webgl_do_create_context(target,attributes){assert(a...
  function _emscripten_webgl_create_context (line 9) | function _emscripten_webgl_create_context(a0,a1){return _emscripten_webg...
  function _emscripten_webgl_do_get_current_context (line 9) | function _emscripten_webgl_do_get_current_context(){return GL.currentCon...
  function _emscripten_webgl_get_current_context (line 9) | function _emscripten_webgl_get_current_context(){return _emscripten_webg...
  function _emscripten_webgl_make_context_current (line 9) | function _emscripten_webgl_make_context_current(contextHandle){var succe...
  function _emscripten_webgl_destroy_context (line 9) | function _emscripten_webgl_destroy_context(contextHandle){if(GL.currentC...
  function _emscripten_webgl_get_context_attributes (line 9) | function _emscripten_webgl_get_context_attributes(c,a){if(!a)return-5;c=...
  function _emscripten_webgl_init_context_attributes (line 9) | function _emscripten_webgl_init_context_attributes(attributes){assert(at...
  function getExecutableName (line 9) | function getExecutableName(){return thisProgram||"./this.program"}
  function getEnvStrings (line 9) | function getEnvStrings(){if(!getEnvStrings.strings){var lang=(typeof nav...
  function _environ_get (line 9) | function _environ_get(__environ,environ_buf){var bufSize=0;getEnvStrings...
  function _environ_sizes_get (line 9) | function _environ_sizes_get(penviron_count,penviron_buf_size){var string...
  function _fd_close (line 9) | function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.cl...
  function _fd_read (line 9) | function _fd_read(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamF...
  function _fd_seek (line 9) | function _fd_seek(fd,offset_low,offset_high,whence,newOffset){try{var st...
  function _fd_write (line 9) | function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStream...
  function _getTempRet0 (line 9) | function _getTempRet0(){return getTempRet0()}
  function _getentropy (line 9) | function _getentropy(buffer,size){if(!_getentropy.randomDevice){_getentr...
  function _glActiveTexture (line 9) | function _glActiveTexture(x0){GLctx["activeTexture"](x0)}
  function _glAttachShader (line 9) | function _glAttachShader(program,shader){GLctx.attachShader(GL.programs[...
  function _glBindAttribLocation (line 9) | function _glBindAttribLocation(program,index,name){GLctx.bindAttribLocat...
  function _glBindBuffer (line 9) | function _glBindBuffer(target,buffer){if(target==34962){GLctx.currentArr...
  function _glBindBufferBase (line 9) | function _glBindBufferBase(target,index,buffer){GLctx["bindBufferBase"](...
  function _glBindFramebuffer (line 9) | function _glBindFramebuffer(target,framebuffer){GLctx.bindFramebuffer(ta...
  function _glBindTexture (line 9) | function _glBindTexture(target,texture){GLctx.bindTexture(target,GL.text...
  function _glBindVertexArray (line 9) | function _glBindVertexArray(vao){GLctx["bindVertexArray"](GL.vaos[vao]);...
  function _glBufferData (line 9) | function _glBufferData(target,size,data,usage){if(GL.currentContext.vers...
  function convertI32PairToI53 (line 9) | function convertI32PairToI53(lo,hi){assert(hi===(hi|0));return(lo>>>0)+h...
  function _glClientWaitSync (line 9) | function _glClientWaitSync(sync,flags,timeoutLo,timeoutHi){return GLctx....
  function _glCompileShader (line 9) | function _glCompileShader(shader){GLctx.compileShader(GL.shaders[shader])}
  function _glCreateProgram (line 9) | function _glCreateProgram(){var id=GL.getNewId(GL.programs);var program=...
  function _glCreateShader (line 9) | function _glCreateShader(shaderType){var id=GL.getNewId(GL.shaders);GL.s...
  function _glDeleteBuffers (line 9) | function _glDeleteBuffers(n,buffers){for(var i=0;i<n;i++){var id=HEAP32[...
  function _glDeleteFramebuffers (line 9) | function _glDeleteFramebuffers(n,framebuffers){for(var i=0;i<n;++i){var ...
  function _glDeleteProgram (line 9) | function _glDeleteProgram(id){if(!id)return;var program=GL.programs[id];...
  function _glDeleteShader (line 9) | function _glDeleteShader(id){if(!id)return;var shader=GL.shaders[id];if(...
  function _glDeleteSync (line 9) | function _glDeleteSync(id){if(!id)return;var sync=GL.syncs[id];if(!sync)...
  function _glDeleteTextures (line 9) | function _glDeleteTextures(n,textures){for(var i=0;i<n;i++){var id=HEAP3...
  function _glDeleteVertexArrays (line 9) | function _glDeleteVertexArrays(n,vaos){for(var i=0;i<n;i++){var id=HEAP3...
  function _glDisable (line 9) | function _glDisable(x0){GLctx["disable"](x0)}
  function _glDisableVertexAttribArray (line 9) | function _glDisableVertexAttribArray(index){var cb=GL.currentContext.cli...
  function _glDrawArrays (line 9) | function _glDrawArrays(mode,first,count){GL.preDrawHandleClientVertexAtt...
  function _glDrawBuffers (line 9) | function _glDrawBuffers(n,bufs){var bufArray=tempFixedLengthArray[n];for...
  function _glEnableVertexAttribArray (line 9) | function _glEnableVertexAttribArray(index){var cb=GL.currentContext.clie...
  function _glFenceSync (line 9) | function _glFenceSync(condition,flags){var sync=GLctx.fenceSync(conditio...
  function _glFinish (line 9) | function _glFinish(){GLctx["finish"]()}
  function _glFlush (line 9) | function _glFlush(){GLctx["flush"]()}
  function _glFramebufferTexture2D (line 9) | function _glFramebufferTexture2D(target,attachment,textarget,texture,lev...
  function _glFramebufferTextureLayer (line 9) | function _glFramebufferTextureLayer(target,attachment,texture,level,laye...
  function __glGenObject (line 9) | function __glGenObject(n,buffers,createFunction,objectTable){for(var i=0...
  function _glGenBuffers (line 9) | function _glGenBuffers(n,buffers){__glGenObject(n,buffers,"createBuffer"...
  function _glGenFramebuffers (line 9) | function _glGenFramebuffers(n,ids){__glGenObject(n,ids,"createFramebuffe...
  function _glGenTextures (line 9) | function _glGenTextures(n,textures){__glGenObject(n,textures,"createText...
  function _glGenVertexArrays (line 9) | function _glGenVertexArrays(n,arrays){__glGenObject(n,arrays,"createVert...
  function _glGetAttribLocation (line 9) | function _glGetAttribLocation(program,name){return GLctx.getAttribLocati...
  function _glGetError (line 9) | function _glGetError(){var error=GLctx.getError()||GL.lastError;GL.lastE...
  function _glGetFramebufferAttachmentParameteriv (line 9) | function _glGetFramebufferAttachmentParameteriv(target,attachment,pname,...
  function readI53FromI64 (line 9) | function readI53FromI64(ptr){return HEAPU32[ptr>>2]+HEAP32[ptr+4>>2]*429...
  function readI53FromU64 (line 9) | function readI53FromU64(ptr){return HEAPU32[ptr>>2]+HEAPU32[ptr+4>>2]*42...
  function writeI53ToI64 (line 9) | function writeI53ToI64(ptr,num){HEAPU32[ptr>>2]=num;HEAPU32[ptr+4>>2]=(n...
  function emscriptenWebGLGet (line 9) | function emscriptenWebGLGet(name_,p,type){if(!p){GL.recordError(1281);re...
  function _glGetIntegerv (line 9) | function _glGetIntegerv(name_,p){emscriptenWebGLGet(name_,p,0)}
  function stringToNewUTF8 (line 9) | function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+...
  function _glGetString (line 9) | function _glGetString(name_){var ret=GL.stringCache[name_];if(!ret){swit...
  function _glGetUniformBlockIndex (line 9) | function _glGetUniformBlockIndex(program,uniformBlockName){return GLctx[...
  function jstoi_q (line 9) | function jstoi_q(str){return parseInt(str)}
  function webglGetLeftBracePos (line 9) | function webglGetLeftBracePos(name){return name.slice(-1)=="]"&&name.las...
  function webglPrepareUniformLocationsBeforeFirstUse (line 9) | function webglPrepareUniformLocationsBeforeFirstUse(program){var uniform...
  function _glGetUniformLocation (line 9) | function _glGetUniformLocation(program,name){name=UTF8ToString(name);if(...
  function _glLinkProgram (line 9) | function _glLinkProgram(program){program=GL.programs[program];GLctx.link...
  function _glPixelStorei (line 9) | function _glPixelStorei(pname,param){if(pname==3317){GL.unpackAlignment=...
  function computeUnpackAlignedImageSize (line 9) | function computeUnpackAlignedImageSize(width,height,sizePerPixel,alignme...
  function __colorChannelsInGlTextureFormat (line 9) | function __colorChannelsInGlTextureFormat(format){var colorChannels={5:3...
  function heapObjectForWebGLType (line 9) | function heapObjectForWebGLType(type){type-=5120;if(type==0)return HEAP8...
  function heapAccessShiftForWebGLHeap (line 9) | function heapAccessShiftForWebGLHeap(heap){return 31-Math.clz32(heap.BYT...
  function emscriptenWebGLGetTexPixelData (line 9) | function emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,...
  function _glReadPixels (line 9) | function _glReadPixels(x,y,width,height,format,type,pixels){if(GL.curren...
  function _glShaderSource (line 9) | function _glShaderSource(shader,count,string,length){var source=GL.getSo...
  function _glTexImage2D (line 9) | function _glTexImage2D(target,level,internalFormat,width,height,border,f...
  function _glTexParameterfv (line 9) | function _glTexParameterfv(target,pname,params){var param=HEAPF32[params...
  function _glTexParameteri (line 9) | function _glTexParameteri(x0,x1,x2){GLctx["texParameteri"](x0,x1,x2)}
  function _glTexStorage2D (line 9) | function _glTexStorage2D(x0,x1,x2,x3,x4){GLctx["texStorage2D"](x0,x1,x2,...
  function _glTexStorage3D (line 9) | function _glTexStorage3D(x0,x1,x2,x3,x4,x5){GLctx["texStorage3D"](x0,x1,...
  function _glTexSubImage2D (line 9) | function _glTexSubImage2D(target,level,xoffset,yoffset,width,height,form...
  function _glTexSubImage3D (line 9) | function _glTexSubImage3D(target,level,xoffset,yoffset,zoffset,width,hei...
  function webglGetUniformLocation (line 9) | function webglGetUniformLocation(location){var p=GLctx.currentProgram;if...
  function _glUniform1f (line 9) | function _glUniform1f(location,v0){GLctx.uniform1f(webglGetUniformLocati...
  function _glUniform1i (line 9) | function _glUniform1i(location,v0){GLctx.uniform1i(webglGetUniformLocati...
  function _glUniform2fv (line 9) | function _glUniform2fv(location,count,value){if(GL.currentContext.versio...
  function _glUniform4fv (line 9) | function _glUniform4fv(location,count,value){if(GL.currentContext.versio...
  function _glUniform4iv (line 9) | function _glUniform4iv(location,count,value){if(GL.currentContext.versio...
  function _glUniformBlockBinding (line 9) | function _glUniformBlockBinding(program,uniformBlockIndex,uniformBlockBi...
  function _glUniformMatrix4fv (line 9) | function _glUniformMatrix4fv(location,count,transpose,value){if(GL.curre...
  function _glUseProgram (line 9) | function _glUseProgram(program){program=GL.programs[program];GLctx.usePr...
  function _glVertexAttribPointer (line 9) | function _glVertexAttribPointer(index,size,type,normalized,stride,ptr){v...
  function _glViewport (line 9) | function _glViewport(x0,x1,x2,x3){GLctx["viewport"](x0,x1,x2,x3)}
  function _gmtime_r (line 9) | function _gmtime_r(time,tmPtr){var date=new Date(HEAP32[time>>2]*1e3);HE...
  function _llvm_eh_typeid_for (line 9) | function _llvm_eh_typeid_for(type){return type}
  function _tzset (line 9) | function _tzset(){if(_tzset.called)return;_tzset.called=true;var current...
  function _localtime_r (line 9) | function _localtime_r(time,tmPtr){_tzset();var date=new Date(HEAP32[time...
  function _mktime (line 9) | function _mktime(tmPtr){_tzset();var date=new Date(HEAP32[tmPtr+20>>2]+1...
  function _proc_exit (line 9) | function _proc_exit(code){procExit(code)}
  function _setTempRet0 (line 9) | function _setTempRet0(val){setTempRet0(val)}
  function __isLeapYear (line 9) | function __isLeapYear(year){return year%4===0&&(year%100!==0||year%400==...
  function __arraySum (line 9) | function __arraySum(array,index){var sum=0;for(var i=0;i<=index;sum+=arr...
  function __addDays (line 9) | function __addDays(date,days){var newDate=new Date(date.getTime());while...
  function _strftime (line 9) | function _strftime(s,maxsize,format,tm){var tm_zone=HEAP32[tm+40>>2];var...
  function _strftime_l (line 9) | function _strftime_l(s,maxsize,format,tm){return _strftime(s,maxsize,for...
  function intArrayFromString (line 9) | function intArrayFromString(stringy,dontAddNull,length){var len=length>0...
  function intArrayFromBase64 (line 9) | function intArrayFromBase64(s){if(typeof ENVIRONMENT_IS_NODE==="boolean"...
  function invoke_viid (line 9) | function invoke_viid(index,a1,a2,a3){var sp=stackSave();try{wasmTable.ge...
  function invoke_vi (line 9) | function invoke_vi(index,a1){var sp=stackSave();try{wasmTable.get(index)...
  function invoke_iii (line 9) | function invoke_iii(index,a1,a2){var sp=stackSave();try{return wasmTable...
  function invoke_viiiii (line 9) | function invoke_viiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{wasm...
  function invoke_iiiiiii (line 9) | function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_v (line 9) | function invoke_v(index){var sp=stackSave();try{wasmTable.get(index)()}c...
  function invoke_viiiiiiiiii (line 9) | function invoke_viiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp...
  function invoke_vii (line 9) | function invoke_vii(index,a1,a2){var sp=stackSave();try{wasmTable.get(in...
  function invoke_ii (line 9) | function invoke_ii(index,a1){var sp=stackSave();try{return wasmTable.get...
  function invoke_viii (line 9) | function invoke_viii(index,a1,a2,a3){var sp=stackSave();try{wasmTable.ge...
  function invoke_viiiiii (line 9) | function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_viiiiiii (line 9) | function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_viiiiiiii (line 9) | function invoke_viiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSav...
  function invoke_viiiiiiiii (line 9) | function invoke_viiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stac...
  function invoke_viiii (line 9) | function invoke_viiii(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTabl...
  function invoke_iiiii (line 9) | function invoke_iiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return w...
  function invoke_viiiiiiiiiii (line 9) | function invoke_viiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){v...
  function invoke_viiidd (line 9) | function invoke_viiidd(index,a1,a2,a3,a4,a5){var sp=stackSave();try{wasm...
  function invoke_iiiiii (line 9) | function invoke_iiiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{retu...
  function invoke_iiiiiiiiii (line 9) | function invoke_iiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stac...
  function invoke_viiiiiiiiiiiii (line 9) | function invoke_viiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,...
  function invoke_iiiiiiii (line 9) | function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_diii (line 9) | function invoke_diii(index,a1,a2,a3){var sp=stackSave();try{return wasmT...
  function invoke_iiii (line 9) | function invoke_iiii(index,a1,a2,a3){var sp=stackSave();try{return wasmT...
  function invoke_viiiiiiiiidd (line 9) | function invoke_viiiiiiiiidd(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){v...
  function invoke_viiiiiiiiiddi (line 9) | function invoke_viiiiiiiiiddi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a...
  function invoke_viiiddi (line 9) | function invoke_viiiddi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_i (line 9) | function invoke_i(index){var sp=stackSave();try{return wasmTable.get(ind...
  function invoke_viiidi (line 9) | function invoke_viiidi(index,a1,a2,a3,a4,a5){var sp=stackSave();try{wasm...
  function invoke_viiiidi (line 9) | function invoke_viiiidi(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_viididii (line 9) | function invoke_viididii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_iiiiiiiii (line 9) | function invoke_iiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8){var sp=stackSav...
  function invoke_viiiiiiiidf (line 9) | function invoke_viiiiiiiidf(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp...
  function invoke_viiiiiiiidd (line 9) | function invoke_viiiiiiiidd(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp...
  function invoke_viiiiid (line 9) | function invoke_viiiiid(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_viiiiiid (line 9) | function invoke_viiiiiid(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_viiiiiiiiiiii (line 9) | function invoke_viiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a...
  function invoke_viiiiiiidiiii (line 9) | function invoke_viiiiiiidiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a...
  function invoke_viiiiif (line 9) | function invoke_viiiiif(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{...
  function invoke_viiiiiif (line 9) | function invoke_viiiiiif(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_viiiiiiifiiii (line 9) | function invoke_viiiiiiifiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a...
  function invoke_viiiifiifiiiiiii (line 9) | function invoke_viiiifiifiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a1...
  function invoke_viiiidiidiiiiiii (line 9) | function invoke_viiiidiidiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a1...
  function invoke_vididdii (line 9) | function invoke_vididdii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_viiid (line 9) | function invoke_viiid(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTabl...
  function invoke_vidii (line 9) | function invoke_vidii(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTabl...
  function invoke_viiiiiiiiiiddi (line 9) | function invoke_viiiiiiiiiiddi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,...
  function invoke_viiiiiiiddi (line 9) | function invoke_viiiiiiiddi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp...
  function invoke_iiiiiiiddi (line 9) | function invoke_iiiiiiiddi(index,a1,a2,a3,a4,a5,a6,a7,a8,a9){var sp=stac...
  function invoke_viiiid (line 9) | function invoke_viiiid(index,a1,a2,a3,a4,a5){var sp=stackSave();try{wasm...
  function invoke_viiiidid (line 9) | function invoke_viiiidid(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();...
  function invoke_viidi (line 9) | function invoke_viidi(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTabl...
  function invoke_vdiii (line 9) | function invoke_vdiii(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTabl...
  function ExitStatus (line 9) | function ExitStatus(status){this.name="ExitStatus";this.message="Program...
  function stackCheckInit (line 9) | function stackCheckInit(){_emscripten_stack_init();writeStackCookie()}
  function run (line 9) | function run(args){args=args||arguments_;if(runDependencies>0){return}st...
  function checkUnflushedContent (line 9) | function checkUnflushedContent(){var oldOut=out;var oldErr=err;var has=f...
  function exit (line 9) | function exit(status,implicit){EXITSTATUS=status;checkUnflushedContent()...
  function procExit (line 9) | function procExit(code){EXITSTATUS=code;if(!keepRuntimeAlive()){if(Modul...

FILE: src/renderer/public/lib/@mediapipe/holistic/holistic_solution_wasm_bin.js
  function locateFile (line 9) | function locateFile(path){if(Module["locateFile"]){return Module["locate...
  function warnOnce (line 9) | function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnc...
  function convertJsFunctionToWasm (line 9) | function convertJsFunctionToWasm(func,sig){if(typeof WebAssembly.Functio...
  function getEmptyTableSlot (line 9) | function getEmptyTableSlot(){if(freeTableIndexes.length){return freeTabl...
  function addFunctionWasm (line 9) | function addFunctionWasm(func,sig){if(!functionsInTableMap){functionsInT...
  function assert (line 9) | function assert(condition,text){if(!condition){abort("Assertion failed: ...
  function getCFunc (line 9) | function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot ...
  function ccall (line 9) | function ccall(ident,returnType,argTypes,args,opts){var toC={"string":fu...
  function UTF8ArrayToString (line 9) | function UTF8ArrayToString(heap,idx,maxBytesToRead){var endIdx=idx+maxBy...
  function UTF8ToString (line 9) | function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(H...
  function stringToUTF8Array (line 9) | function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxByte...
  function stringToUTF8 (line 9) | function stringToUTF8(str,outPtr,maxBytesToWrite){assert(typeof maxBytes...
  function lengthBytesUTF8 (line 9) | function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){va...
  function UTF16ToString (line 9) | function UTF16ToString(ptr,maxBytesToRead){assert(ptr%2==0,"Pointer pass...
  function stringToUTF16 (line 9) | function stringToUTF16(str,outPtr,maxBytesToWrite){assert(outPtr%2==0,"P...
  function lengthBytesUTF16 (line 9) | function lengthBytesUTF16(str){return str.length*2}
  function UTF32ToString (line 9) | function UTF32ToString(ptr,maxBytesToRead){assert(ptr%4==0,"Pointer pass...
  function stringToUTF32 (line 9) | function stringToUTF32(str,outPtr,maxBytesToWrite){assert(outPtr%4==0,"P...
  function lengthBytesUTF32 (line 9) | function lengthBytesUTF32(str){var len=0;for(var i=0;i<str.length;++i){v...
  function allocateUTF8 (line 9) | function allocateUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_mall...
  function writeArrayToMemory (line 9) | function writeArrayToMemory(array,buffer){assert(array.length>=0,"writeA...
  function writeAsciiToMemory (line 9) | function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i<str.le...
  function alignUp (line 9) | function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}ret...
  function updateGlobalBufferAndViews (line 9) | function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP...
  function writeStackCookie (line 9) | function writeStackCookie(){var max=_emscripten_stack_get_end();assert((...
  function checkStackCookie (line 9) | function checkStackCookie(){if(ABORT)return;var max=_emscripten_stack_ge...
  function keepRuntimeAlive (line 9) | function keepRuntimeAlive(){return noExitRuntime||runtimeKeepaliveCounte...
  function preRun (line 9) | function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="func...
  function initRuntime (line 9) | function initRuntime(){checkStackCookie();assert(!runtimeInitialized);ru...
  function exitRuntime (line 9) | function exitRuntime(){checkStackCookie();runtimeExited=true}
  function postRun (line 9) | function postRun(){checkStackCookie();if(Module["postRun"]){if(typeof Mo...
  function addOnPreRun (line 9) | function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}
  function addOnInit (line 9) | function addOnInit(cb){__ATINIT__.unshift(cb)}
  function addOnPostRun (line 9) | function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}
  function getUniqueRunDependency (line 9) | function getUniqueRunDependency(id){var orig=id;while(1){if(!runDependen...
  function addRunDependency (line 9) | function addRunDependency(id){runDependencies++;if(Module["monitorRunDep...
  function removeRunDependency (line 9) | function removeRunDependency(id){runDependencies--;if(Module["monitorRun...
  function abort (line 9) | function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+...
  function isDataURI (line 9) | function isDataURI(filename){return filename.startsWith(dataURIPrefix)}
  function isFileURI (line 9) | function isFileURI(filename){return filename.startsWith("file://")}
  function createExportWrapper (line 9) | function createExportWrapper(name,fixedasm){return function(){var displa...
  function getBinary (line 9) | function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return...
  function getBinaryPromise (line 9) | function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRON...
  function createWasm (line 9) | function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_previ...
  function HaveOffsetConverter (line 9) | function HaveOffsetConverter(){return typeof wasmOffsetConverter!=="unde...
  function _emscripten_set_main_loop_timing (line 9) | function _emscripten_set_main_loop_timing(mode,value){Browser.mainLoop.t...
  function _emscripten_webgl_do_commit_frame (line 9) | function _emscripten_webgl_do_commit_frame(){if(!GL.currentContext||!GL....
  function _exit (line 9) | function _exit(status){exit(status)}
  function handleException (line 9) | function handleException(e){if(e instanceof ExitStatus||e==="unwind"){re...
  function maybeExit (line 9) | function maybeExit(){if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch...
  function setMainLoop (line 9) | function setMainLoop(browserIterationFunc,fps,simulateInfiniteLoop,arg,n...
  function callUserCallback (line 9) | function callUserCallback(func,synchronous){if(ABORT){err("user callback...
  function safeSetTimeout (line 9) | function safeSetTimeout(func,timeout){return setTimeout(function(){callU...
  function finish (line 9) | function finish(audio){if(done)return;done=true;Module["preloadedAudios"...
  function fail (line 9) | function fail(){if(done)return;done=true;Module["preloadedAudios"][name]...
  function encode64 (line 9) | function encode64(data){var BASE="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkl...
  function pointerLockChange (line 9) | function pointerLockChange(){Browser.pointerLock=document["pointerLockEl...
  function fullscreenChange (line 9) | function fullscreenChange(){Browser.isFullscreen=false;var canvasContain...
  function callRuntimeCallbacks (line 9) | function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var c...
  function demangle (line 9) | function demangle(func){warnOnce("warning: build with  -s DEMANGLE_SUPPO...
  function demangleAll (line 9) | function demangleAll(text){var regex=/\b_Z[\w\d_]+/g;return text.replace...
  function jsStackTrace (line 9) | function jsStackTrace(){var error=new Error;if(!error.stack){try{throw n...
  function stackTrace (line 9) | function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"]...
  function ___cxa_allocate_exception (line 9) | function ___cxa_allocate_exception(size){return _malloc(size+16)+16}
  function _atexit (line 9) | function _atexit(func,arg){}
  function ___cxa_atexit (line 9) | function ___cxa_atexit(a0,a1){return _atexit(a0,a1)}
  function ExceptionInfo (line 9) | function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-16;thi...
  function CatchInfo (line 9) | function CatchInfo(ptr){this.free=function(){_free(this.ptr);this.ptr=0}...
  function exception_addRef (line 9) | function exception_addRef(info){info.add_ref()}
  function ___cxa_begin_catch (line 9) | function ___cxa_begin_catch(ptr){var catchInfo=new CatchInfo(ptr);var in...
  function ___cxa_free_exception (line 9) | function ___cxa_free_exception(ptr){try{return _free(new ExceptionInfo(p...
  function exception_decRef (line 9) | function exception_decRef(info){if(info.release_ref()&&!info.get_rethrow...
  function ___cxa_end_catch (line 9) | function ___cxa_end_catch(){_setThrew(0);assert(exceptionCaught.length>0...
  function ___resumeException (line 9) | function ___resumeException(catchInfoPtr){var catchInfo=new CatchInfo(ca...
  function ___cxa_find_matching_catch_2 (line 9) | function ___cxa_find_matching_catch_2(){var thrown=exceptionLast;if(!thr...
  function ___cxa_find_matching_catch_3 (line 9) | function ___cxa_find_matching_catch_3(){var thrown=exceptionLast;if(!thr...
  function ___cxa_rethrow (line 9) | function ___cxa_rethrow(){var catchInfo=exceptionCaught.pop();if(!catchI...
  function ___cxa_thread_atexit (line 9) | function ___cxa_thread_atexit(a0,a1){return _atexit(a0,a1)}
  function ___cxa_throw (line 9) | function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(pt...
  function setErrNo (line 9) | function setErrNo(value){HEAP32[___errno_location()>>2]=value;return value}
  function getRandomDevice (line 9) | function getRandomDevice(){if(typeof crypto==="object"&&typeof crypto["g...
  function trim (line 9) | function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[sta...
  function zeroMemory (line 9) | function zeroMemory(address,size){HEAPU8.fill(0,address,address+size)}
  function alignMemory (line 9) | function alignMemory(size,alignment){assert(alignment,"alignment argumen...
  function mmapAlloc (line 9) | function mmapAlloc(size){size=alignMemory(size,65536);var ptr=_memalign(...
  function asyncLoad (line 9) | function asyncLoad(url,onload,onerror,noRunDep){var dep=!noRunDep?getUni...
  function doCallback (line 9) | function doCallback(errCode){assert(FS.syncFSRequests>0);FS.syncFSReques...
  function done (line 9) | function done(errCode){if(errCode){if(!done.errored){done.errored=true;r...
  function LazyUint8Array (line 9) | function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}
  function processData (line 9) | function processData(byteArray){function finish(byteArray){if(preFinish)...
  function finish (line 9) | function finish(){if(fail==0)onload();else onerror()}
  function finish (line 9) | function finish(){if(fail==0)onload();else onerror()}
  function ___sys_fcntl64 (line 9) | function ___sys_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var...
  function ___sys_ioctl (line 9) | function ___sys_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var st...
  function syscallMmap2 (line 9) | function syscallMmap2(addr,len,prot,flags,fd,off){off<<=12;var ptr;var a...
  function ___sys_mmap2 (line 9) | function ___sys_mmap2(addr,len,prot,flags,fd,off){try{return syscallMmap...
  function ___sys_open (line 9) | function ___sys_open(path,flags,varargs){SYSCALLS.varargs=varargs;try{va...
  function ___sys_stat64 (line 9) | function ___sys_stat64(path,buf){try{path=SYSCALLS.getStr(path);return S...
  function makeLegalFunctionName (line 9) | function makeLegalFunctionName(name){if(undefined===name){return"_unknow...
  function createNamedFunction (line 9) | function createNamedFunction(name,body){name=makeLegalFunctionName(name)...
  function count_emval_handles (line 9) | function count_emval_handles(){var count=0;for(var i=5;i<emval_handle_ar...
  function get_first_emval (line 9) | function get_first_emval(){for(var i=5;i<emval_handle_array.length;++i){...
  function init_emval (line 9) | function init_emval(){Module["count_emval_handles"]=count_emval_handles;...
  function __emval_register (line 9) | function __emval_register(value){switch(value){case undefined:{return 1}...
  function extendError (line 9) | function extendError(baseErrorType,errorName){var errorClass=createNamed...
  function embind_init_charCodes (line 9) | function embind_init_charCodes(){var codes=new Array(256);for(var i=0;i<...
  function readLatin1String (line 9) | function readLatin1String(ptr){var ret="";var c=ptr;while(HEAPU8[c]){ret...
  function getInheritedInstanceCount (line 9) | function getInheritedInstanceCount(){return Object.keys(registeredInstan...
  function getLiveInheritedInstances (line 9) | function getLiveInheritedInstances(){var rv=[];for(var k in registeredIn...
  function flushPendingDeletes (line 9) | function flushPendingDeletes(){while(deletionQueue.length){var obj=delet...
  function setDelayFunction (line 9) | function setDelayFunction(fn){delayFunction=fn;if(deletionQueue.length&&...
  function init_embind (line 9) | function init_embind(){Module["getInheritedInstanceCount"]=getInheritedI...
  function throwBindingError (line 9) | function throwBindingError(message){throw new BindingError(message)}
  function getBasestPointer (line 9) | function getBasestPointer(class_,ptr){if(ptr===undefined){throwBindingEr...
  function registerInheritedInstance (line 9) | function registerInheritedInstance(class_,ptr,instance){ptr=getBasestPoi...
  function requireHandle (line 9) | function requireHandle(handle){if(!handle){throwBindingError("Cannot use...
  function getTypeName (line 9) | function getTypeName(type){var ptr=___getTypeName(type);var rv=readLatin...
  function requireRegisteredType (line 9) | function requireRegisteredType(rawType,humanName){var impl=registeredTyp...
  function unregisterInheritedInstance (line 9) | function unregisterInheritedInstance(class_,ptr){ptr=getBasestPointer(cl...
  function detachFinalizer (line 9) | function detachFinalizer(handle){}
  function runDestructor (line 9) | function runDestructor($$){if($$.smartPtr){$$.smartPtrType.rawDestructor...
  function releaseClassHandle (line 9) | function releaseClassHandle($$){$$.count.value-=1;var toDelete=0===$$.co...
  function attachFinalizer (line 9) | function attachFinalizer(handle){if("undefined"===typeof FinalizationGro...
  function __embind_create_inheriting_constructor (line 9) | function __embind_create_inheriting_constructor(constructorName,wrapperT...
  function runDestructors (line 9) | function runDestructors(destructors){while(destructors.length){var ptr=d...
  function simpleReadValueFromPointer (line 9) | function simpleReadValueFromPointer(pointer){return this["fromWireType"]...
  function throwInternalError (line 9) | function throwInternalError(message){throw new InternalError(message)}
  function whenDependentTypesAreResolved (line 9) | function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeCon...
  function __embind_finalize_value_object (line 9) | function __embind_finalize_value_object(structType){var reg=structRegist...
  function __embind_register_bigint (line 9) | function __embind_register_bigint(primitiveType,name,size,minRange,maxRa...
  function getShiftFromSize (line 9) | function 
Condensed preview — 173 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,568K chars).
[
  {
    "path": ".eslintrc.js",
    "chars": 309,
    "preview": "module.exports = {\n  env: {\n    browser: true,\n    commonjs: true,\n    es2021: true,\n    node: true,\n  },\n  extends: [\"p"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 2145,
    "preview": "name: Build App\n\non:\n  workflow_dispatch:\n    inputs:\n      version:\n        description: \"Version label (e.g. v1.2.3)\"\n"
  },
  {
    "path": ".gitignore",
    "chars": 265,
    "preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\nnode_modules\n/npm-"
  },
  {
    "path": "LICENSE",
    "chars": 35149,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
  },
  {
    "path": "README-CN.md",
    "chars": 3265,
    "preview": "# Hime Display\n\n<p align=\"center\">\n<img width=\"200px\" src=\"./images/icon.png\">\n</p>\n\n> illustrated by [MakoSaikou](https"
  },
  {
    "path": "README-JP.md",
    "chars": 4205,
    "preview": "# Hime Display\n\n<p align=\"center\">\n<img width=\"200px\" src=\"./images/icon.png\">\n</p>\n\n> illustrated by [MakoSaikou](https"
  },
  {
    "path": "README.md",
    "chars": 5752,
    "preview": "# Hime Display\n\n<p align=\"center\">\n<img width=\"200px\" src=\"./images/icon.png\">\n</p>\n\n> illustrated by [MakoSaikou](https"
  },
  {
    "path": "build.config.js",
    "chars": 1570,
    "preview": "/**\n * @type {import('electron-builder').CliOptions}\n * {@link https://www.electron.build/configuration/configuration}\n "
  },
  {
    "path": "package.json",
    "chars": 1010,
    "preview": "{\n  \"name\": \"hime-display\",\n  \"version\": \"1.2.0\",\n  \"description\": \"A universal desktop model displayer for Live2D, Spin"
  },
  {
    "path": "scripts/build.js",
    "chars": 2305,
    "preview": "const path = require(\"path\");\nconst chalk = require(\"chalk\");\nconst ListR = require(\"listr\");\nconst builder = require(\"e"
  },
  {
    "path": "scripts/constants.js",
    "chars": 394,
    "preview": "const path = require(\"path\");\n\nmodule.exports = {\n  MAIN_ROOT: path.resolve(__dirname, \"../src/main\"),\n  // MAIN_PRELOAD"
  },
  {
    "path": "scripts/dev-runner.js",
    "chars": 2921,
    "preview": "const path = require(\"path\");\nconst chalk = require(\"chalk\");\nconst electron = require(\"electron\");\nconst { spawn } = re"
  },
  {
    "path": "src/main/Application.js",
    "chars": 7250,
    "preview": "import { EventEmitter } from \"events\";\nimport { WindowManager } from \"./ui/WindowManager\";\nimport { ThemeManager } from "
  },
  {
    "path": "src/main/Launcher.js",
    "chars": 1569,
    "preview": "import { EventEmitter } from \"events\";\nimport { app } from \"electron\";\n// import is from \"electron-is\";\nimport { Excepti"
  },
  {
    "path": "src/main/core/ExceptionHandler.js",
    "chars": 502,
    "preview": "import { app, dialog } from \"electron\";\nimport { logger } from \"./Logger\";\nimport is from \"electron-is\";\nexport class Ex"
  },
  {
    "path": "src/main/core/Logger.js",
    "chars": 97,
    "preview": "import logger from \"electron-log\";\nlogger.info(\"[Hime Display] Logger init\");\nexport { logger };\n"
  },
  {
    "path": "src/main/index.js",
    "chars": 55,
    "preview": "import { Launcher } from \"./Launcher\";\nnew Launcher();\n"
  },
  {
    "path": "src/main/menus/tray.js",
    "chars": 246,
    "preview": "export const trayMenuTemplate = [\n  { locale: \"tray.open-control-window\", event: \"tray:open-control-window\" },\n  { local"
  },
  {
    "path": "src/main/options/paths.js",
    "chars": 341,
    "preview": "import { app } from \"electron\";\nimport { resolve } from \"path\";\nexport const APP_DATA_PATH = app.getPath(\"userData\");\nex"
  },
  {
    "path": "src/main/options/windows.js",
    "chars": 2441,
    "preview": "import { resolve } from \"path\";\nimport { DEV_SERVER_PORT } from \"@shared/constants\";\nexport const windowsOptions = {\n  c"
  },
  {
    "path": "src/main/package.json",
    "chars": 274,
    "preview": "{\n  \"name\": \"@app/main\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"electron\": \"^35.2.1\",\n    \"electron-is\": \"^3.0.0"
  },
  {
    "path": "src/main/ui/ThemeManager.js",
    "chars": 442,
    "preview": "import { nativeTheme } from \"electron\";\nimport { EventEmitter } from \"events\";\nexport class ThemeManager extends EventEm"
  },
  {
    "path": "src/main/ui/TrayManager.js",
    "chars": 1005,
    "preview": "import i18next from \"@shared/locales/i18next\";\nimport { trayMenuTemplate } from \"../menus/tray\";\nimport { Tray, Menu } f"
  },
  {
    "path": "src/main/ui/WindowManager.js",
    "chars": 4144,
    "preview": "import { EventEmitter } from \"events\";\nimport { windowsOptions } from \"../options/windows\";\nimport { BrowserWindow } fro"
  },
  {
    "path": "src/main/vite.config.js",
    "chars": 602,
    "preview": "import { resolve } from \"path\";\nimport { defineConfig } from \"vite\";\nimport autoExternal from \"rollup-plugin-auto-extern"
  },
  {
    "path": "src/preload/control/config.js",
    "chars": 837,
    "preview": "// 几经考虑,还是把配置数据库也搬到控制面板了,IPC通信实在是麻烦了,不如直接在控制面板的preload中加载数据库\nimport low from \"lowdb\";\nimport lowFileSync from \"lowdb/ada"
  },
  {
    "path": "src/preload/control/database.js",
    "chars": 10002,
    "preview": "// 由于数据库仅在控制面板使用而不在主进程以及展示器使用,决定直接在控制面板的preload中加载数据库,减少IPC通信,优化性能\nimport low from \"lowdb\";\nimport lowFileSync from \"low"
  },
  {
    "path": "src/preload/control/index.js",
    "chars": 426,
    "preview": "import { contextBridge } from \"electron\";\nimport { shell } from \"electron\";\nimport * as database from \"./database\";\nimpo"
  },
  {
    "path": "src/preload/control/ipc.js",
    "chars": 1935,
    "preview": "import { ipcRenderer } from \"electron\";\nexport function selectPath() {\n  return ipcRenderer.invoke(\"control2main:select-"
  },
  {
    "path": "src/preload/control/paths.js",
    "chars": 312,
    "preview": "import { ipcRenderer } from \"electron\";\n// console.time(\"control:query-database-path\");\n// 应用的许多后续操作必须要等到数据库加载完成,若使用异步请求"
  },
  {
    "path": "src/preload/control/theme.js",
    "chars": 944,
    "preview": "import { ipcRenderer } from \"electron\";\n// document.addEventListener(\"DOMContentLoaded\", () => {\n//   ipcRenderer.invoke"
  },
  {
    "path": "src/preload/control/utils.js",
    "chars": 3283,
    "preview": "export function detectSpineVersionFromBinary(dataToParse) {\n  const versionOld = readSpineVersionOldFormat(dataToParse);"
  },
  {
    "path": "src/preload/control/vite.config.js",
    "chars": 617,
    "preview": "import { resolve } from \"path\";\nimport { defineConfig } from \"vite\";\nimport autoExternal from \"rollup-plugin-auto-extern"
  },
  {
    "path": "src/preload/display/index.js",
    "chars": 128,
    "preview": "import { contextBridge } from \"electron\";\nimport * as ipc from \"./ipc\";\ncontextBridge.exposeInMainWorld(\"nodeAPI\", {\n  i"
  },
  {
    "path": "src/preload/display/ipc.js",
    "chars": 1977,
    "preview": "import { ipcRenderer } from \"electron\";\nexport function handleLoadModel(callback) {\n  ipcRenderer.on(\"control2display:lo"
  },
  {
    "path": "src/preload/display/vite.config.js",
    "chars": 526,
    "preview": "import { resolve } from \"path\";\nimport { defineConfig } from \"vite\";\nimport autoExternal from \"rollup-plugin-auto-extern"
  },
  {
    "path": "src/preload/package.json",
    "chars": 218,
    "preview": "{\n  \"name\": \"@app/preload\",\n  \"version\": \"0.0.0\",\n  \"dependencies\": {\n    \"electron\": \"^35.2.1\",\n    \"lowdb\": \"1.0.0\"\n  "
  },
  {
    "path": "src/renderer/control/App.vue",
    "chars": 4313,
    "preview": "<template>\n  <div class=\"drag-area\"></div>\n  <el-config-provider :locale=\"locale\">\n    <el-container>\n      <hime-menu><"
  },
  {
    "path": "src/renderer/control/components/Common/ConfigItem.vue",
    "chars": 1064,
    "preview": "<template>\n  <div\n    class=\"hime-config-item\"\n    :class=\"{ 'hime-config-item--top': labelPosition === 'top' }\"\n  >\n   "
  },
  {
    "path": "src/renderer/control/components/Common/SvgIcon.vue",
    "chars": 556,
    "preview": "<template>\n  <svg aria-hidden=\"true\">\n    <use :xlink:href=\"symbolId\" :fill=\"color\" />\n  </svg>\n</template>\n\n<script>\nim"
  },
  {
    "path": "src/renderer/control/components/Common/SvgIconElButton.vue",
    "chars": 426,
    "preview": "<template>\n  <el-button>\n    <svg-icon :name=\"name\" class=\"hime-el-svg-icon\"></svg-icon>\n  </el-button>\n</template>\n\n<sc"
  },
  {
    "path": "src/renderer/control/components/Common/TitleWithDivider.vue",
    "chars": 169,
    "preview": "<template>\n  <div style=\"font-size: 2rem\"><slot></slot></div>\n  <el-divider class=\"hime-el-divider\" />\n</template>\n\n<scr"
  },
  {
    "path": "src/renderer/control/components/Contents/About.vue",
    "chars": 3970,
    "preview": "<template>\n  <div class=\"hime-content\">\n    <hime-title-with-divider>{{ $t(\"menu.about\") }}</hime-title-with-divider>\n  "
  },
  {
    "path": "src/renderer/control/components/Contents/Control/Common/2d/EventAnimation.vue",
    "chars": 2370,
    "preview": "<template>\n  <config-item :label=\"$t('control.animation.event-motion')\">\n    <el-select v-model=\"eventSelected\" style=\"w"
  },
  {
    "path": "src/renderer/control/components/Contents/Control/Common/2d/Transform2D.vue",
    "chars": 1486,
    "preview": "<template>\n  <config-item label=\"x\">\n    <el-input-number\n      :precision=\"2\"\n      :step=\"10\"\n      v-model=\"transform"
  },
  {
    "path": "src/renderer/control/components/Contents/Control/Common/3d/AnimationControl.vue",
    "chars": 6894,
    "preview": "<template>\n  <el-scrollbar max-height=\"400px\">\n    <el-collapse class=\"hime-control-collapse\">\n      <el-collapse-item\n "
  },
  {
    "path": "src/renderer/control/components/Contents/Control/Common/3d/ObjectTransform3D.vue",
    "chars": 2467,
    "preview": "<template>\n  <config-item :label=\"$t('control.transform.tree-select')\">\n    <el-tree-select\n      :data=\"[transformInfo."
  },
  {
    "path": "src/renderer/control/components/Contents/Control/Common/3d/ParameterControl.vue",
    "chars": 2922,
    "preview": "<template>\n  <config-item :label=\"$t('control.parameter.morph')\" label-position=\"top\">\n    <config-item :label=\"$t('cont"
  },
  {
    "path": "src/renderer/control/components/Contents/Control/Common/3d/Transform3D.vue",
    "chars": 1889,
    "preview": "<template>\n  <!-- 遇到一个坑,如果template下级有多个元素的话,下方的input事件就会无法正确向上传递 -->\n  <div class=\"hime-transform--3d\">\n    <config-item"
  },
  {
    "path": "src/renderer/control/components/Contents/Control/Common/ControlLoadError.vue",
    "chars": 114,
    "preview": "<template>{{ $t(\"control.control-load-error\") }}</template>\n\n<script setup></script>\n\n<style lang=\"scss\"></style>\n"
  },
  {
    "path": "src/renderer/control/components/Contents/Control/Common/ModelDescription.vue",
    "chars": 466,
    "preview": "<template>\n  <el-descriptions border size=\"small\" direction=\"vertical\" :column=\"5\">\n    <el-descriptions-item\n      alig"
  },
  {
    "path": "src/renderer/control/components/Contents/Control/Common/MotionCapture.vue",
    "chars": 1526,
    "preview": "<template>\n  <config-item\n    :label=\"$t('control.capture.capture-type')\"\n    v-if=\"modelType == 'MMD' || modelType == '"
  },
  {
    "path": "src/renderer/control/components/Contents/Control/Live2DControl/AnimationControl.vue",
    "chars": 2284,
    "preview": "<template>\n  <el-table\n    :data=\"motions\"\n    :border=\"true\"\n    @current-change=\"changeCurrentMotion\"\n    highlight-cu"
  },
  {
    "path": "src/renderer/control/components/Contents/Control/Live2DControl/ParameterControl.vue",
    "chars": 4664,
    "preview": "<template>\n  <config-item label=\"Parameter\" label-position=\"top\">\n    <config-item :label=\"$t('control.parameter.target-"
  },
  {
    "path": "src/renderer/control/components/Contents/Control/Live2DControl/index.vue",
    "chars": 2157,
    "preview": "<template>\n  <div class=\"hime-model-control\">\n    <el-tabs type=\"border-card\">\n      <el-tab-pane :label=\"$t(`control.mo"
  },
  {
    "path": "src/renderer/control/components/Contents/Control/MMDControl/index.vue",
    "chars": 2639,
    "preview": "<template>\n  <div class=\"hime-model-control\">\n    <!-- 弃用方案:使用Menu组件构建 -->\n    <!-- <el-menu\n      @select=\"handleSelect"
  },
  {
    "path": "src/renderer/control/components/Contents/Control/SpineControl/AnimationControl.vue",
    "chars": 2385,
    "preview": "<template>\n  <el-scrollbar max-height=\"400px\">\n    <config-item\n      :label=\"$t('control.animation.motion-db')\"\n      l"
  },
  {
    "path": "src/renderer/control/components/Contents/Control/SpineControl/ParameterControl.vue",
    "chars": 751,
    "preview": "<template>\n  <config-item :label=\"$t('control.parameter.skin')\">\n    <el-select v-model=\"selectedSkin\" @change=\"setSkin\""
  },
  {
    "path": "src/renderer/control/components/Contents/Control/SpineControl/index.vue",
    "chars": 2005,
    "preview": "<template>\n  <div class=\"hime-model-control\">\n    <el-tabs type=\"border-card\">\n      <el-tab-pane :label=\"$t(`control.mo"
  },
  {
    "path": "src/renderer/control/components/Contents/Control/VRoidControl/index.vue",
    "chars": 2695,
    "preview": "<template>\n  <div class=\"hime-model-control\">\n    <!-- 弃用方案:使用Menu组件构建 -->\n    <!-- <el-menu\n      @select=\"handleSelect"
  },
  {
    "path": "src/renderer/control/components/Contents/Control/index.vue",
    "chars": 1782,
    "preview": "<template>\n  <div class=\"hime-content\">\n    <hime-title-with-divider>{{ $t(\"menu.control\") }}</hime-title-with-divider>\n"
  },
  {
    "path": "src/renderer/control/components/Contents/Display.vue",
    "chars": 11764,
    "preview": "<template>\n  <div class=\"hime-content\">\n    <!-- <el-form label-position=\"top\" class=\"hime-el-form--large-label\"> -->\n  "
  },
  {
    "path": "src/renderer/control/components/Contents/General.vue",
    "chars": 3241,
    "preview": "<template>\n  <div class=\"hime-content\">\n    <hime-title-with-divider>{{ $t(\"menu.general\") }}</hime-title-with-divider>\n"
  },
  {
    "path": "src/renderer/control/components/Contents/Model.vue",
    "chars": 6782,
    "preview": "<template>\n  <div class=\"hime-content\">\n    <hime-title-with-divider>{{ $t(\"menu.model\") }}</hime-title-with-divider>\n  "
  },
  {
    "path": "src/renderer/control/components/Contents/Source.vue",
    "chars": 9152,
    "preview": "<template>\n  <div class=\"hime-content\">\n    <hime-title-with-divider>{{ $t(\"menu.source\") }}</hime-title-with-divider>\n "
  },
  {
    "path": "src/renderer/control/components/Main.vue",
    "chars": 2129,
    "preview": "<template>\n  <el-main\n    v-loading=\"\n      controlStore.modelControlInfoLoading &&\n      contentComponentNow === HimeCo"
  },
  {
    "path": "src/renderer/control/components/Menu/Index.vue",
    "chars": 429,
    "preview": "<template>\n  <el-aside>\n    <div class=\"menu\">\n      <hime-menu-item\n        v-for=\"menuItem in menuItems\"\n        :menu"
  },
  {
    "path": "src/renderer/control/components/Menu/MenuItem.vue",
    "chars": 1654,
    "preview": "<template>\n  <div\n    class=\"menu-item\"\n    :class=\"{ active: appStore.ui.activeMenuItem === menuItem }\"\n    @click=\"app"
  },
  {
    "path": "src/renderer/control/i18n.js",
    "chars": 170,
    "preview": "import i18next from \"@shared/locales/i18next\";\nimport I18NextVue from \"i18next-vue\";\n\nexport default function (app) {\n  "
  },
  {
    "path": "src/renderer/control/main.js",
    "chars": 573,
    "preview": "import { createApp } from \"vue\";\nimport { createPinia } from \"pinia\";\nimport App from \"./App.vue\";\nimport i18n from \"./i"
  },
  {
    "path": "src/renderer/control/store/app.js",
    "chars": 1591,
    "preview": "import { defineStore } from \"pinia\";\nexport const useAppStore = defineStore(\"app\", {\n  state: () => ({\n    // initialize"
  },
  {
    "path": "src/renderer/control/store/control.js",
    "chars": 228,
    "preview": "// 对模型进行控制的Store\nimport { defineStore } from \"pinia\";\nexport const useControlStore = defineStore(\"control\", {\n  state: ("
  },
  {
    "path": "src/renderer/control/styles/el-theme.scss",
    "chars": 1562,
    "preview": "// 颜色主题配置预留\n// $--colors: (\n//   \"primary\": (\n//     \"base\": purple,\n//   ),\n//   \"success\": (\n//     \"base\": #21ba45,\n/"
  },
  {
    "path": "src/renderer/control.html",
    "chars": 342,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n\t<meta charset=\"UTF-8\">\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n"
  },
  {
    "path": "src/renderer/display/Application.js",
    "chars": 7455,
    "preview": "import { Live2dManager } from \"@display/modelManagers/Live2dManager\";\nimport { MmdManager } from \"@display/modelManagers"
  },
  {
    "path": "src/renderer/display/main.js",
    "chars": 384,
    "preview": "import { Application } from \"@display/Application\";\nwindow.app = new Application();\nconst ipcAPI = window.nodeAPI.ipc;\nw"
  },
  {
    "path": "src/renderer/display/modelManagers/Live2dManager.js",
    "chars": 13750,
    "preview": "import { ModelManager } from \"./ModelManager\";\nimport { ParameterMonitor, PartMonitor } from \"@display/utils/live2d/Moni"
  },
  {
    "path": "src/renderer/display/modelManagers/MmdManager.js",
    "chars": 14270,
    "preview": "import { ModelManager3D } from \"./ModelManager3D\";\nimport * as THREE from \"three\";\nimport { MMDLoader } from \"three/exam"
  },
  {
    "path": "src/renderer/display/modelManagers/ModelManager.js",
    "chars": 309,
    "preview": "// 所有管理器的祖先\nexport class ModelManager {\n  constructor(parentApp) {\n    this.config = parentApp.config;\n    this.stats = "
  },
  {
    "path": "src/renderer/display/modelManagers/ModelManager3D.js",
    "chars": 4053,
    "preview": "// 统筹两个3D模型公用的功能\nimport { ModelManager } from \"./ModelManager\";\nimport { OrbitControls } from \"three/examples/jsm/contro"
  },
  {
    "path": "src/renderer/display/modelManagers/SpineManager.js",
    "chars": 7786,
    "preview": "import { ModelManager } from \"./ModelManager\";\nimport { setModelBaseTransfrom, draggable } from \"@display/utils/2d/utils"
  },
  {
    "path": "src/renderer/display/modelManagers/SpineManager42.js",
    "chars": 2182,
    "preview": "import * as PIXI from \"pixi.js\";\nimport { Spine } from \"@esotericsoftware/spine-pixi-v8\";\nimport { SpineManager } from \""
  },
  {
    "path": "src/renderer/display/modelManagers/VroidManager.js",
    "chars": 7613,
    "preview": "import { ModelManager3D } from \"./ModelManager3D\";\nimport * as THREE from \"three\";\nimport { GLTFLoader } from \"three/exa"
  },
  {
    "path": "src/renderer/display/utils/2d/utils.js",
    "chars": 2324,
    "preview": "export function setModelBaseTransfrom(model, displayConfig, type) {\n  const configWidth =\n    (innerWidth *\n      (displ"
  },
  {
    "path": "src/renderer/display/utils/3d/AudioManager.js",
    "chars": 836,
    "preview": "// MMDAnimationHelper里面自带那个AudioManager……实在是不太行,中途暂停,定位播放之类的直接不可能实现,于是我还是自己写一个吧\nexport class AudioManager {\n  constructo"
  },
  {
    "path": "src/renderer/display/utils/3d/Monitor.js",
    "chars": 1049,
    "preview": "class TransformMonitor {\n  constructor() {\n    this.transform = null;\n    this.isJustBined = false;\n  }\n  bind(target) {"
  },
  {
    "path": "src/renderer/display/utils/3d/MouseFocusHelper.js",
    "chars": 1818,
    "preview": "// Author: TSKI433\nimport { Vector3 } from \"three\";\n// 相机绝对坐标\nconst cameraAbsolutePosition = new Vector3();\n// object 绝对"
  },
  {
    "path": "src/renderer/display/utils/3d/NodeInfo.js",
    "chars": 1331,
    "preview": "function buildNodeInfoTree(node, tree = {}) {\n  let additionalInfo = \"\";\n  if (node.name !== \"\") {\n    additionalInfo +="
  },
  {
    "path": "src/renderer/display/utils/animation/Mixamo2MMDAnimationConverter.js",
    "chars": 12305,
    "preview": "import {\n  Quaternion,\n  Euler,\n  PropertyBinding,\n  Matrix4,\n  Vector3,\n  VectorKeyframeTrack,\n  QuaternionKeyframeTrac"
  },
  {
    "path": "src/renderer/display/utils/animation/Mixamo2MMDAnimationConverterNew.js",
    "chars": 15681,
    "preview": "import {\n  Quaternion,\n  Euler,\n  PropertyBinding,\n  Matrix4,\n  Vector3,\n  VectorKeyframeTrack,\n  QuaternionKeyframeTrac"
  },
  {
    "path": "src/renderer/display/utils/animation/utils.js",
    "chars": 5224,
    "preview": "import {\n  VectorKeyframeTrack,\n  Quaternion,\n  Vector3,\n  Matrix4,\n  Euler,\n} from \"three\";\nconst _q1 = new Quaternion("
  },
  {
    "path": "src/renderer/display/utils/capture/FaceMeshCaptureManager.js",
    "chars": 3486,
    "preview": "import { Face } from \"kalidokit\";\nimport {\n  setTarget,\n  createVideo,\n  onResults,\n  askForMediaAccess,\n} from \"./paren"
  },
  {
    "path": "src/renderer/display/utils/capture/HolisticCaptureManager.js",
    "chars": 5246,
    "preview": "import { Face, Pose, Hand } from \"kalidokit\";\nimport {\n  setTarget,\n  createVideo,\n  onResults,\n  askForMediaAccess,\n} f"
  },
  {
    "path": "src/renderer/display/utils/capture/Live2DFaceMeshCaptureManager.js",
    "chars": 3402,
    "preview": "import { FaceMeshCaptureManager } from \"./FaceMeshCaptureManager.js\";\nimport { Vector, Face } from \"kalidokit\";\nconst { "
  },
  {
    "path": "src/renderer/display/utils/capture/MMDFaceMeshCaptureManager.js",
    "chars": 1498,
    "preview": "import { FaceMeshCaptureManager } from \"./FaceMeshCaptureManager.js\";\n\nimport {\n  rigFace,\n  lerpMorphTargetByName,\n  le"
  },
  {
    "path": "src/renderer/display/utils/capture/MMDHolisticCaptureManager.js",
    "chars": 4422,
    "preview": "import { HolisticCaptureManager } from \"./HolisticCaptureManager.js\";\nimport {\n  rigFace,\n  lerpMorphTargetByName,\n  ler"
  },
  {
    "path": "src/renderer/display/utils/capture/VRoidFaceMeshCaptureManager.js",
    "chars": 1255,
    "preview": "import { FaceMeshCaptureManager } from \"./FaceMeshCaptureManager.js\";\nimport {\n  rigFace,\n  lerpMorphTargetByName,\n  ler"
  },
  {
    "path": "src/renderer/display/utils/capture/VRoidHolisticCaptureManager.js",
    "chars": 5623,
    "preview": "import { HolisticCaptureManager } from \"./HolisticCaptureManager.js\";\nimport {\n  rigFace,\n  lerpMorphTargetByName,\n  ler"
  },
  {
    "path": "src/renderer/display/utils/capture/parents/parents.js",
    "chars": 949,
    "preview": "// 我时候来才知道,原来自己这里在毫不知情的情况下手动实现了mixin……我之前都没听说过这个概念啊,只是想了半天,为了防止不必要的重复,然后就这么写出来了\nfunction setTarget(target) {\n  this.mode"
  },
  {
    "path": "src/renderer/display/utils/capture/rig/3DRig.js",
    "chars": 692,
    "preview": "import { Vector } from \"kalidokit\";\nconst { lerp } = Vector;\nfunction lerpBoneRotationByBone(bone, rotation, lerpRatio, "
  },
  {
    "path": "src/renderer/display/utils/capture/rig/MMDRig.js",
    "chars": 2490,
    "preview": "import { Vector, Face } from \"kalidokit\";\nconst { lerp } = Vector;\nfunction rigFace(riggedFace, lerpRatio = 0.5) {\n  // "
  },
  {
    "path": "src/renderer/display/utils/capture/rig/VRoidRig.js",
    "chars": 1721,
    "preview": "import { Vector, Face } from \"kalidokit\";\nconst { lerp } = Vector;\nfunction rigFace(riggedFace, lerpRatio = 0.5) {\n  con"
  },
  {
    "path": "src/renderer/display/utils/common.js",
    "chars": 471,
    "preview": "export function getCurrentDateString() {\n  const date = new Date();\n  const year = date.getFullYear();\n  const month = S"
  },
  {
    "path": "src/renderer/display/utils/live2d/Cubism2Shim.js",
    "chars": 2865,
    "preview": "export const LIVE2D_VERSION = {\n  CUBISM2: \"Cubism2\",\n  CUBISM4: \"Cubism4\",\n};\n\n// Cubism2只能搞到一个经过混淆的js文件,要想直接控制内部的参数需要费"
  },
  {
    "path": "src/renderer/display/utils/live2d/Monitor.js",
    "chars": 2508,
    "preview": "// 绝了,不知道是谁的锅,这里的live2d渲染系统设定_parameterValues和_partOpacities会发生小数偏移,例如设为0.3,他可能自动变成0.3000078397489这样的,导致我设定的参数变化监测系统直接疯狂"
  },
  {
    "path": "src/renderer/display/utils/mmd/AnimationManager.js",
    "chars": 6596,
    "preview": "import { MMDAnimationHelper } from \"three/examples/jsm/animation/MMDAnimationHelper.js\";\nimport { AudioManager } from \"@"
  },
  {
    "path": "src/renderer/display/utils/mmd/Monitor.js",
    "chars": 953,
    "preview": "class MorphMonitor {\n  constructor() {\n    this.value = 0;\n    this.model = null;\n    this.isJustBined = false;\n  }\n  bi"
  },
  {
    "path": "src/renderer/display/utils/record/RecordManager.js",
    "chars": 895,
    "preview": "import { getCurrentDateString } from \"@display/utils/common\";\n// 尝试过实现录屏\n// 浏览器直接录制出来的webm没有时长信息,要想录制gif之类的更是麻烦,而且原始数据的最"
  },
  {
    "path": "src/renderer/display/utils/spine/premultipliedImageLoader.js",
    "chars": 1251,
    "preview": "// 此图片载入的预乘程序遵循GPL协议来源于https://github.com/HuiDesktop/huidesktop-ng-spine/blob/main/src/premultipliedImageLoader.ts\nexpor"
  },
  {
    "path": "src/renderer/display/utils/vroid/Monitor.js",
    "chars": 957,
    "preview": "import { VRMExpressionPresetName } from \"@pixiv/three-vrm\";\nclass MorphMonitor {\n  constructor() {\n    this.value = 0;\n "
  },
  {
    "path": "src/renderer/display.html",
    "chars": 2156,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n\t<meta charset=\"UTF-8\">\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n"
  },
  {
    "path": "src/renderer/package.json",
    "chars": 741,
    "preview": "{\n  \"name\": \"@app/renderer\",\n  \"version\": \"0.0.0\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"vite build\",\n    \"ser"
  },
  {
    "path": "src/renderer/public/lib/@mediapipe/cdn/camera_utils.js",
    "chars": 7881,
    "preview": "(function(){/*\n\n Copyright The Closure Library Authors.\n SPDX-License-Identifier: Apache-2.0\n*/\n'use strict';function n("
  },
  {
    "path": "src/renderer/public/lib/@mediapipe/cdn/drawing_utils.js",
    "chars": 3797,
    "preview": "(function(){/*\n\n Copyright The Closure Library Authors.\n SPDX-License-Identifier: Apache-2.0\n*/\n'use strict';function h("
  },
  {
    "path": "src/renderer/public/lib/@mediapipe/cdn/face_mesh.js",
    "chars": 64913,
    "preview": "(function(){/*\n\n Copyright The Closure Library Authors.\n SPDX-License-Identifier: Apache-2.0\n*/\n'use strict';var v;funct"
  },
  {
    "path": "src/renderer/public/lib/@mediapipe/cdn/holistic.js",
    "chars": 69028,
    "preview": "(function(){/*\n\n Copyright The Closure Library Authors.\n SPDX-License-Identifier: Apache-2.0\n*/\n'use strict';var x;funct"
  },
  {
    "path": "src/renderer/public/lib/@mediapipe/face_mesh/face_mesh_solution_packed_assets_loader.js",
    "chars": 8928,
    "preview": "\n  var Module = typeof createMediapipeSolutionsPackedAssets !== 'undefined' ? createMediapipeSolutionsPackedAssets : {};"
  },
  {
    "path": "src/renderer/public/lib/@mediapipe/face_mesh/face_mesh_solution_simd_wasm_bin.data",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/renderer/public/lib/@mediapipe/face_mesh/face_mesh_solution_simd_wasm_bin.js",
    "chars": 330166,
    "preview": "\nvar createMediapipeSolutionsWasm = (function() {\n  var _scriptDir = typeof document !== 'undefined' && document.current"
  },
  {
    "path": "src/renderer/public/lib/@mediapipe/face_mesh/face_mesh_solution_wasm_bin.js",
    "chars": 330161,
    "preview": "\nvar createMediapipeSolutionsWasm = (function() {\n  var _scriptDir = typeof document !== 'undefined' && document.current"
  },
  {
    "path": "src/renderer/public/lib/@mediapipe/holistic/holistic_solution_packed_assets_loader.js",
    "chars": 10080,
    "preview": "\n  var Module = typeof createMediapipeSolutionsPackedAssets !== 'undefined' ? createMediapipeSolutionsPackedAssets : {};"
  },
  {
    "path": "src/renderer/public/lib/@mediapipe/holistic/holistic_solution_simd_wasm_bin.data",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/renderer/public/lib/@mediapipe/holistic/holistic_solution_simd_wasm_bin.js",
    "chars": 331605,
    "preview": "\nvar createMediapipeSolutionsWasm = (function() {\n  var _scriptDir = typeof document !== 'undefined' && document.current"
  },
  {
    "path": "src/renderer/public/lib/@mediapipe/holistic/holistic_solution_wasm_bin.js",
    "chars": 331600,
    "preview": "\nvar createMediapipeSolutionsWasm = (function() {\n  var _scriptDir = typeof document !== 'undefined' && document.current"
  },
  {
    "path": "src/renderer/public/lib/spine/pixi-spine.umd.js",
    "chars": 1177538,
    "preview": "/* eslint-disable */\n \n/*!\n * pixi-spine - v3.0.15\n * Compiled Fri, 03 Jun 2022 12:34:36 UTC\n *\n * pixi-spine is license"
  },
  {
    "path": "src/renderer/public/lib/three/ammo.wasm.js",
    "chars": 393753,
    "preview": "\n// This is ammo.js, a port of Bullet Physics to JavaScript. zlib licensed.\n\nvar Ammo = (function() {\n  var _scriptDir ="
  },
  {
    "path": "src/renderer/vite.config.js",
    "chars": 1588,
    "preview": "import { resolve } from \"path\";\nimport { defineConfig } from \"vite\";\nimport vue from \"@vitejs/plugin-vue\";\nimport { DEV_"
  },
  {
    "path": "src/shared/constants.js",
    "chars": 37,
    "preview": "export const DEV_SERVER_PORT = 3000;\n"
  },
  {
    "path": "src/shared/defaults/defalutDatabase.js",
    "chars": 120,
    "preview": "export const defalutDatabase = {\n  modelNow: null,\n  sourcePathInfo: [],\n  model: [],\n  motion3D: [],\n  audio3D: [],\n};\n"
  },
  {
    "path": "src/shared/defaults/defaultConfig.js",
    "chars": 1065,
    "preview": "export const defaultConfig = {\n  general: {\n    \"open-control-at-launch\": true,\n    \"open-display-at-launch\": true,\n    "
  },
  {
    "path": "src/shared/locales/en/control.js",
    "chars": 3302,
    "preview": "export default {\n  \"model-description\": \"Model Description\",\n  \"object-transform\": \"Object Transform\",\n  \"animation-cont"
  },
  {
    "path": "src/shared/locales/en/display.js",
    "chars": 1232,
    "preview": "export default {\n  window: \"Window\",\n  \"window-type\": \"Window Type\",\n  fullscreen: \"Fullscreen\",\n  windowed: \"Windowed\","
  },
  {
    "path": "src/shared/locales/en/general.js",
    "chars": 465,
    "preview": "export default {\n  \"when-launch\": \"When Launch\",\n  \"open-control-panel\": \"Open Control Panel\",\n  \"open-display-window\": "
  },
  {
    "path": "src/shared/locales/en/index.js",
    "chars": 345,
    "preview": "import menu from \"./menu\";\nimport control from \"./control\";\nimport tray from \"./tray\";\nimport message from \"./message\";\n"
  },
  {
    "path": "src/shared/locales/en/menu.js",
    "chars": 142,
    "preview": "export default {\n  general: \"General\",\n  display: \"Display\",\n  control: \"Control\",\n  model: \"Model\",\n  source: \"Source\","
  },
  {
    "path": "src/shared/locales/en/message.js",
    "chars": 354,
    "preview": "export default {\n  \"display-open-dev-title\":\n    \"Are you sure you want to open the developer tools?\",\n  \"display-open-d"
  },
  {
    "path": "src/shared/locales/en/model.js",
    "chars": 214,
    "preview": "export default {\n  \"model-db\": \"Model Database\",\n  \"search-model\": \"Search Model\",\n  name: \"Name\",\n  type: \"Type\",\n  ext"
  },
  {
    "path": "src/shared/locales/en/source.js",
    "chars": 488,
    "preview": "export default {\n  \"data-source\": \"Data Source\",\n  \"search-type\": \"Search Type\",\n  \"source-path\": \"Source Path\",\n  opera"
  },
  {
    "path": "src/shared/locales/en/tray.js",
    "chars": 142,
    "preview": "export default {\n  \"open-control-window\": \"Open Control Window\",\n  \"open-display-window\": \"Open Display Window\",\n  \"quit"
  },
  {
    "path": "src/shared/locales/i18next.js",
    "chars": 156,
    "preview": "import i18next from \"i18next\";\nimport resources from \"./resources\";\ni18next.init({\n  fallbackLng: \"en\",\n  resources: res"
  },
  {
    "path": "src/shared/locales/jp/control.js",
    "chars": 2751,
    "preview": "// 片假名这……您怎么能这么长呢?\nexport default {\n  \"model-description\": \"モデル情報\",\n  \"object-transform\": \"オブジェクト変換\",\n  \"animation-contr"
  },
  {
    "path": "src/shared/locales/jp/display.js",
    "chars": 1032,
    "preview": "export default {\n  window: \"ウィンドウ\",\n  \"window-type\": \"ジャンル\",\n  fullscreen: \"フルスクリーン\",\n  windowed: \"ウィンドウ\",\n  show: \"表示\","
  },
  {
    "path": "src/shared/locales/jp/general.js",
    "chars": 383,
    "preview": "export default {\n  \"when-launch\": \"起動した時\",\n  \"open-control-panel\": \"コントロールパネルを開く\",\n  \"open-display-window\": \"ディスプレイウィンドウ"
  },
  {
    "path": "src/shared/locales/jp/index.js",
    "chars": 345,
    "preview": "import menu from \"./menu\";\nimport control from \"./control\";\nimport tray from \"./tray\";\nimport message from \"./message\";\n"
  },
  {
    "path": "src/shared/locales/jp/menu.js",
    "chars": 127,
    "preview": "export default {\n  general: \"一般\",\n  display: \"ディスプレイ\",\n  control: \"コントロール\",\n  model: \"モデル\",\n  source: \"ソース\",\n  about: \"情"
  },
  {
    "path": "src/shared/locales/jp/message.js",
    "chars": 230,
    "preview": "export default {\n  \"display-open-dev-title\": \"本当に開発者ツールを開きますか?\",\n  \"display-open-dev-detail\":\n    \"透明なディスプレイウィンドウについては、開"
  },
  {
    "path": "src/shared/locales/jp/model.js",
    "chars": 187,
    "preview": "export default {\n  \"model-db\": \"モデルデータベース\",\n  \"search-model\": \"モデルを検索\",\n  name: \"名前\",\n  type: \"ジャンル\",\n  extension: \"拡張子\""
  },
  {
    "path": "src/shared/locales/jp/source.js",
    "chars": 398,
    "preview": "export default {\n  \"data-source\": \"データソース\",\n  \"search-type\": \"検索ジャンル\",\n  \"source-path\": \"データソースパス\",\n  operate: \"操作\",\n  \""
  },
  {
    "path": "src/shared/locales/jp/tray.js",
    "chars": 130,
    "preview": "export default {\n  \"open-control-window\": \"コントロールウィンドウを開く\",\n  \"open-display-window\": \"ディスプレイウィンドウを開く\",\n  \"quit-app\": \"アプ"
  },
  {
    "path": "src/shared/locales/languageNames.js",
    "chars": 67,
    "preview": "export default {\n  English: \"en\",\n  简体中文: \"zh-CN\",\n  日本語: \"jp\",\n};\n"
  },
  {
    "path": "src/shared/locales/resources.js",
    "chars": 311,
    "preview": "import appLocaleEn from \"./en\";\nimport appLocaleJp from \"./jp\";\nimport appLocaleZhCN from \"./zh-CN\";\nexport default {\n  "
  },
  {
    "path": "src/shared/locales/zh-CN/control.js",
    "chars": 2474,
    "preview": "export default {\n  \"model-description\": \"模型信息\",\n  \"object-transform\": \"对象变换\",\n  \"animation-control\": \"动画控制\",\n  \"morph-ta"
  },
  {
    "path": "src/shared/locales/zh-CN/display.js",
    "chars": 953,
    "preview": "export default {\n  window: \"窗口\",\n  \"window-type\": \"类型\",\n  fullscreen: \"全屏\",\n  windowed: \"窗口\",\n  show: \"显示\",\n  \"pixel-rat"
  },
  {
    "path": "src/shared/locales/zh-CN/general.js",
    "chars": 346,
    "preview": "export default {\n  \"when-launch\": \"启动时\",\n  \"open-control-panel\": \"打开控制面板\",\n  \"open-display-window\": \"打开展示器\",\n  language:"
  },
  {
    "path": "src/shared/locales/zh-CN/index.js",
    "chars": 345,
    "preview": "import menu from \"./menu\";\nimport control from \"./control\";\nimport tray from \"./tray\";\nimport message from \"./message\";\n"
  },
  {
    "path": "src/shared/locales/zh-CN/menu.js",
    "chars": 117,
    "preview": "export default {\n  general: \"通用\",\n  display: \"展示\",\n  control: \"控制\",\n  model: \"模型\",\n  source: \"来源\",\n  about: \"关于\",\n};\n"
  },
  {
    "path": "src/shared/locales/zh-CN/message.js",
    "chars": 180,
    "preview": "export default {\n  \"display-open-dev-title\": \"您确定要打开开发者工具吗?\",\n  \"display-open-dev-detail\":\n    \"对于透明的展示器窗口,请确保开发者工具窗口设置为"
  },
  {
    "path": "src/shared/locales/zh-CN/model.js",
    "chars": 169,
    "preview": "export default {\n  \"model-db\": \"模型数据库\",\n  \"search-model\": \"搜索模型\",\n  name: \"名称\",\n  type: \"类型\",\n  extension: \"扩展名\",\n  \"loa"
  },
  {
    "path": "src/shared/locales/zh-CN/source.js",
    "chars": 374,
    "preview": "export default {\n  \"data-source\": \"数据源\",\n  \"search-type\": \"检索类型\",\n  \"source-path\": \"数据源路径\",\n  operate: \"操作\",\n  \"end-edit"
  },
  {
    "path": "src/shared/locales/zh-CN/tray.js",
    "chars": 111,
    "preview": "export default {\n  \"open-control-window\": \"打开控制面板\",\n  \"open-display-window\": \"打开展示器\",\n  \"quit-app\": \"退出应用\",\n};\n"
  }
]

// ... and 13 more files (download for full content)

About this extraction

This page contains the full source code of the TSKI433/hime-display GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 173 files (45.8 MB), approximately 864.0k tokens, and a symbol index with 2557 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!