Compare commits
180 commits
Author | SHA1 | Date | |
---|---|---|---|
7c66950280 | |||
fe209f9061 | |||
|
83a57c145c | ||
|
199799f1c2 | ||
|
6fe8539461 | ||
|
56e4955c54 | ||
|
012f2a213a | ||
|
3eed13a162 | ||
|
b228c4e76c | ||
|
a960456c6e | ||
|
ab108f8a60 | ||
|
142b5de5af | ||
|
dc0d6fe267 | ||
|
73b5c0501d | ||
|
e76729ce62 | ||
|
5def0e8be1 | ||
|
582fb101cf | ||
|
ae341d144e | ||
|
13f14757be | ||
|
d7f25f9ae5 | ||
|
0c03676f20 | ||
|
895c9466d7 | ||
|
4cb7e8a9aa | ||
|
140b66862a | ||
|
d74affe0b9 | ||
|
a5ed554c68 | ||
|
34b2f9d881 | ||
|
58e4a21aa6 | ||
|
fec1d1fdd4 | ||
|
c04a89396c | ||
|
97b485284e | ||
|
09c2ed6b30 | ||
|
d6dfab1805 | ||
|
42a95b32a2 | ||
|
3ebc7a93d4 | ||
|
3505251ad2 | ||
|
662ada181a | ||
|
783fd0b304 | ||
|
cbb89d442f | ||
|
5adb11f374 | ||
|
fa8bb20fe2 | ||
|
43747bd8a1 | ||
|
e873e4c665 | ||
|
86d0200441 | ||
|
cef614f9f6 | ||
|
1428b250e6 | ||
|
07f68f6ab7 | ||
|
c67835d350 | ||
|
9538097a6f | ||
|
8e9e887344 | ||
|
bcba146be9 | ||
|
1212d7dfd8 | ||
|
3d3811f3b1 | ||
|
4df8b1e6fd | ||
|
c9d8de8971 | ||
|
db1aabe3c2 | ||
|
941174d0ea | ||
|
8c85209d53 | ||
|
ef165e29df | ||
|
28831a7ff0 | ||
|
d2a0d9299f | ||
|
eecdd8c331 | ||
|
0b2a526e3d | ||
|
a0069b6a3f | ||
|
59f0d9fe11 | ||
|
513e63193e | ||
|
e707fa20f2 | ||
|
2c61df578a | ||
|
d1c25a8eca | ||
|
16f0a1a030 | ||
|
697459b61d | ||
|
2088a5ec1c | ||
|
3a98ba9012 | ||
|
f9f0ff84fb | ||
|
d126a2b589 | ||
|
6682233079 | ||
|
ecfc521a87 | ||
|
dc290652e0 | ||
|
63102eccd6 | ||
|
2fc906b5ae | ||
|
331dc1f5c4 | ||
|
ced402a4c6 | ||
|
06ed730cd1 | ||
|
945201026e | ||
|
43ffc0bd36 | ||
|
6fedab9a22 | ||
|
6a8d3a8197 | ||
|
fb868a2d77 | ||
|
7cbe4333aa | ||
|
91b2ade693 | ||
|
c543cc0899 | ||
|
a2d230666b | ||
|
93fb8cf471 | ||
|
ee6d6c7bcc | ||
|
2cdbd029b6 | ||
|
59f365b16d | ||
|
e0c6621abc | ||
|
cd1c3fef94 | ||
|
7f871efccb | ||
|
902beeedcf | ||
|
87911bb9fd | ||
|
b74b007186 | ||
|
6d995cee9b | ||
|
bfb827b736 | ||
|
8d274c013f | ||
|
144b835c53 | ||
|
fc1e192087 | ||
|
5d4d88d11e | ||
|
60fb1a246e | ||
|
5a3907bf56 | ||
|
f0310d4a63 | ||
|
19e5e681e5 | ||
|
2228f78117 | ||
|
8164aae151 | ||
|
80148c7176 | ||
|
c4adcc2963 | ||
|
06ff213691 | ||
|
d6dacf039e | ||
|
9174cff7f0 | ||
|
571ff8e328 | ||
|
61b1789d4b | ||
|
4f0e8716f2 | ||
|
d5210cf230 | ||
|
1b9b980121 | ||
|
b88d62ecc1 | ||
|
a14a9dc3a4 | ||
|
49cb69f2b8 | ||
|
4093ec17af | ||
|
1454714343 | ||
|
c3c9936c67 | ||
|
dcba9ececd | ||
|
6ee76f80d1 | ||
|
56d53d2693 | ||
|
ae1c7e8d9a | ||
|
5cf07c7f91 | ||
|
c42909d028 | ||
|
f9a14c0d56 | ||
|
31c5ad6b95 | ||
|
4f459f5a06 | ||
|
22fe7f2963 | ||
|
8054a808a6 | ||
|
0c47866e3d | ||
|
26620cd1d4 | ||
|
a508677b1d | ||
|
30a01b7061 | ||
|
603df4defa | ||
|
b00c644099 | ||
|
1c081f2011 | ||
|
a5a864926a | ||
|
7a399daaff | ||
|
7b03678b8e | ||
|
9be5faecff | ||
|
7766ae39e9 | ||
|
61cbbbf08a | ||
|
7411ddaeef | ||
|
885695e705 | ||
|
2aa18da255 | ||
|
40e8824eca | ||
|
d6d27ae8b3 | ||
|
143e5cf79b | ||
|
871a6ed9b7 | ||
|
9bed66ecfc | ||
|
4d8f5ef150 | ||
|
0148580bd2 | ||
|
ae68ab3a6f | ||
|
d28849a533 | ||
|
a366c7cffe | ||
|
e184295c9e | ||
|
1ecb2cc369 | ||
|
0b293d2af0 | ||
|
ff6a51ffa4 | ||
|
cdf4556e23 | ||
|
ba3a7afef3 | ||
|
4ec5238abb | ||
|
f232de68c9 | ||
|
ea704c8ef7 | ||
|
9f06dcf9ac | ||
|
0b6d61e3f1 | ||
|
11c2868b90 | ||
|
bc052360cd |
160
.github/workflows/main.yml
vendored
|
@ -1,160 +0,0 @@
|
|||
name: Build Porymap
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- '*'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-qt5-linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Cache Qt
|
||||
id: cache-qt
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ../Qt
|
||||
key: ${{ runner.os }}-QtCache
|
||||
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v2
|
||||
with:
|
||||
version: '5.14.2'
|
||||
modules: 'qtwidgets qtqml'
|
||||
cached: ${{ steps.cache-qt.outputs.cache-hit }}
|
||||
|
||||
- name: Configure
|
||||
run: qmake porymap.pro
|
||||
|
||||
- name: Compile
|
||||
run: make
|
||||
|
||||
build-macos:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Cache Qt
|
||||
id: cache-qt
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
path: ../Qt
|
||||
key: ${{ runner.os }}-QtCache
|
||||
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
version: '6.2.*'
|
||||
cached: ${{ steps.cache-qt.outputs.cache-hit }}
|
||||
|
||||
- name: Configure
|
||||
run: qmake -config release porymap.pro
|
||||
|
||||
- name: Compile
|
||||
run: make
|
||||
|
||||
- name: Create Disk Image
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: macdeployqt porymap.app -dmg
|
||||
|
||||
- name: Prep Release Directory
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: |
|
||||
mkdir porymap-macOS-${{ github.ref_name }}
|
||||
cp porymap.dmg porymap-macOS-${{ github.ref_name }}/porymap.dmg
|
||||
cp RELEASE-README.txt porymap-macOS-${{ github.ref_name }}/README.txt
|
||||
|
||||
- name: Bundle Release Directory
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: zip -r porymap-macOS-${{ github.ref_name }}.zip porymap-macOS-${{ github.ref_name }}
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: porymap-macOS-${{ github.ref_name }}.zip
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
build-static-windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: dsaltares/fetch-gh-release-asset@master
|
||||
if: steps.cache-static-qt.outputs.cache-hit != 'true'
|
||||
with:
|
||||
repo: 'huderlem/porymap'
|
||||
version: 'tags/qt-static-6.0.1-windows'
|
||||
file: 'Qt-Static-Windows-mingw-6.0.1.zip'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Unzip Static Qt
|
||||
if: steps.cache-static-qt.outputs.cache-hit != 'true'
|
||||
run: powershell.exe -Command "Expand-Archive -Path Qt-Static-Windows-mingw-6.0.1.zip -DestinationPath ../Qt"
|
||||
|
||||
- uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
repo: 'huderlem/porymap'
|
||||
version: 'tags/qt-static-6.0.1-windows'
|
||||
file: 'mingw810_64.zip'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Unzip mingw
|
||||
run: powershell.exe -Command "Expand-Archive -Path mingw810_64.zip -DestinationPath ../mingw810_64"
|
||||
|
||||
- name: Add Qt Static to PATH
|
||||
run: echo "$env:GITHUB_WORKSPACE/../Qt/6.0.1/bin" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8
|
||||
|
||||
- name: Add static config to .pro file
|
||||
run: echo "CONFIG += qt static" >> porymap.pro
|
||||
|
||||
- name: Add static qmake flags to .pro file
|
||||
run: echo "QMAKE_LFLAGS += -static-libgcc -static-libstdc++ -static -lwinpthread" >> porymap.pro
|
||||
|
||||
- name: Run Qmake
|
||||
env:
|
||||
QTDIR: ../Qt/6.0.1
|
||||
run: qmake.exe -o Makefile porymap.pro -spec win32-g++ "CONFIG+=qtquickcompiler"
|
||||
|
||||
- name: Add mingw to PATH
|
||||
run: echo "$env:GITHUB_WORKSPACE/../mingw810_64/bin" | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8
|
||||
|
||||
- name: Compile
|
||||
env:
|
||||
QTDIR: ../Qt/6.0.1
|
||||
run: mingw32-make.exe -j8
|
||||
|
||||
- name: Prep Release Directory
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: |
|
||||
mkdir porymap-windows-${{ github.ref_name }}
|
||||
cp release/porymap.exe porymap-windows-${{ github.ref_name }}/porymap.exe
|
||||
cp RELEASE-README.txt porymap-windows-${{ github.ref_name }}/README.txt
|
||||
|
||||
- name: Bundle Release Directory
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: powershell.exe -Command "Compress-Archive -Path porymap-windows-${{ github.ref_name }} -DestinationPath porymap-windows-${{ github.ref_name }}.zip"
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
files: porymap-windows-${{ github.ref_name }}.zip
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
92
CHANGELOG.md
|
@ -7,11 +7,97 @@ and this project somewhat adheres to [Semantic Versioning](https://semver.org/sp
|
|||
The **"Breaking Changes"** listed below are changes that have been made in the decompilation projects (e.g. pokeemerald), which porymap requires in order to work properly. It also includes changes to the scripting API that may change the behavior of existing porymap scripts. If porymap is used with a project or API script that is not up-to-date with the breaking changes, then porymap will likely break or behave improperly.
|
||||
|
||||
## [Unreleased]
|
||||
Nothing, yet.
|
||||
|
||||
## [5.4.1] - 2024-03-21
|
||||
### Fixed
|
||||
- Fix object event sprites not loading for some struct data formats.
|
||||
|
||||
## [5.4.0] - 2024-02-13
|
||||
### Added
|
||||
- Add a `Check for Updates` option to show new releases (Windows and macOS only).
|
||||
|
||||
### Changed
|
||||
- If Wild Encounters fail to load they are now only disabled for that session, and the settings remain unchanged.
|
||||
- Defaults are used if project constants are missing, rather than failing to open the project or changing settings.
|
||||
- Selector images now center on the selection when eyedropping or zooming.
|
||||
|
||||
### Fixed
|
||||
- Fix some minor visual issues with the various zoom sliders.
|
||||
- Smooth out scrolling when mouse is over tile/metatile images.
|
||||
- Fix the Tileset Editor selectors getting extra white space when changing tilesets.
|
||||
- Fix a crash when adding disabled events with the Pencil tool.
|
||||
- Fix error log about failing to find the scripts file when a new map is created.
|
||||
|
||||
## [5.3.0] - 2024-01-15
|
||||
### Added
|
||||
- Add zoom sliders to the Tileset Editor.
|
||||
- Add `getMetatileBehaviorName` and `setMetatileBehaviorName` to the API.
|
||||
- Add `metatile_behaviors`, `num_primary_palettes`, and `num_secondary_palettes` to `constants` in the API.
|
||||
|
||||
### Changed
|
||||
- Metatile ID strings are now padded to their current max, not the overall max.
|
||||
- Non-existent directories are now removed from the Open Recent Project menu.
|
||||
- Hovering on the layer view in the Tileset Editor now displays the tile ID.
|
||||
- Labels in the Script dropdown are now sorted alphabetically.
|
||||
- The name of the Heal Locations table is no longer enforced.
|
||||
- The API functions `addImage` and `createImage` now support project-relative paths.
|
||||
|
||||
### Fixed
|
||||
- Fix the metatile selector rectangle jumping when selecting up or left of the origin.
|
||||
- Fix the event group tabs sometimes showing an event from the wrong group.
|
||||
- Fix the clear buttons in the Shortcuts Editor not actually removing shortcuts.
|
||||
- Fix slow speed for the script label autcomplete.
|
||||
- Fix deleted script labels still appearing in the autocomplete after project reload.
|
||||
- Fix the map search bar stealing focus on startup.
|
||||
- Fix border metatiles view not resizing properly.
|
||||
- Fix Open Recent Project not clearing the API overlay
|
||||
- Fix API error reporting.
|
||||
|
||||
## [5.2.0] - 2024-01-02
|
||||
### Added
|
||||
- Add an editor window under `Options -> Project Settings...` to customize the project-specific settings in `porymap.project.cfg` and `porymap.user.cfg`.
|
||||
- Add an editor window under `Options -> Custom Scripts...` for Porymap's API scripts.
|
||||
- Add an `Open Recent Project` menu
|
||||
- Add a warning to warp events if they're on an incompatible metatile behavior.
|
||||
- Add settings for custom images, including the collision graphics, default event icons, and pokémon icons.
|
||||
- Add settings to override any symbol or macro names Porymap expects to find.
|
||||
- Add a zoom slider to the Collision tab.
|
||||
- Add toggleable grids to the Tileset Editor.
|
||||
- Support for custom metatile ID, collision, and elevation data sizes.
|
||||
- Support for 8bpp tileset tile images.
|
||||
|
||||
### Changed
|
||||
- `Script` dropdowns now include scripts from the current map's scripts file.
|
||||
- Encounter Rate now defaults to the most commonly used value, rather than 0.
|
||||
- The Collision tab now allows selection of any valid elevation/collision value.
|
||||
- The Palette Editor now remembers the Bit Depth setting.
|
||||
- The min/max levels on the Wild Pokémon tab will now adjust automatically if they invalidate each other.
|
||||
- If the recent project directory doesn't exist Porymap will open an empty project instead of failing with a misleading error message.
|
||||
- Settings under `Options` were relocated either to the `Preferences` window or `Options -> Project Settings`.
|
||||
- Secret Base and Weather Trigger events are automatically disabled if their respective constants files fail to parse, instead of not opening the project.
|
||||
- If a Pokémon icon fails to load Porymap will attempt to predict its filepath. If this also fails it will appear with a placeholder icon, and won't disappear when edited.
|
||||
- The bits in metatile attribute masks are now allowed to be non-contiguous.
|
||||
- Porymap will now attempt to read metatile attribute masks from the project.
|
||||
|
||||
### Fixed
|
||||
- Fix text boxes in the Palette Editor calculating color incorrectly.
|
||||
- Fix metatile labels being sorted incorrectly for tileset names with multiple underscores.
|
||||
- Fix default object sprites retaining dimensions and transparency of the previous sprite.
|
||||
- Fix connections not being deleted when the map name text box is cleared.
|
||||
- Fix the map border not updating when a tileset is changed.
|
||||
- Improve the poor speed of the API functions `setMetatileTile` and `setMetatileTiles`.
|
||||
- Stop the Tileset Editor from scrolling to the initially selected metatile when saving.
|
||||
- Fix `0x0`/`NULL` appearing more than once in the scripts dropdown.
|
||||
- Fix the selection outline sticking in single-tile mode on the Prefab tab.
|
||||
- Fix heal location data being cleared if certain spaces aren't used in the table.
|
||||
- Fix bad URL color contrast on dark themes.
|
||||
- Fix some issues when too few/many pokémon are specified for a wild encounter group.
|
||||
- Fix Porymap reporting errors for macros it doesn't use.
|
||||
- Fix painting on the Collision tab with the opacity slider at 0 painting metatiles.
|
||||
- Fix crashes when File->Reload Project fails.
|
||||
- Fix overworld sprite facing directions if spritesheet has vertical layout.
|
||||
- Stop reporting `Error: Interrupted` for custom scripts during project reopen
|
||||
|
||||
## [5.1.1] - 2023-02-20
|
||||
### Added
|
||||
|
@ -398,7 +484,11 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
|
|||
## [1.0.0] - 2018-10-26
|
||||
This was the initial release.
|
||||
|
||||
[Unreleased]: https://github.com/huderlem/porymap/compare/5.1.1...HEAD
|
||||
[Unreleased]: https://github.com/huderlem/porymap/compare/5.4.1...HEAD
|
||||
[5.4.1]: https://github.com/huderlem/porymap/compare/5.4.0...5.4.1
|
||||
[5.4.0]: https://github.com/huderlem/porymap/compare/5.3.0...5.4.0
|
||||
[5.3.0]: https://github.com/huderlem/porymap/compare/5.2.0...5.3.0
|
||||
[5.2.0]: https://github.com/huderlem/porymap/compare/5.1.1...5.2.0
|
||||
[5.1.1]: https://github.com/huderlem/porymap/compare/5.1.0...5.1.1
|
||||
[5.1.0]: https://github.com/huderlem/porymap/compare/5.0.0...5.1.0
|
||||
[5.0.0]: https://github.com/huderlem/porymap/compare/4.5.0...5.0.0
|
||||
|
|
|
@ -7,7 +7,7 @@ porymap requires Qt 5.14.2 & C++11.
|
|||
The easiest way to get Qt is through [homebrew](https://brew.sh/).
|
||||
Once homebrew is installed, run these commands in Terminal:
|
||||
|
||||
```
|
||||
```bash
|
||||
xcode-select --install
|
||||
|
||||
brew update
|
||||
|
@ -32,8 +32,9 @@ Install [Qt development tools](https://www.qt.io/download-qt-installer), and use
|
|||
You need to install Qt. The minimum supported version is currently Qt 5.14.2. You can check your Qt version
|
||||
with `qtdiag`.
|
||||
|
||||
```
|
||||
sudo apt-get install qt5-default qtdeclarative5-dev
|
||||
```bash
|
||||
sudo apt-get install qt6-declarative-dev
|
||||
# if your distro does not have qt6-declarative-dev, try sudo apt-get install qtdeclarative5-dev
|
||||
qmake
|
||||
make
|
||||
./porymap
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Version: 5.1.1
|
||||
Date: February 20th, 2023
|
||||
Version: 5.4.1
|
||||
Date: March 21st, 2024
|
||||
|
||||
This version of porymap works with pokeruby and pokeemerald as of the following commit hashes:
|
||||
* pokeemerald: c76beed98990a57c84d3930190fd194abfedf7e8
|
||||
|
@ -12,6 +12,96 @@ Please report any issues on GitHub: [https://github.com/huderlem/porymap/issues]
|
|||
|
||||
-------------------------
|
||||
|
||||
## [5.4.1] - 2024-03-21
|
||||
### Fixed
|
||||
- Fix object event sprites not loading for some struct data formats.
|
||||
|
||||
## [5.4.0] - 2024-02-13
|
||||
### Added
|
||||
- Add a `Check for Updates` option to show new releases (Windows and macOS only).
|
||||
|
||||
### Changed
|
||||
- If Wild Encounters fail to load they are now only disabled for that session, and the settings remain unchanged.
|
||||
- Defaults are used if project constants are missing, rather than failing to open the project or changing settings.
|
||||
- Selector images now center on the selection when eyedropping or zooming.
|
||||
|
||||
### Fixed
|
||||
- Fix some minor visual issues with the various zoom sliders.
|
||||
- Smooth out scrolling when mouse is over tile/metatile images.
|
||||
- Fix the Tileset Editor selectors getting extra white space when changing tilesets.
|
||||
- Fix a crash when adding disabled events with the Pencil tool.
|
||||
- Fix error log about failing to find the scripts file when a new map is created.
|
||||
|
||||
## [5.3.0] - 2024-01-15
|
||||
### Added
|
||||
- Add zoom sliders to the Tileset Editor.
|
||||
- Add `getMetatileBehaviorName` and `setMetatileBehaviorName` to the API.
|
||||
- Add `metatile_behaviors`, `num_primary_palettes`, and `num_secondary_palettes` to `constants` in the API.
|
||||
|
||||
### Changed
|
||||
- Metatile ID strings are now padded to their current max, not the overall max.
|
||||
- Non-existent directories are now removed from the Open Recent Project menu.
|
||||
- Hovering on the layer view in the Tileset Editor now displays the tile ID.
|
||||
- Labels in the Script dropdown are now sorted alphabetically.
|
||||
- The name of the Heal Locations table is no longer enforced.
|
||||
- The API functions `addImage` and `createImage` now support project-relative paths.
|
||||
|
||||
### Fixed
|
||||
- Fix the metatile selector rectangle jumping when selecting up or left of the origin.
|
||||
- Fix the event group tabs sometimes showing an event from the wrong group.
|
||||
- Fix the clear buttons in the Shortcuts Editor not actually removing shortcuts.
|
||||
- Fix slow speed for the script label autcomplete.
|
||||
- Fix deleted script labels still appearing in the autocomplete after project reload.
|
||||
- Fix the map search bar stealing focus on startup.
|
||||
- Fix border metatiles view not resizing properly.
|
||||
- Fix Open Recent Project not clearing the API overlay
|
||||
- Fix API error reporting.
|
||||
|
||||
## [5.2.0] - 2024-01-02
|
||||
### Added
|
||||
- Add an editor window under `Options -> Project Settings...` to customize the project-specific settings in `porymap.project.cfg` and `porymap.user.cfg`.
|
||||
- Add an editor window under `Options -> Custom Scripts...` for Porymap's API scripts.
|
||||
- Add an `Open Recent Project` menu
|
||||
- Add a warning to warp events if they're on an incompatible metatile behavior.
|
||||
- Add settings for custom images, including the collision graphics, default event icons, and pokémon icons.
|
||||
- Add settings to override any symbol or macro names Porymap expects to find.
|
||||
- Add a zoom slider to the Collision tab.
|
||||
- Add toggleable grids to the Tileset Editor.
|
||||
- Support for custom metatile ID, collision, and elevation data sizes.
|
||||
- Support for 8bpp tileset tile images.
|
||||
|
||||
### Changed
|
||||
- `Script` dropdowns now include scripts from the current map's scripts file.
|
||||
- Encounter Rate now defaults to the most commonly used value, rather than 0.
|
||||
- The Collision tab now allows selection of any valid elevation/collision value.
|
||||
- The Palette Editor now remembers the Bit Depth setting.
|
||||
- The min/max levels on the Wild Pokémon tab will now adjust automatically if they invalidate each other.
|
||||
- If the recent project directory doesn't exist Porymap will open an empty project instead of failing with a misleading error message.
|
||||
- Settings under `Options` were relocated either to the `Preferences` window or `Options -> Project Settings`.
|
||||
- Secret Base and Weather Trigger events are automatically disabled if their respective constants files fail to parse, instead of not opening the project.
|
||||
- If a Pokémon icon fails to load Porymap will attempt to predict its filepath. If this also fails it will appear with a placeholder icon, and won't disappear when edited.
|
||||
- The bits in metatile attribute masks are now allowed to be non-contiguous.
|
||||
- Porymap will now attempt to read metatile attribute masks from the project.
|
||||
|
||||
### Fixed
|
||||
- Fix text boxes in the Palette Editor calculating color incorrectly.
|
||||
- Fix metatile labels being sorted incorrectly for tileset names with multiple underscores.
|
||||
- Fix default object sprites retaining dimensions and transparency of the previous sprite.
|
||||
- Fix connections not being deleted when the map name text box is cleared.
|
||||
- Fix the map border not updating when a tileset is changed.
|
||||
- Improve the poor speed of the API functions `setMetatileTile` and `setMetatileTiles`.
|
||||
- Stop the Tileset Editor from scrolling to the initially selected metatile when saving.
|
||||
- Fix `0x0`/`NULL` appearing more than once in the scripts dropdown.
|
||||
- Fix the selection outline sticking in single-tile mode on the Prefab tab.
|
||||
- Fix heal location data being cleared if certain spaces aren't used in the table.
|
||||
- Fix bad URL color contrast on dark themes.
|
||||
- Fix some issues when too few/many pokémon are specified for a wild encounter group.
|
||||
- Fix Porymap reporting errors for macros it doesn't use.
|
||||
- Fix painting on the Collision tab with the opacity slider at 0 painting metatiles.
|
||||
- Fix crashes when File->Reload Project fails.
|
||||
- Fix overworld sprite facing directions if spritesheet has vertical layout.
|
||||
- Stop reporting `Error: Interrupted` for custom scripts during project reopen
|
||||
|
||||
## [5.1.1] - 2023-02-20
|
||||
### Added
|
||||
- Add `registerToggleAction` to the scripting API
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Sphinx build info version 1
|
||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||
config: 84555ec9fefb928fe9970dd525a17df6
|
||||
config: 23fd5c9a8562e86bc017afd5666bb426
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||
|
|
BIN
docs/_images/base-game-version.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
docs/_images/button-create.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
docs/_images/button-load.png
Normal file
After Width: | Height: | Size: 9.3 KiB |
BIN
docs/_images/button-refresh.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
docs/_images/custom-scripts-editor.png
Normal file
After Width: | Height: | Size: 81 KiB |
BIN
docs/_images/default-tilesets.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
docs/_images/delete.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
docs/_images/events.png
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
docs/_images/file_edit.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
docs/_images/folder.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
docs/_images/import-defaults.png
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
docs/_images/import_defaults.png
Normal file
After Width: | Height: | Size: 8.3 KiB |
Before Width: | Height: | Size: 147 KiB After Width: | Height: | Size: 403 KiB |
BIN
docs/_images/maps.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
docs/_images/new-map-defaults.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
docs/_images/new-script.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
docs/_images/pokemon-icon-placeholder.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
docs/_images/pokemon_icon_placeholder.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
docs/_images/prefabs.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
docs/_images/preferences.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
docs/_images/refresh-prompt.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
docs/_images/restore-defaults.png
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
docs/_images/settings.png
Normal file
After Width: | Height: | Size: 115 KiB |
BIN
docs/_images/tab-events.png
Normal file
After Width: | Height: | Size: 308 KiB |
BIN
docs/_images/tab-files.png
Normal file
After Width: | Height: | Size: 193 KiB |
BIN
docs/_images/tab-general.png
Normal file
After Width: | Height: | Size: 185 KiB |
BIN
docs/_images/tab-identifiers.png
Normal file
After Width: | Height: | Size: 191 KiB |
BIN
docs/_images/tab-maps.png
Normal file
After Width: | Height: | Size: 173 KiB |
BIN
docs/_images/tab-project-files.png
Normal file
After Width: | Height: | Size: 201 KiB |
BIN
docs/_images/tab-tilesets.png
Normal file
After Width: | Height: | Size: 186 KiB |
BIN
docs/_images/tilesets-metatiles.png
Normal file
After Width: | Height: | Size: 80 KiB |
|
@ -9,7 +9,7 @@ Selecting Collision Types
|
|||
|
||||
The Collision Type Selector is a tab next to the Metatile Selector. It features 32 total different collision types. The left column is for collision types that allow the player to walk through the tiles. These are denoted by white text. The right column is for collision types that are impassable by the player. These are denoted by red text.
|
||||
|
||||
The transparency slider above the collision types controls the transparency of the collision properties on the map view.
|
||||
The transparency slider above the collision types controls the transparency of the collision properties on the map view. The slider at the bottom of the panel zooms the selector image in and out.
|
||||
|
||||
.. figure:: images/editing-map-collisions/map-collisions.png
|
||||
:alt: Map Collisions View
|
||||
|
@ -73,3 +73,6 @@ Multi-Level Collision Type |multi-level-collision-type-1| |multi-level-collision
|
|||
|
||||
.. |multi-level-collision-type-2|
|
||||
image:: images/editing-map-collisions/multi-level-collision-type-2.png
|
||||
|
||||
.. note::
|
||||
For advanced usage: Any valid elevation/collision value combination can be selected using the ``Elevation`` and ``Collision`` value spinners, even if it's not represented graphically on the selector image. You may also resize/replace this selector image under ``Options -> Project Settings``.
|
||||
|
|
|
@ -110,7 +110,7 @@ Target Map
|
|||
Warp Events
|
||||
-----------
|
||||
|
||||
Warp events are how the player is able to warp to other maps, such as entering a building. Double-clicking on a warp will automatically open the destination map and select the destination warp. This makes it very easy to navigate around in Porymap.
|
||||
Warp events are how the player is able to warp to other maps, such as entering a building. Double-clicking on a warp will automatically open the destination map and select the destination warp. This makes it very easy to navigate around in Porymap. Warps need to be on specific metatiles to function as an exit; a warning will appear if the warp event is not on one of these metatiles.
|
||||
|
||||
.. figure:: images/editing-map-events/event-warp.png
|
||||
:alt: Warp Event Properties
|
||||
|
|
|
@ -6,9 +6,16 @@ Porymap relies on the user maintaining a certain level of integrity with their p
|
|||
This is a list of files that porymap reads from and writes to. Generally, if porymap writes
|
||||
to a file, it probably is not a good idea to edit yourself unless otherwise noted.
|
||||
|
||||
The filepath that Porymap expects for each file can be overridden with config options. The name of each config override is listed in the table, and should begin with ``path/``.
|
||||
For example if you wanted to rename ``include/constants/items.h`` to ``headers/defines/stuff.h``, you would add ``path/constants_items=headers/defines/stuff.h`` to your project's ``porymap.project.cfg`` file.
|
||||
The filepath that Porymap expects for each file can be overridden on the ``Files`` tab of ``Options -> Project Settings``. A new path can be specified by entering it in the text box or choosing it with the |button-folder| button. Paths are expected to be relative to the root project folder. If no path is specified, or if the file/folder specified does not exist, then the default path will be used instead. The name of each setting in this section is listed in the table below under ``Override``.
|
||||
|
||||
.. |button-folder| image:: images/scripting-capabilities/folder.png
|
||||
:width: 24
|
||||
:height: 24
|
||||
|
||||
.. figure:: images/settings-and-options/tab-files.png
|
||||
:alt: Files tab
|
||||
|
||||
.. _files:
|
||||
|
||||
.. csv-table::
|
||||
:header: File Name,Read,Write,Override,Notes
|
||||
|
@ -28,7 +35,7 @@ For example if you wanted to rename ``include/constants/items.h`` to ``headers/d
|
|||
data/tilesets/graphics.inc, yes, yes, ``tilesets_graphics_asm``, only if ``tilesets_headers`` can't be found
|
||||
data/tilesets/metatiles.inc, yes, yes, ``tilesets_metatiles_asm``, only if ``tilesets_headers`` can't be found
|
||||
data/tilesets/[primary|secondary]/\*, yes, yes, ``data_tilesets_folders``, default tileset data location
|
||||
src/data/wild_encounters.json, yes, yes, ``json_wild_encounters``,
|
||||
src/data/wild_encounters.json, yes, yes, ``json_wild_encounters``, optional (only required to use Wild Pokémon tab)
|
||||
src/data/object_events/object_event_graphics_info_pointers.h, yes, no, ``data_obj_event_gfx_pointers``,
|
||||
src/data/object_events/object_event_graphics_info.h, yes, no, ``data_obj_event_gfx_info``,
|
||||
src/data/object_events/object_event_pic_tables.h, yes, no, ``data_obj_event_pic_tables``,
|
||||
|
@ -37,18 +44,17 @@ For example if you wanted to rename ``include/constants/items.h`` to ``headers/d
|
|||
src/data/heal_locations.h, yes, yes, ``data_heal_locations``,
|
||||
src/data/region_map/region_map_sections.json, yes, yes, ``json_region_map_entries``,
|
||||
src/data/region_map/porymap_config.json, yes, yes, ``json_region_porymap_cfg``,
|
||||
include/constants/global.h, yes, no, ``constants_global``, reads ``OBJECT_EVENT_TEMPLATES_COUNT``
|
||||
include/constants/global.h, yes, no, ``constants_global``, reads ``define_obj_event_count``
|
||||
include/constants/map_groups.h, no, yes, ``constants_map_groups``,
|
||||
include/constants/items.h, yes, no, ``constants_items``,
|
||||
include/constants/opponents.h, yes, no, ``constants_opponents``, reads max trainers constant
|
||||
include/constants/flags.h, yes, no, ``constants_flags``,
|
||||
include/constants/vars.h, yes, no, ``constants_vars``,
|
||||
include/constants/weather.h, yes, no, ``constants_weather``,
|
||||
include/constants/songs.h, yes, no, ``constants_songs``,
|
||||
include/constants/items.h, yes, no, ``constants_items``, for Hidden Item events
|
||||
include/constants/flags.h, yes, no, ``constants_flags``, for Object and Hidden Item events
|
||||
include/constants/vars.h, yes, no, ``constants_vars``, for Trigger events
|
||||
include/constants/weather.h, yes, no, ``constants_weather``, for map weather and Weather Triggers
|
||||
include/constants/songs.h, yes, no, ``constants_songs``, for map music
|
||||
include/constants/heal_locations.h, yes, yes, ``constants_heal_locations``,
|
||||
include/constants/pokemon.h, yes, no, ``constants_pokemon``, reads min and max level constants
|
||||
include/constants/pokemon.h, yes, no, ``constants_pokemon``, reads ``define_min_level`` and ``define_max_level``
|
||||
include/constants/map_types.h, yes, no, ``constants_map_types``,
|
||||
include/constants/trainer_types.h, yes, no, ``constants_trainer_types``,
|
||||
include/constants/trainer_types.h, yes, no, ``constants_trainer_types``, for Object events
|
||||
include/constants/secret_bases.h, yes, no, ``constants_secret_bases``, pokeemerald and pokeruby only
|
||||
include/constants/event_object_movement.h, yes, no, ``constants_obj_event_movement``,
|
||||
include/constants/event_objects.h, yes, no, ``constants_obj_events``,
|
||||
|
@ -56,8 +62,76 @@ For example if you wanted to rename ``include/constants/items.h`` to ``headers/d
|
|||
include/constants/region_map_sections.h, yes, no, ``constants_region_map_sections``,
|
||||
include/constants/metatile_labels.h, yes, yes, ``constants_metatile_labels``,
|
||||
include/constants/metatile_behaviors.h, yes, no, ``constants_metatile_behaviors``,
|
||||
include/constants/species.h, yes, no, ``constants_metatile_behaviors``, for the Wild Pokémon tab
|
||||
include/global.fieldmap.h, yes, no, ``global_fieldmap``, reads map and tileset data masks
|
||||
include/fieldmap.h, yes, no, ``constants_fieldmap``, reads tileset related constants
|
||||
src/event_object_movement.c, yes, no, ``initial_facing_table``, reads ``gInitialMovementTypeFacingDirections``
|
||||
src/pokemon_icon.c, yes, no, ``pokemon_icon_table``, reads files in ``gMonIconTable``
|
||||
src/fieldmap.c, yes, no, ``fieldmap``, reads ``symbol_attribute_table``
|
||||
src/event_object_movement.c, yes, no, ``initial_facing_table``, reads ``symbol_facing_directions``
|
||||
src/pokemon_icon.c, yes, no, ``pokemon_icon_table``, reads files in ``symbol_pokemon_icon_table``
|
||||
graphics/pokemon/\*/icon.png, yes, no, ``pokemon_gfx``, to search for Pokémon icons if they aren't found in ``symbol_pokemon_icon_table``
|
||||
|
||||
|
||||
In addition to these files, there are some specific symbol and macro names that Porymap expects to find in your project. These can be overridden on the ``Identifiers`` tab of ``Options -> Project Settings``. The name of each setting in this section is listed in the table below under ``Override``. Overrides with ``regex`` in the name support the `regular expression syntax <https://perldoc.perl.org/perlre>`_ used by Qt.
|
||||
|
||||
.. figure:: images/settings-and-options/tab-identifiers.png
|
||||
:alt: Files tab
|
||||
|
||||
.. _identifiers:
|
||||
|
||||
.. csv-table::
|
||||
:header: Override,Default,Notes
|
||||
:widths: 20, 20, 30
|
||||
|
||||
``symbol_facing_directions``, ``gInitialMovementTypeFacingDirections``, to set sprite frame for Object Events based on movement type
|
||||
``symbol_obj_event_gfx_pointers``, ``gObjectEventGraphicsInfoPointers``, to map Object Event graphics IDs to graphics data
|
||||
``symbol_pokemon_icon_table``, ``gMonIconTable``, to map species constants to icon images
|
||||
``symbol_wild_encounters``, ``gWildMonHeaders``, output as the ``label`` property for the top-level wild ecounters JSON object
|
||||
``symbol_heal_locations_type``, ``struct HealLocation``, the type for the Heal Locations table
|
||||
``symbol_heal_locations``, ``sHealLocations``, the default Heal Locations table name when ``Respawn Map/NPC`` is disabled
|
||||
``symbol_spawn_points``, ``sSpawnPoints``, the default Heal Locations table name when ``Respawn Map/NPC`` is enabled
|
||||
``symbol_spawn_maps``, ``u16 sWhiteoutRespawnHealCenterMapIdxs``, the type and table name for Heal Location ``Respawn Map`` values
|
||||
``symbol_spawn_npcs``, ``u8 sWhiteoutRespawnHealerNpcIds``, the type and table name for Heal Location ``Respawn NPC`` values
|
||||
``symbol_attribute_table``, ``sMetatileAttrMasks``, optionally read to get settings on ``Tilesets`` tab
|
||||
``symbol_tilesets_prefix``, ``gTileset_``, for new tileset names and to extract base tileset names
|
||||
``define_obj_event_count``, ``OBJECT_EVENT_TEMPLATES_COUNT``, to limit total Object Events
|
||||
``define_min_level``, ``MIN_LEVEL``, minimum wild encounters level
|
||||
``define_max_level``, ``MAX_LEVEL``, maximum wild encounters level
|
||||
``define_tiles_primary``, ``NUM_TILES_IN_PRIMARY``,
|
||||
``define_tiles_total``, ``NUM_TILES_TOTAL``,
|
||||
``define_metatiles_primary``, ``NUM_METATILES_IN_PRIMARY``, total metatiles are calculated using metatile ID mask
|
||||
``define_pals_primary``, ``NUM_PALS_IN_PRIMARY``,
|
||||
``define_pals_total``, ``NUM_PALS_TOTAL``,
|
||||
``define_map_size``, ``MAX_MAP_DATA_SIZE``, to limit map dimensions
|
||||
``define_mask_metatile``, ``MAPGRID_METATILE_ID_MASK``, optionally read to get settings on ``Maps`` tab
|
||||
``define_mask_collision``, ``MAPGRID_COLLISION_MASK``, optionally read to get settings on ``Maps`` tab
|
||||
``define_mask_elevation``, ``MAPGRID_ELEVATION_MASK``, optionally read to get settings on ``Maps`` tab
|
||||
``define_mask_behavior``, ``METATILE_ATTR_BEHAVIOR_MASK``, optionally read to get settings on ``Tilesets`` tab
|
||||
``define_mask_layer``, ``METATILE_ATTR_LAYER_MASK``, optionally read to get settings on ``Tilesets`` tab
|
||||
``define_attribute_behavior``, ``METATILE_ATTRIBUTE_BEHAVIOR``, name used to extract setting from ``symbol_attribute_table``
|
||||
``define_attribute_layer``, ``METATILE_ATTRIBUTE_LAYER_TYPE``, name used to extract setting from ``symbol_attribute_table``
|
||||
``define_attribute_terrain``, ``METATILE_ATTRIBUTE_TERRAIN``, name used to extract setting from ``symbol_attribute_table``
|
||||
``define_attribute_encounter``, ``METATILE_ATTRIBUTE_ENCOUNTER_TYPE``, name used to extract setting from ``symbol_attribute_table``
|
||||
``define_metatile_label_prefix``, ``METATILE_``, expected prefix for metatile label macro names
|
||||
``define_heal_locations_prefix``, ``HEAL_LOCATION_``, output as prefix for Heal Location IDs if ``Respawn Map/NPC`` is disabled
|
||||
``define_spawn_prefix``, ``SPAWN_``, output as prefix for Heal Location IDs if ``Respawn Map/NPC`` is enabled
|
||||
``define_map_prefix``, ``MAP_``, expected prefix for map macro names
|
||||
``define_map_dynamic``, ``DYNAMIC``, macro name after prefix for Dynamic maps
|
||||
``define_map_empty``, ``UNDEFINED``, macro name after prefix for empty maps
|
||||
``define_map_section_prefix``, ``MAPSEC_``, expected prefix for location macro names
|
||||
``define_map_section_empty``, ``NONE``, macro name after prefix for empty region map sections
|
||||
``define_map_section_count``, ``COUNT``, macro name after prefix for total number of region map sections
|
||||
``regex_behaviors``, ``\bMB_``, regex to find metatile behavior macro names
|
||||
``regex_obj_event_gfx``, ``\bOBJ_EVENT_GFX_``, regex to find Object Event graphics ID macro names
|
||||
``regex_items``, ``\bITEM_(?!(B_)?USE_)``, regex to find item macro names
|
||||
``regex_flags``, ``\bFLAG_``, regex to find flag macro names
|
||||
``regex_vars``, ``\bVAR_``, regex to find var macro names
|
||||
``regex_movement_types``, ``\bMOVEMENT_TYPE_``, regex to find movement type macro names
|
||||
``regex_map_types``, ``\bMAP_TYPE_``, regex to find map type macro names
|
||||
``regex_battle_scenes``, ``\bMAP_BATTLE_SCENE_``, regex to find battle scene macro names
|
||||
``regex_weather``, ``\bWEATHER_``, regex to find map weather macro names
|
||||
``regex_coord_event_weather``, ``\bCOORD_EVENT_WEATHER_``, regex to find weather trigger macro names
|
||||
``regex_secret_bases``, ``\bSECRET_BASE_[A-Za-z0-9_]*_[0-9]+``, regex to find secret base ID macro names
|
||||
``regex_sign_facing_directions``, ``\bBG_EVENT_PLAYER_FACING_``, regex to find sign facing direction macro names
|
||||
``regex_trainer_types``, ``\bTRAINER_TYPE_``, regex to find trainer type macro names
|
||||
``regex_music``, ``\b(SE|MUS)_``, regex to find music macro names
|
||||
``regex_species``, ``\bSPECIES_``, regex to find species macro names
|
||||
|
|
|
@ -5,66 +5,273 @@ Porymap Settings
|
|||
****************
|
||||
|
||||
Porymap uses config files to read and store user and project settings.
|
||||
|
||||
===============
|
||||
Global settings
|
||||
===============
|
||||
|
||||
A global settings file is stored in a platform-dependent location for app configuration files
|
||||
(``%Appdata%\pret\porymap\porymap.cfg`` on Windows, ``~/Library/Application\ Support/pret/porymap/porymap.cfg`` on macOS).
|
||||
|
||||
A config file is also created when opening a project in porymap for the first time. It is stored in
|
||||
your project root as ``porymap.project.cfg``. There are several project-specific settings that are
|
||||
determined by this file. You may want to force commit this file so that other users will automatically have access to your project settings.
|
||||
A selection of the settings in this file can be edited under ``Preferences...``, and the rest are updated automatically while using Porymap.
|
||||
|
||||
A second config file is created for user-specific settings. It is stored in
|
||||
your project root as ``porymap.user.cfg``. You should add this file to your gitignore.
|
||||
================
|
||||
Project settings
|
||||
================
|
||||
|
||||
.. csv-table::
|
||||
:header: Setting,Default,Location,Can Edit?,Description
|
||||
:widths: 10, 3, 5, 5, 20
|
||||
* :ref:`General <general>`
|
||||
* :ref:`Maps <maps>`
|
||||
* :ref:`Tilesets <tilesets>`
|
||||
* :ref:`Events <events>`
|
||||
* :ref:`Files & Identifiers <files-identifiers>`
|
||||
|
||||
``recent_project``, , global, yes, The project that will be opened on launch
|
||||
``reopen_on_launch``, 1, global, yes, Whether the most recent project should be opened on launch
|
||||
``recent_map``, , user, yes, The map that will be opened on launch
|
||||
``pretty_cursors``, 1, global, yes, Whether to use custom crosshair cursors
|
||||
``map_sort_order``, group, global, yes, The order map list is sorted in
|
||||
``window_geometry``, , global, no, For restoring window sizes
|
||||
``window_state``, , global, no, For restoring window sizes
|
||||
``map_splitter_state``, , global, no, For restoring window sizes
|
||||
``main_splitter_state``, , global, no, For restoring window sizes
|
||||
``collision_opacity``, 50, global, yes, Opacity of collision overlay
|
||||
``metatiles_zoom``, 30, global, yes, Scale of map metatiles
|
||||
``show_player_view``, 0, global, yes, Display a rectangle for the GBA screen radius
|
||||
``show_cursor_tile``, 0, global, yes, Display a rectangle around the hovered metatile(s)
|
||||
``monitor_files``, 1, global, yes, Whether porymap will monitor changes to project files
|
||||
``tileset_checkerboard_fill``, 1, global, yes, Whether new tilesets will be filled with a checkerboard pattern of metatiles.
|
||||
``theme``, default, global, yes, The color theme for porymap windows and widgets
|
||||
``text_editor_goto_line``, , global, yes, The command that will be executed when clicking the button next the ``Script`` combo-box.
|
||||
``text_editor_open_directory``, , global, yes, The command that will be executed when clicking ``Open Project in Text Editor``.
|
||||
``base_game_version``, , project, no, The base pret repo for this project
|
||||
``use_encounter_json``, 1, user, yes, Enables wild encounter table editing
|
||||
``use_poryscript``, 0, project, yes, Whether to open .pory files for scripts
|
||||
``use_custom_border_size``, 0, project, yes, Whether to allow variable border sizes
|
||||
``enable_event_weather_trigger``, 1 if not ``pokefirered``, project, yes, Allows adding Weather Trigger events
|
||||
``enable_event_secret_base``, 1 if not ``pokefirered``, project, yes, Allows adding Secret Base events
|
||||
``enable_event_clone_object``, 1 if ``pokefirered``, project, yes, Allows adding Clone Object events
|
||||
``enable_hidden_item_quantity``, 1 if ``pokefirered``, project, yes, Adds ``Quantity`` to Hidden Item events
|
||||
``enable_hidden_item_requires_itemfinder``, 1 if ``pokefirered``, project, yes, Adds ``Requires Itemfinder`` to Hidden Item events
|
||||
``enable_heal_location_respawn_data``, 1 if ``pokefirered``, project, yes, Adds ``Respawn Map`` and ``Respawn NPC`` to Heal Location events
|
||||
``enable_floor_number``, 1 if ``pokefirered``, project, yes, Adds ``Floor Number`` to map headers
|
||||
``enable_map_allow_flags``, 1 if not ``pokeruby``, project, yes, "Adds ``Allow Running``, ``Allow Biking``, and ``Allow Dig & Escape Rope`` to map headers"
|
||||
``create_map_text_file``, 1 if not ``pokeemerald``, project, yes, A ``text.inc`` or ``text.pory`` file will be created for any new map
|
||||
``enable_triple_layer_metatiles``, 0, project, yes, Enables triple-layer metatiles (See https://github.com/pret/pokeemerald/wiki/Triple-layer-metatiles)
|
||||
``new_map_metatile``, 1, project, yes, The metatile id that will be used to fill new maps
|
||||
``new_map_elevation``, 3, project, yes, The elevation that will be used to fill new maps
|
||||
``new_map_border_metatiles``, "``468,469,476,477`` or ``20,21,28,29``", project, yes, The list of metatile ids that will be used to fill the 2x2 border of new maps
|
||||
``default_primary_tileset``, ``gTileset_General``, project, yes, The label of the default primary tileset
|
||||
``default_secondary_tileset``, ``gTileset_Petalburg`` or ``gTileset_PalletTown``, project, yes, The label of the default secondary tileset
|
||||
``custom_scripts``, , user, yes, A list of script files to load into the scripting engine
|
||||
``prefabs_filepath``, ``<project_root>/prefabs.json``, project, yes, The filepath containing prefab JSON data
|
||||
``prefabs_import_prompted``, 0, project, no, Keeps track of whether or not the project was prompted for importing default prefabs
|
||||
``tilesets_have_callback``, 1, project, yes, Whether new tileset headers should have the ``callback`` field
|
||||
``tilesets_have_is_compressed``, 1, project, yes, Whether new tileset headers should have the ``isCompressed`` field
|
||||
``metatile_attributes_size``, 2 or 4, project, yes, The number of attribute bytes each metatile has
|
||||
``metatile_behavior_mask``, ``0xFF`` or ``0x1FF``, project, yes, The mask for the metatile Behavior attribute
|
||||
``metatile_encounter_type_mask``, ``0x0`` or ``0x7000000``, project, yes, The mask for the metatile Encounter Type attribute
|
||||
``metatile_layer_type_mask``, ``0xF000`` or ``0x60000000``, project, yes, The mask for the metatile Layer Type attribute
|
||||
``metatile_terrain_type_mask``, ``0x0`` or ``0x3E00``, project, yes, The mask for the metatile Terrain Type attribute
|
||||
A config file for project-specific settings is also created when opening a project in porymap for the first time. It is stored in your project root as ``porymap.project.cfg``. You may want to force commit this file so that other users will automatically have access to your project settings.
|
||||
|
||||
A second config file is created for user-specific settings. It is stored in your project root as ``porymap.user.cfg``. You should add this file to your gitignore.
|
||||
|
||||
The settings in ``porymap.project.cfg`` and ``porymap.user.cfg`` can be edited under ``Options -> Project Settings...``. Any changes made in this window will not take effect unless confirmed by selecting ``OK`` and then reloading the project.
|
||||
|
||||
.. |button-folder| image:: images/scripting-capabilities/folder.png
|
||||
:width: 24
|
||||
:height: 24
|
||||
|
||||
.. |button-import-defaults| image:: images/settings-and-options/import-defaults.png
|
||||
:height: 24
|
||||
|
||||
.. |button-restore-defaults| image:: images/settings-and-options/restore-defaults.png
|
||||
:height: 24
|
||||
|
||||
.. |pokemon-icon-placeholder| image:: images/settings-and-options/pokemon-icon-placeholder.png
|
||||
:width: 24
|
||||
:height: 24
|
||||
|
||||
|
||||
.. _general:
|
||||
|
||||
General
|
||||
-------
|
||||
|
||||
.. figure:: images/settings-and-options/tab-general.png
|
||||
:alt: General tab
|
||||
|
||||
Use Poryscript
|
||||
If this is checked, a ``scripts.pory`` (and ``text.pory``, if applicable) file will be created alongside new maps, instead of a ``scripts.inc`` file. Additionally, ``.pory`` files will be considered when searching for scripts labels and when opening scripts files (in addition to the regular ``.inc`` files).
|
||||
|
||||
Defaults to ``unchecked``.
|
||||
|
||||
Show Wild Encounter Tables
|
||||
If this is checked, the ``Wild Pokemon`` tab will be enabled and wild encounter data will be read from the project's encounters JSON file.
|
||||
|
||||
Defaults to ``checked``. If no encounters JSON file is found this will be automatically unchecked.
|
||||
|
||||
Prefabs
|
||||
``Prefabs Path`` is the file path to a ``.json`` file that contains definitions of prefabs. This will be used to populate the ``Prefabs`` panel on the ``Map`` tab. If no path is specified prefabs will be saved to a new ``prefabs.json`` file in the root project folder. A new file can be selected with the |button-folder| button or by editing the file path.
|
||||
|
||||
The |button-import-defaults| button will populate the specified file with version-specific prefabs constructed using the vanilla tilesets. This will overwrite any existing prefabs.
|
||||
|
||||
Collision Graphics
|
||||
``Image Path`` is a path to any image file you'd like to use to represent collision and elevation values on the ``Collision`` tab. A new file can be selected with the |button-folder| button or by editing the file path. The image will be evenly divided into segments, with each row representing an elevation value (starting with ``0`` at the top) and each column representing a collision value (starting with ``0`` on the left).
|
||||
|
||||
Your image does not need to have a row/column for every valid elevation/collision value (for instance, the default collision values range from ``0-3``, but because ``2-3`` are semantically the same as ``1`` they are not displayed). You can specify the highest elevation and collision value represented on your image with ``Max Elevation`` and ``Max Collision``.
|
||||
|
||||
Note: Images with transparency may not function correctly when displayed on the map.
|
||||
|
||||
The filepath defaults empty, which will use `Porymap's original image <https://github.com/huderlem/porymap/blob/master/resources/images/collisions.png>`_. ``Max Elevation`` and ``Max Collision`` default to ``15`` and ``1`` respectively.
|
||||
|
||||
Pokémon Icons
|
||||
Porymap can display Pokémon species icons that it reads from your project on the ``Wild Pokemon`` tab. If Porymap fails to load your icon image, or if you'd like to display your own icon in Porymap for any reason, you can select a new image with the |button-folder| button or by editing the file path. You can select a species with the dropdown to edit the path for a different icon.
|
||||
|
||||
If your custom icon or the default icon fails to load a |pokemon-icon-placeholder| icon will be displayed.
|
||||
|
||||
Defaults to empty (the path in your project where Porymap expects to find each icon).
|
||||
|
||||
Base Game Version
|
||||
This is the name of the base pret repository for this project. Changing this setting will prompt you to restore the default project settings for any of the three versions. You can also do this for the currently-selected base game version by selecting |button-restore-defaults| at the bottom of the window. Aside from determining the default settings in this window, the base game version also determines the default settings when initializing the region map and when importing default prefabs.
|
||||
|
||||
Defaults to ``pokeruby``, ``pokefirered``, or ``pokeemerald`` depending on the project folder name. If the folder name doesn't match you will be prompted to select a version on first launch.
|
||||
|
||||
.. _maps:
|
||||
|
||||
Maps
|
||||
----
|
||||
|
||||
.. figure:: images/settings-and-options/tab-maps.png
|
||||
:alt: Maps tab
|
||||
|
||||
Map Data Defaults
|
||||
Border Metatiles
|
||||
This is list of metatile ID values that will be used to fill the border on new maps. The spin boxes correspond to the top-left, top-right, bottom-left, and bottom-right border metatiles respectively.
|
||||
|
||||
If ``Enable Custom Border Size`` is checked, this will instead be a comma-separated list of metatile ID values that will be used to fill the border on new maps. Values in the list will be read sequentially to fill the new border left-to-right top-to-bottom. If the number of metatiles in the border for a new map is not the same as the number of values in the list then the border will be filled with metatile ID ``0x000`` instead.
|
||||
|
||||
Defaults to ``0x014``, ``0x015``, ``0x01C``, ``0x01D`` for ``pokefirered``, and ``0x1D4``, ``0x1D5``, ``0x1DC``, ``0x1DD`` for other versions.
|
||||
|
||||
Metatile ID
|
||||
This is the metatile ID value that will be used to fill new maps.
|
||||
|
||||
Defaults to ``0x1``.
|
||||
|
||||
Collision
|
||||
This is the collision value that will be used to fill new maps. It will also be used to set the default selection on the Collision tab when the project is first opened.
|
||||
|
||||
Defaults to ``0``.
|
||||
|
||||
Elevation
|
||||
This is the elevation value that will be used to fill new maps. It will also be used to set the default selection on the Collision tab when the project is first opened.
|
||||
|
||||
Defaults to ``3``.
|
||||
|
||||
Create separate text file
|
||||
If this is checked, a ``text.inc`` (or ``text.pory``) file will be created alongside new maps.
|
||||
|
||||
Defaults to ``unchecked`` for ``pokeemerald`` and ``checked`` for other versions.
|
||||
|
||||
Map Data Layout
|
||||
Each of these three settings are bit masks that will be used to read and write an attribute of the data that makes up each map space (metatile ID, collision, and elevation). A warning will be displayed if any of the masks overlap. Their values may be read from ``#define`` s in your project, in which case editing will be disabled and you can change their values by modifying them in your project.
|
||||
|
||||
Default to being read from ``MAPGRID_METATILE_ID_MASK``, ``MAPGRID_COLLISION_MASK``, and ``MAPGRID_ELEVATION_MASK``. If they can't be read, they default to ``0x3FF``, ``0xC00``, and ``0xF000`` respectively.
|
||||
|
||||
Enable 'Floor Number'
|
||||
If this is checked, a ``Floor Number`` option will become available on the ``Header`` tab and on the new map prompt. For more information see `Editing Map Headers <https://huderlem.github.io/porymap/manual/editing-map-header.html>`_.
|
||||
|
||||
Defaults to ``checked`` for ``pokefirered`` and ``unchecked`` for other versions.
|
||||
|
||||
Enable 'Allow Running/Biking/Escaping'
|
||||
If this is checked, ``Allow Running``, ``Allow Biking``, and ``Allow Dig & Escape Rope`` options will become available on the ``Header`` tab and on the new map prompt. For more information see `Editing Map Headers <https://huderlem.github.io/porymap/manual/editing-map-header.html>`_.
|
||||
|
||||
Defaults to ``unchecked`` for ``pokeruby`` and ``checked`` for other versions.
|
||||
|
||||
Enable Custom Border Size
|
||||
If this is checked, ``Border Width`` and ``Border Height`` options will become available under the ``Change Dimensions`` button and on the new map prompt. If it is unchecked all maps will use the default 2x2 dimensions.
|
||||
|
||||
Defaults to ``checked`` for ``pokefirered`` and ``unchecked`` for other versions.
|
||||
|
||||
.. _tilesets:
|
||||
|
||||
Tilesets
|
||||
--------
|
||||
|
||||
.. figure:: images/settings-and-options/tab-tilesets.png
|
||||
:alt: Tilesets tab
|
||||
|
||||
Default Primary/Secondary Tilesest
|
||||
These will be the initially-selected tilesets when creating a new map, and will be used if a layout's tileset fails to load. If a default tileset is not found then the first tileset in the respective list will be used instead.
|
||||
|
||||
The default primary tileset is ``gTileset_General``.
|
||||
|
||||
The default secondary tileset is ``gTileset_PalletTown`` for ``pokefirered``, and ``gTileset_Petalburg`` for other versions.
|
||||
|
||||
Enable Triple Layer Metatiles
|
||||
Metatile data normally consists of 2 layers with 4 tiles each. If this is checked, they should instead consist of 3 layers with 4 tiles each. Additionally, the ``Layer Type`` option in the ``Tileset Editor`` will be removed. Note that layer type data will still be read and written according to your ``Layer Type mask`` setting.
|
||||
|
||||
For details on supporting this setting in your project, see https://github.com/pret/pokeemerald/wiki/Triple-layer-metatiles.
|
||||
|
||||
Defaults to ``unchecked``
|
||||
|
||||
Attributes size
|
||||
The number of bytes used per metatile for metatile attributes. The data in each of your project's ``metatile_attributes.bin`` files will be expected to be ``s * n``, where ``s`` is this size and ``n`` is the number of metatiles in the tileset. Additionally, new ``metatile_attributes.bin`` will be included in the project with a corresponding ``INCBIN_U8``, ``INCBIN_U16``, or ``INCBIN_U32`` directive.
|
||||
|
||||
Changing this setting will automatically enforce the new limit on the metatile attribute mask settings.
|
||||
|
||||
Defaults to ``4`` for ``pokefirered`` and ``2`` for other versions.
|
||||
|
||||
Attribute masks
|
||||
Each of these four settings are bit masks that will be used to read and write a specific metatile attribute from the metatile attributes data. If you are instead importing metatile attribute data from AdvanceMap, a default mask value will be used to read the data, and the mask value specified here will be used to write the new file.
|
||||
|
||||
If any of the mask values are set to ``0x0``, the corresponding option in the Tileset Editor will be removed. The maximum for all the attribute masks is determined by the Attributes size setting. A warning will be displayed if any of the masks overlap.
|
||||
|
||||
- Metatile Behavior mask
|
||||
This is the mask value for the ``Metatile Behavior`` metatile attribute.
|
||||
|
||||
Defaults to being read from ``sMetatileAttrMasks`` or ``METATILE_ATTR_BEHAVIOR_MASK``. If these can't be read, defaults to ``0x1FF`` for ``pokefirered``, and ``0xFF`` for other versions.
|
||||
|
||||
- Layer Type mask
|
||||
This is the mask value for the ``Layer Type`` metatile attribute. If the value is set to ``0x0`` the ``Layer Type`` option will be disabled in the Tileset Editor, and all metatiles will be treated in the editor as if they had the ``Normal`` layer type.
|
||||
|
||||
Defaults to being read from ``sMetatileAttrMasks`` or ``METATILE_ATTR_LAYER_MASK``. If these can't be read, defaults to ``0x60000000`` for ``pokefirered``, and ``0xF000`` for other versions.
|
||||
|
||||
- Encounter Type mask
|
||||
This is the mask value for the ``Encounter Type`` metatile attribute.
|
||||
|
||||
Defaults to being read from ``sMetatileAttrMasks``. If this can't be read, defaults to ``0x7000000`` for ``pokefirered``, and ``0x0`` for other versions.
|
||||
|
||||
- Terrain Type mask
|
||||
This is the mask value for the ``Terrain Type`` metatile attribute.
|
||||
|
||||
Defaults to being read from ``sMetatileAttrMasks``. If this can't be read, defaults to ``0x3E00`` for ``pokefirered``, and ``0x0`` for other versions.
|
||||
|
||||
Output 'callback' and 'isCompressed' fields
|
||||
If these are checked, then ``callback`` and ``isCompressed`` fields will be output in the C data for new tilesets. Their default values will be ``NULL`` and ``TRUE``, respectively.
|
||||
|
||||
Defaults to ``checked`` for both.
|
||||
|
||||
.. _events:
|
||||
|
||||
Events
|
||||
------
|
||||
|
||||
.. figure:: images/settings-and-options/tab-events.png
|
||||
:alt: Events tab
|
||||
|
||||
Default Icons
|
||||
Each event group is represented by a unique icon on the ``Events`` tab of the main editor. Here you can provide filepaths to your own image files to replace these icons, either by selecting the |button-folder| button or by editing the file path directly.
|
||||
|
||||
Events in the ``Objects`` group will only use this icon if there are no graphics associated with their ``Sprite`` field.
|
||||
|
||||
The filepaths default to empty, which will use `Porymap's original icons <https://github.com/huderlem/porymap/blob/master/resources/images/Entities_16x16.png>`_.
|
||||
|
||||
Warp Behaviors
|
||||
By default, Warp Events only function as exits if they're positioned on a metatile whose Metatile Behavior is treated specially in your project's code. If any Warp Events are positioned on a metatile that doesn't have one of these behaviors they will display a warning. Here you can disable that warning, or edit the list of behavior names that will silence the warning.
|
||||
|
||||
Defaults to ``unchecked``, i.e. the warning is enabled. The list of behaviors is initially populated with all the vanilla warp behavior names across pokeemerald, pokefirered, and pokeruby.
|
||||
|
||||
Enable Clone Objects
|
||||
If this is checked Clone Object Events will be available on the ``Events`` tab. For more information see `Clone Object Events <https://huderlem.github.io/porymap/manual/editing-map-events.html#clone-object-events>`_.
|
||||
|
||||
Defaults to ``checked`` for ``pokefirered`` and ``unchecked`` for other versions.
|
||||
|
||||
Enable Secret Bases
|
||||
If this is checked Secret Base Events will be available on the ``Events`` tab. For more information see `Secret Base Events <https://huderlem.github.io/porymap/manual/editing-map-events.html#secret-base-event>`_.
|
||||
|
||||
Defaults to ``unchecked`` for ``pokefirered`` and ``checked`` for other versions.
|
||||
|
||||
Enable Weather Triggers
|
||||
If this is checked Weather Trigger Events will be available on the ``Events`` tab. For more information see `Weather Trigger Events <https://huderlem.github.io/porymap/manual/editing-map-events.html#weather-trigger-events>`_.
|
||||
|
||||
Defaults to ``unchecked`` for ``pokefirered`` and ``checked`` for other versions.
|
||||
|
||||
Enable 'Quantity' for Hidden Items
|
||||
If this is checked the ``Quantity`` property will be available for Hidden Item Events. For more information see `Hidden Item Events <https://huderlem.github.io/porymap/manual/editing-map-events.html#hidden-item-event>`_.
|
||||
|
||||
Defaults to ``checked`` for ``pokefirered`` and ``unchecked`` for other versions.
|
||||
|
||||
Enable 'Requires Itemfinder' for Hidden Items
|
||||
If this is checked the ``Requires Itemfinder`` property will be available for Hidden Item Events. For more information see `Hidden Item Events <https://huderlem.github.io/porymap/manual/editing-map-events.html#hidden-item-event>`_.
|
||||
|
||||
Defaults to ``checked`` for ``pokefirered`` and ``unchecked`` for other versions.
|
||||
|
||||
Enable 'Repsawn Map/NPC' for Heal Locations
|
||||
If this is checked the ``Respawn Map`` and ``Respawn NPC`` properties will be available for Heal Location events. For more information see `Heal Locations <https://huderlem.github.io/porymap/manual/editing-map-events.html#heal-location-healspots>`_.
|
||||
|
||||
Defaults to ``checked`` for ``pokefirered`` and ``unchecked`` for other versions.
|
||||
|
||||
|
||||
.. _files-identifiers:
|
||||
|
||||
Files & Identifiers
|
||||
-------------------
|
||||
|
||||
.. figure:: images/settings-and-options/tab-files.png
|
||||
:alt: Files tab
|
||||
|
||||
.. figure:: images/settings-and-options/tab-identifiers.png
|
||||
:alt: Identifiers tab
|
||||
|
||||
These two tabs provide a way to override the filepaths and symbol/macro names Porymap expects to find in your project.
|
||||
|
||||
For ``Files``, each can be overridden by typing a new path or selecting a file/folder with the |button-folder| button. Paths are expected to be relative to the root project folder. If no path is specified, or if the file/folder specified does not exist, then the default path will be used instead.
|
||||
|
||||
For ``Identifiers``, each can be overridden by typing a new name in the line edit. Overrides with ``regex`` in the name support the `regular expression syntax <https://perldoc.perl.org/perlre>`_ used by Qt.
|
||||
|
||||
For more information on what each of these overrides does, see `Project Files <https://huderlem.github.io/porymap/manual/project-files.html>`_.
|
||||
|
||||
Some of these settings can be toggled manually in porymap via the *Options* menu.
|
||||
|
|
|
@ -76,12 +76,19 @@ Metatile Label
|
|||
*optional*
|
||||
|
||||
A name can be given to metatiles so that they may be referenced in source code.
|
||||
These are defined in ``include/constants/metatile_labels.h`` and can be used in
|
||||
together with the ``METATILE_ID`` macro.
|
||||
These are defined in ``include/constants/metatile_labels.h``.
|
||||
|
||||
For example, the metatile pictured above can be accessed like
|
||||
``METATILE_ID(General, Plain_Grass)``.
|
||||
For example, the metatile pictured above can be referenced using the define
|
||||
``METATILE_General_Plain_Grass``.
|
||||
This define name can be copied using the Copy button next to the metatile label text box.
|
||||
|
||||
Sometimes it may be useful to have a ``METATILE`` define that applies to many tilesets.
|
||||
This can be done by manually creating a ``METATILE`` define with a value outside its tileset.
|
||||
For example, the primary tileset ``SecretBase`` is associated with many secondary tilesets,
|
||||
all of which use the same labels. ``#define METATILE_SecretBase_PC 0x220`` defines a label
|
||||
for the secondary metatile id ``0x220`` which will be used by any secondary tileset that's
|
||||
paired with ``SecretBase``. Labels like this will appear gray in the text box, and can't
|
||||
be edited from within Porymap; they must be edited manually in ``metatile_labels.h``.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -7,17 +7,118 @@ and this project somewhat adheres to [Semantic Versioning](https://semver.org/sp
|
|||
The **"Breaking Changes"** listed below are changes that have been made in the decompilation projects (e.g. pokeemerald), which porymap requires in order to work properly. It also includes changes to the scripting API that may change the behavior of existing porymap scripts. If porymap is used with a project or API script that is not up-to-date with the breaking changes, then porymap will likely break or behave improperly.
|
||||
|
||||
## [Unreleased]
|
||||
Nothing, yet.
|
||||
|
||||
## [5.4.1] - 2024-03-21
|
||||
### Fixed
|
||||
- Fix object event sprites not loading for some struct data formats.
|
||||
|
||||
## [5.4.0] - 2024-02-13
|
||||
### Added
|
||||
- Add a `Check for Updates` option to show new releases (Windows and macOS only).
|
||||
|
||||
### Changed
|
||||
- Change encounter tab copy and paste behavior.
|
||||
- If Wild Encounters fail to load they are now only disabled for that session, and the settings remain unchanged.
|
||||
- Defaults are used if project constants are missing, rather than failing to open the project or changing settings.
|
||||
- Selector images now center on the selection when eyedropping or zooming.
|
||||
|
||||
### Fixed
|
||||
- Fix some minor visual issues with the various zoom sliders.
|
||||
- Smooth out scrolling when mouse is over tile/metatile images.
|
||||
- Fix the Tileset Editor selectors getting extra white space when changing tilesets.
|
||||
- Fix a crash when adding disabled events with the Pencil tool.
|
||||
- Fix error log about failing to find the scripts file when a new map is created.
|
||||
|
||||
## [5.3.0] - 2024-01-15
|
||||
### Added
|
||||
- Add zoom sliders to the Tileset Editor.
|
||||
- Add `getMetatileBehaviorName` and `setMetatileBehaviorName` to the API.
|
||||
- Add `metatile_behaviors`, `num_primary_palettes`, and `num_secondary_palettes` to `constants` in the API.
|
||||
|
||||
### Changed
|
||||
- Metatile ID strings are now padded to their current max, not the overall max.
|
||||
- Non-existent directories are now removed from the Open Recent Project menu.
|
||||
- Hovering on the layer view in the Tileset Editor now displays the tile ID.
|
||||
- Labels in the Script dropdown are now sorted alphabetically.
|
||||
- The name of the Heal Locations table is no longer enforced.
|
||||
- The API functions `addImage` and `createImage` now support project-relative paths.
|
||||
|
||||
### Fixed
|
||||
- Fix the metatile selector rectangle jumping when selecting up or left of the origin.
|
||||
- Fix the event group tabs sometimes showing an event from the wrong group.
|
||||
- Fix the clear buttons in the Shortcuts Editor not actually removing shortcuts.
|
||||
- Fix slow speed for the script label autcomplete.
|
||||
- Fix deleted script labels still appearing in the autocomplete after project reload.
|
||||
- Fix the map search bar stealing focus on startup.
|
||||
- Fix border metatiles view not resizing properly.
|
||||
- Fix Open Recent Project not clearing the API overlay
|
||||
- Fix API error reporting.
|
||||
|
||||
## [5.2.0] - 2024-01-02
|
||||
### Added
|
||||
- Add an editor window under `Options -> Project Settings...` to customize the project-specific settings in `porymap.project.cfg` and `porymap.user.cfg`.
|
||||
- Add an editor window under `Options -> Custom Scripts...` for Porymap's API scripts.
|
||||
- Add an `Open Recent Project` menu
|
||||
- Add a warning to warp events if they're on an incompatible metatile behavior.
|
||||
- Add settings for custom images, including the collision graphics, default event icons, and pokémon icons.
|
||||
- Add settings to override any symbol or macro names Porymap expects to find.
|
||||
- Add a zoom slider to the Collision tab.
|
||||
- Add toggleable grids to the Tileset Editor.
|
||||
- Support for custom metatile ID, collision, and elevation data sizes.
|
||||
- Support for 8bpp tileset tile images.
|
||||
|
||||
### Changed
|
||||
- `Script` dropdowns now include scripts from the current map's scripts file.
|
||||
- Encounter Rate now defaults to the most commonly used value, rather than 0.
|
||||
- The Collision tab now allows selection of any valid elevation/collision value.
|
||||
- The Palette Editor now remembers the Bit Depth setting.
|
||||
- The min/max levels on the Wild Pokémon tab will now adjust automatically if they invalidate each other.
|
||||
- If the recent project directory doesn't exist Porymap will open an empty project instead of failing with a misleading error message.
|
||||
- Settings under `Options` were relocated either to the `Preferences` window or `Options -> Project Settings`.
|
||||
- Secret Base and Weather Trigger events are automatically disabled if their respective constants files fail to parse, instead of not opening the project.
|
||||
- If a Pokémon icon fails to load Porymap will attempt to predict its filepath. If this also fails it will appear with a placeholder icon, and won't disappear when edited.
|
||||
- The bits in metatile attribute masks are now allowed to be non-contiguous.
|
||||
- Porymap will now attempt to read metatile attribute masks from the project.
|
||||
|
||||
### Fixed
|
||||
- Fix text boxes in the Palette Editor calculating color incorrectly.
|
||||
- Fix metatile labels being sorted incorrectly for tileset names with multiple underscores.
|
||||
- Fix default object sprites retaining dimensions and transparency of the previous sprite.
|
||||
- Fix connections not being deleted when the map name text box is cleared.
|
||||
- Fix the map border not updating when a tileset is changed.
|
||||
- Improve the poor speed of the API functions `setMetatileTile` and `setMetatileTiles`.
|
||||
- Stop the Tileset Editor from scrolling to the initially selected metatile when saving.
|
||||
- Fix `0x0`/`NULL` appearing more than once in the scripts dropdown.
|
||||
- Fix the selection outline sticking in single-tile mode on the Prefab tab.
|
||||
- Fix heal location data being cleared if certain spaces aren't used in the table.
|
||||
- Fix bad URL color contrast on dark themes.
|
||||
- Fix some issues when too few/many pokémon are specified for a wild encounter group.
|
||||
- Fix Porymap reporting errors for macros it doesn't use.
|
||||
- Fix painting on the Collision tab with the opacity slider at 0 painting metatiles.
|
||||
- Fix crashes when File->Reload Project fails.
|
||||
- Fix overworld sprite facing directions if spritesheet has vertical layout.
|
||||
- Stop reporting `Error: Interrupted` for custom scripts during project reopen
|
||||
|
||||
## [5.1.1] - 2023-02-20
|
||||
### Added
|
||||
- Add `registerToggleAction` to the scripting API
|
||||
|
||||
### Changed
|
||||
- Change encounter tab copy and paste behavior.
|
||||
- A warning will appear if a custom script fails to load or an action fails to run.
|
||||
|
||||
### Fixed
|
||||
- Fix null characters being unpredictably written to some JSON files.
|
||||
- Fix tilesets that share part of their name loading incorrectly.
|
||||
- Fix events being hidden behind connecting maps.
|
||||
- Metatile labels with values defined outside their tileset are no longer deleted.
|
||||
- Fix the Tileset Editor retaining edit history after changing tilesets.
|
||||
- Fix some minor visual issues on the Connections tab.
|
||||
- Fix bug which caused encounter configurator to crash if slots in fields containing groups were deleted.
|
||||
- Fix bug which caused encounter configurator to crash if last field was deleted.
|
||||
- Fix map render when collision view was active while map changed.
|
||||
- Fix the updated pokefirered region map graphics appearing in grayscale.
|
||||
- Fix the API function `registerAction` not correctly handling actions with the same name.
|
||||
|
||||
## [5.1.0] - 2023-01-22
|
||||
### Added
|
||||
|
@ -383,7 +484,12 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
|
|||
## [1.0.0] - 2018-10-26
|
||||
This was the initial release.
|
||||
|
||||
[Unreleased]: https://github.com/huderlem/porymap/compare/5.1.0...HEAD
|
||||
[Unreleased]: https://github.com/huderlem/porymap/compare/5.4.1...HEAD
|
||||
[5.4.1]: https://github.com/huderlem/porymap/compare/5.4.0...5.4.1
|
||||
[5.4.0]: https://github.com/huderlem/porymap/compare/5.3.0...5.4.0
|
||||
[5.3.0]: https://github.com/huderlem/porymap/compare/5.2.0...5.3.0
|
||||
[5.2.0]: https://github.com/huderlem/porymap/compare/5.1.1...5.2.0
|
||||
[5.1.1]: https://github.com/huderlem/porymap/compare/5.1.0...5.1.1
|
||||
[5.1.0]: https://github.com/huderlem/porymap/compare/5.0.0...5.1.0
|
||||
[5.0.0]: https://github.com/huderlem/porymap/compare/4.5.0...5.0.0
|
||||
[4.5.0]: https://github.com/huderlem/porymap/compare/4.4.0...4.5.0
|
||||
|
|
BIN
docs/_static/ajax-loader.gif
vendored
Normal file
After Width: | Height: | Size: 673 B |
331
docs/_static/basic.css
vendored
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Sphinx stylesheet -- basic theme.
|
||||
*
|
||||
* :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS.
|
||||
* :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
@ -15,12 +15,6 @@ div.clearer {
|
|||
clear: both;
|
||||
}
|
||||
|
||||
div.section::after {
|
||||
display: block;
|
||||
content: '';
|
||||
clear: left;
|
||||
}
|
||||
|
||||
/* -- relbar ---------------------------------------------------------------- */
|
||||
|
||||
div.related {
|
||||
|
@ -130,7 +124,7 @@ ul.search li a {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
ul.search li p.context {
|
||||
ul.search li div.context {
|
||||
color: #888;
|
||||
margin: 2px 0 0 30px;
|
||||
text-align: left;
|
||||
|
@ -222,7 +216,7 @@ table.modindextable td {
|
|||
/* -- general body styles --------------------------------------------------- */
|
||||
|
||||
div.body {
|
||||
min-width: 360px;
|
||||
min-width: 450px;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
|
@ -267,25 +261,19 @@ p.rubric {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
img.align-left, figure.align-left, .figure.align-left, object.align-left {
|
||||
img.align-left, .figure.align-left, object.align-left {
|
||||
clear: left;
|
||||
float: left;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
img.align-right, figure.align-right, .figure.align-right, object.align-right {
|
||||
img.align-right, .figure.align-right, object.align-right {
|
||||
clear: right;
|
||||
float: right;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
img.align-center, figure.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
img.align-default, figure.align-default, .figure.align-default {
|
||||
img.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
@ -299,45 +287,30 @@ img.align-default, figure.align-default, .figure.align-default {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.align-default {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* -- sidebars -------------------------------------------------------------- */
|
||||
|
||||
div.sidebar,
|
||||
aside.sidebar {
|
||||
div.sidebar {
|
||||
margin: 0 0 0.5em 1em;
|
||||
border: 1px solid #ddb;
|
||||
padding: 7px;
|
||||
padding: 7px 7px 0 7px;
|
||||
background-color: #ffe;
|
||||
width: 40%;
|
||||
float: right;
|
||||
clear: right;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
p.sidebar-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
nav.contents,
|
||||
aside.topic,
|
||||
div.admonition, div.topic, blockquote {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
/* -- topics ---------------------------------------------------------------- */
|
||||
|
||||
nav.contents,
|
||||
aside.topic,
|
||||
div.topic {
|
||||
border: 1px solid #ccc;
|
||||
padding: 7px;
|
||||
padding: 7px 7px 0 7px;
|
||||
margin: 10px 0 10px 0;
|
||||
}
|
||||
|
||||
|
@ -359,6 +332,10 @@ div.admonition dt {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.admonition dl {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
margin: 0px 10px 5px 0px;
|
||||
font-weight: bold;
|
||||
|
@ -369,34 +346,9 @@ div.body p.centered {
|
|||
margin-top: 25px;
|
||||
}
|
||||
|
||||
/* -- content of sidebars/topics/admonitions -------------------------------- */
|
||||
|
||||
div.sidebar > :last-child,
|
||||
aside.sidebar > :last-child,
|
||||
nav.contents > :last-child,
|
||||
aside.topic > :last-child,
|
||||
div.topic > :last-child,
|
||||
div.admonition > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.sidebar::after,
|
||||
aside.sidebar::after,
|
||||
nav.contents::after,
|
||||
aside.topic::after,
|
||||
div.topic::after,
|
||||
div.admonition::after,
|
||||
blockquote::after {
|
||||
display: block;
|
||||
content: '';
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* -- tables ---------------------------------------------------------------- */
|
||||
|
||||
table.docutils {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
border: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
@ -406,11 +358,6 @@ table.align-center {
|
|||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-default {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table caption span.caption-number {
|
||||
font-style: italic;
|
||||
}
|
||||
|
@ -426,6 +373,10 @@ table.docutils td, table.docutils th {
|
|||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
|
||||
table.footnote td, table.footnote th {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
padding-right: 5px;
|
||||
|
@ -440,34 +391,22 @@ table.citation td {
|
|||
border-bottom: none;
|
||||
}
|
||||
|
||||
th > :first-child,
|
||||
td > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
th > :last-child,
|
||||
td > :last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
/* -- figures --------------------------------------------------------------- */
|
||||
|
||||
div.figure, figure {
|
||||
div.figure {
|
||||
margin: 0.5em;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
div.figure p.caption, figcaption {
|
||||
div.figure p.caption {
|
||||
padding: 0.3em;
|
||||
}
|
||||
|
||||
div.figure p.caption span.caption-number,
|
||||
figcaption span.caption-number {
|
||||
div.figure p.caption span.caption-number {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.figure p.caption span.caption-text,
|
||||
figcaption span.caption-text {
|
||||
div.figure p.caption span.caption-text {
|
||||
}
|
||||
|
||||
/* -- field list styles ----------------------------------------------------- */
|
||||
|
@ -494,71 +433,10 @@ table.field-list td, table.field-list th {
|
|||
|
||||
/* -- hlist styles ---------------------------------------------------------- */
|
||||
|
||||
table.hlist {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
table.hlist td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* -- object description styles --------------------------------------------- */
|
||||
|
||||
.sig {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
}
|
||||
|
||||
.sig-name, code.descname {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sig-name {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
code.descname {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.sig-prename, code.descclassname {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.optional {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.sig-paren {
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
.sig-param.n {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* C++ specific styling */
|
||||
|
||||
.sig-inline.c-texpr,
|
||||
.sig-inline.cpp-texpr {
|
||||
font-family: unset;
|
||||
}
|
||||
|
||||
.sig.c .k, .sig.c .kt,
|
||||
.sig.cpp .k, .sig.cpp .kt {
|
||||
color: #0033B3;
|
||||
}
|
||||
|
||||
.sig.c .m,
|
||||
.sig.cpp .m {
|
||||
color: #1750EB;
|
||||
}
|
||||
|
||||
.sig.c .s, .sig.c .sc,
|
||||
.sig.cpp .s, .sig.cpp .sc {
|
||||
color: #067D17;
|
||||
}
|
||||
|
||||
|
||||
/* -- other body styles ----------------------------------------------------- */
|
||||
|
||||
|
@ -582,81 +460,11 @@ ol.upperroman {
|
|||
list-style: upper-roman;
|
||||
}
|
||||
|
||||
:not(li) > ol > li:first-child > :first-child,
|
||||
:not(li) > ul > li:first-child > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
:not(li) > ol > li:last-child > :last-child,
|
||||
:not(li) > ul > li:last-child > :last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
ol.simple ol p,
|
||||
ol.simple ul p,
|
||||
ul.simple ol p,
|
||||
ul.simple ul p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ol.simple > li:not(:first-child) > p,
|
||||
ul.simple > li:not(:first-child) > p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ol.simple p,
|
||||
ul.simple p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
aside.footnote > span,
|
||||
div.citation > span {
|
||||
float: left;
|
||||
}
|
||||
aside.footnote > span:last-of-type,
|
||||
div.citation > span:last-of-type {
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
aside.footnote > p {
|
||||
margin-left: 2em;
|
||||
}
|
||||
div.citation > p {
|
||||
margin-left: 4em;
|
||||
}
|
||||
aside.footnote > p:last-of-type,
|
||||
div.citation > p:last-of-type {
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
aside.footnote > p:last-of-type:after,
|
||||
div.citation > p:last-of-type:after {
|
||||
content: "";
|
||||
clear: both;
|
||||
}
|
||||
|
||||
dl.field-list {
|
||||
display: grid;
|
||||
grid-template-columns: fit-content(30%) auto;
|
||||
}
|
||||
|
||||
dl.field-list > dt {
|
||||
font-weight: bold;
|
||||
word-break: break-word;
|
||||
padding-left: 0.5em;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
dl.field-list > dd {
|
||||
padding-left: 0.5em;
|
||||
margin-top: 0em;
|
||||
margin-left: 0em;
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
dd > :first-child {
|
||||
dd p {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
|
@ -670,11 +478,6 @@ dd {
|
|||
margin-left: 30px;
|
||||
}
|
||||
|
||||
dl > dd:last-child,
|
||||
dl > dd:last-child > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt:target, span.highlighted {
|
||||
background-color: #fbe54e;
|
||||
}
|
||||
|
@ -688,6 +491,14 @@ dl.glossary dt {
|
|||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.optional {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.sig-paren {
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
.versionmodified {
|
||||
font-style: italic;
|
||||
}
|
||||
|
@ -726,13 +537,6 @@ dl.glossary dt {
|
|||
font-style: oblique;
|
||||
}
|
||||
|
||||
.classifier:before {
|
||||
font-style: normal;
|
||||
margin: 0 0.5em;
|
||||
content: ":";
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
abbr, acronym {
|
||||
border-bottom: dotted 1px;
|
||||
cursor: help;
|
||||
|
@ -745,69 +549,29 @@ pre {
|
|||
overflow-y: hidden; /* fixes display issues on Chrome browsers */
|
||||
}
|
||||
|
||||
pre, div[class*="highlight-"] {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
span.pre {
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
-webkit-hyphens: none;
|
||||
hyphens: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div[class*="highlight-"] {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
td.linenos pre {
|
||||
padding: 5px 0px;
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
table.highlighttable {
|
||||
display: block;
|
||||
}
|
||||
|
||||
table.highlighttable tbody {
|
||||
display: block;
|
||||
}
|
||||
|
||||
table.highlighttable tr {
|
||||
display: flex;
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
|
||||
table.highlighttable td {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table.highlighttable td.linenos {
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
|
||||
table.highlighttable td.code {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.highlight .hll {
|
||||
display: block;
|
||||
}
|
||||
|
||||
div.highlight pre,
|
||||
table.highlighttable pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.code-block-caption + div {
|
||||
margin-top: 0;
|
||||
padding: 0 0.5em 0 0.5em;
|
||||
}
|
||||
|
||||
div.code-block-caption {
|
||||
margin-top: 1em;
|
||||
padding: 2px 5px;
|
||||
font-size: small;
|
||||
}
|
||||
|
@ -816,14 +580,8 @@ div.code-block-caption code {
|
|||
background-color: transparent;
|
||||
}
|
||||
|
||||
table.highlighttable td.linenos,
|
||||
span.linenos,
|
||||
div.highlight span.gp { /* gp: Generic.Prompt */
|
||||
user-select: none;
|
||||
-webkit-user-select: text; /* Safari fallback only */
|
||||
-webkit-user-select: none; /* Chrome/Safari */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* IE10+ */
|
||||
div.code-block-caption + div > div.highlight > pre {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
div.code-block-caption span.caption-number {
|
||||
|
@ -835,7 +593,21 @@ div.code-block-caption span.caption-text {
|
|||
}
|
||||
|
||||
div.literal-block-wrapper {
|
||||
margin: 1em 0;
|
||||
padding: 1em 1em 0;
|
||||
}
|
||||
|
||||
div.literal-block-wrapper div.highlight {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
code.descname {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
code.descclassname {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
code.xref, a code {
|
||||
|
@ -876,7 +648,8 @@ span.eqno {
|
|||
}
|
||||
|
||||
span.eqno a.headerlink {
|
||||
position: absolute;
|
||||
position: relative;
|
||||
left: 0px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
|
BIN
docs/_static/comment-bright.png
vendored
Normal file
After Width: | Height: | Size: 756 B |
BIN
docs/_static/comment-close.png
vendored
Normal file
After Width: | Height: | Size: 829 B |
BIN
docs/_static/comment.png
vendored
Normal file
After Width: | Height: | Size: 641 B |
2
docs/_static/css/badge_only.css
vendored
|
@ -1 +1 @@
|
|||
.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}
|
||||
.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../fonts/fontawesome-webfont.eot");src:url("../fonts/fontawesome-webfont.eot?#iefix") format("embedded-opentype"),url("../fonts/fontawesome-webfont.woff") format("woff"),url("../fonts/fontawesome-webfont.ttf") format("truetype"),url("../fonts/fontawesome-webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}
|
||||
|
|
6
docs/_static/css/theme.css
vendored
379
docs/_static/doctools.js
vendored
|
@ -2,155 +2,314 @@
|
|||
* doctools.js
|
||||
* ~~~~~~~~~~~
|
||||
*
|
||||
* Base JavaScript utilities for all Sphinx HTML documentation.
|
||||
* Sphinx JavaScript utilities for all documentation.
|
||||
*
|
||||
* :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS.
|
||||
* :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([
|
||||
"TEXTAREA",
|
||||
"INPUT",
|
||||
"SELECT",
|
||||
"BUTTON",
|
||||
]);
|
||||
/**
|
||||
* select a different prefix for underscore
|
||||
*/
|
||||
$u = _.noConflict();
|
||||
|
||||
const _ready = (callback) => {
|
||||
if (document.readyState !== "loading") {
|
||||
callback();
|
||||
} else {
|
||||
document.addEventListener("DOMContentLoaded", callback);
|
||||
}
|
||||
/**
|
||||
* make the code below compatible with browsers without
|
||||
* an installed firebug like debugger
|
||||
if (!window.console || !console.firebug) {
|
||||
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
|
||||
"dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
|
||||
"profile", "profileEnd"];
|
||||
window.console = {};
|
||||
for (var i = 0; i < names.length; ++i)
|
||||
window.console[names[i]] = function() {};
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* small helper function to urldecode strings
|
||||
*/
|
||||
jQuery.urldecode = function(x) {
|
||||
return decodeURIComponent(x).replace(/\+/g, ' ');
|
||||
};
|
||||
|
||||
/**
|
||||
* small helper function to urlencode strings
|
||||
*/
|
||||
jQuery.urlencode = encodeURIComponent;
|
||||
|
||||
/**
|
||||
* This function returns the parsed url parameters of the
|
||||
* current request. Multiple values per key are supported,
|
||||
* it will always return arrays of strings for the value parts.
|
||||
*/
|
||||
jQuery.getQueryParameters = function(s) {
|
||||
if (typeof s === 'undefined')
|
||||
s = document.location.search;
|
||||
var parts = s.substr(s.indexOf('?') + 1).split('&');
|
||||
var result = {};
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var tmp = parts[i].split('=', 2);
|
||||
var key = jQuery.urldecode(tmp[0]);
|
||||
var value = jQuery.urldecode(tmp[1]);
|
||||
if (key in result)
|
||||
result[key].push(value);
|
||||
else
|
||||
result[key] = [value];
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* highlight a given string on a jquery object by wrapping it in
|
||||
* span elements with the given class name.
|
||||
*/
|
||||
jQuery.fn.highlightText = function(text, className) {
|
||||
function highlight(node, addItems) {
|
||||
if (node.nodeType === 3) {
|
||||
var val = node.nodeValue;
|
||||
var pos = val.toLowerCase().indexOf(text);
|
||||
if (pos >= 0 &&
|
||||
!jQuery(node.parentNode).hasClass(className) &&
|
||||
!jQuery(node.parentNode).hasClass("nohighlight")) {
|
||||
var span;
|
||||
var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
|
||||
if (isInSVG) {
|
||||
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
|
||||
} else {
|
||||
span = document.createElement("span");
|
||||
span.className = className;
|
||||
}
|
||||
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
|
||||
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
|
||||
document.createTextNode(val.substr(pos + text.length)),
|
||||
node.nextSibling));
|
||||
node.nodeValue = val.substr(0, pos);
|
||||
if (isInSVG) {
|
||||
var bbox = span.getBBox();
|
||||
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
||||
rect.x.baseVal.value = bbox.x;
|
||||
rect.y.baseVal.value = bbox.y;
|
||||
rect.width.baseVal.value = bbox.width;
|
||||
rect.height.baseVal.value = bbox.height;
|
||||
rect.setAttribute('class', className);
|
||||
var parentOfText = node.parentNode.parentNode;
|
||||
addItems.push({
|
||||
"parent": node.parentNode,
|
||||
"target": rect});
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!jQuery(node).is("button, select, textarea")) {
|
||||
jQuery.each(node.childNodes, function() {
|
||||
highlight(this, addItems);
|
||||
});
|
||||
}
|
||||
}
|
||||
var addItems = [];
|
||||
var result = this.each(function() {
|
||||
highlight(this, addItems);
|
||||
});
|
||||
for (var i = 0; i < addItems.length; ++i) {
|
||||
jQuery(addItems[i].parent).before(addItems[i].target);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/*
|
||||
* backward compatibility for jQuery.browser
|
||||
* This will be supported until firefox bug is fixed.
|
||||
*/
|
||||
if (!jQuery.browser) {
|
||||
jQuery.uaMatch = function(ua) {
|
||||
ua = ua.toLowerCase();
|
||||
|
||||
var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
|
||||
/(webkit)[ \/]([\w.]+)/.exec(ua) ||
|
||||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
|
||||
/(msie) ([\w.]+)/.exec(ua) ||
|
||||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
|
||||
[];
|
||||
|
||||
return {
|
||||
browser: match[ 1 ] || "",
|
||||
version: match[ 2 ] || "0"
|
||||
};
|
||||
};
|
||||
jQuery.browser = {};
|
||||
jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Small JavaScript module for the documentation.
|
||||
*/
|
||||
const Documentation = {
|
||||
init: () => {
|
||||
Documentation.initDomainIndexTable();
|
||||
Documentation.initOnKeyListeners();
|
||||
var Documentation = {
|
||||
|
||||
init : function() {
|
||||
this.fixFirefoxAnchorBug();
|
||||
this.highlightSearchWords();
|
||||
this.initIndexTable();
|
||||
if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) {
|
||||
this.initOnKeyListeners();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* i18n support
|
||||
*/
|
||||
TRANSLATIONS: {},
|
||||
PLURAL_EXPR: (n) => (n === 1 ? 0 : 1),
|
||||
LOCALE: "unknown",
|
||||
TRANSLATIONS : {},
|
||||
PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
|
||||
LOCALE : 'unknown',
|
||||
|
||||
// gettext and ngettext don't access this so that the functions
|
||||
// can safely bound to a different name (_ = Documentation.gettext)
|
||||
gettext: (string) => {
|
||||
const translated = Documentation.TRANSLATIONS[string];
|
||||
switch (typeof translated) {
|
||||
case "undefined":
|
||||
return string; // no translation
|
||||
case "string":
|
||||
return translated; // translation exists
|
||||
default:
|
||||
return translated[0]; // (singular, plural) translation tuple exists
|
||||
gettext : function(string) {
|
||||
var translated = Documentation.TRANSLATIONS[string];
|
||||
if (typeof translated === 'undefined')
|
||||
return string;
|
||||
return (typeof translated === 'string') ? translated : translated[0];
|
||||
},
|
||||
|
||||
ngettext : function(singular, plural, n) {
|
||||
var translated = Documentation.TRANSLATIONS[singular];
|
||||
if (typeof translated === 'undefined')
|
||||
return (n == 1) ? singular : plural;
|
||||
return translated[Documentation.PLURALEXPR(n)];
|
||||
},
|
||||
|
||||
addTranslations : function(catalog) {
|
||||
for (var key in catalog.messages)
|
||||
this.TRANSLATIONS[key] = catalog.messages[key];
|
||||
this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
|
||||
this.LOCALE = catalog.locale;
|
||||
},
|
||||
|
||||
/**
|
||||
* add context elements like header anchor links
|
||||
*/
|
||||
addContextElements : function() {
|
||||
$('div[id] > :header:first').each(function() {
|
||||
$('<a class="headerlink">\u00B6</a>').
|
||||
attr('href', '#' + this.id).
|
||||
attr('title', _('Permalink to this headline')).
|
||||
appendTo(this);
|
||||
});
|
||||
$('dt[id]').each(function() {
|
||||
$('<a class="headerlink">\u00B6</a>').
|
||||
attr('href', '#' + this.id).
|
||||
attr('title', _('Permalink to this definition')).
|
||||
appendTo(this);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* workaround a firefox stupidity
|
||||
* see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
|
||||
*/
|
||||
fixFirefoxAnchorBug : function() {
|
||||
if (document.location.hash && $.browser.mozilla)
|
||||
window.setTimeout(function() {
|
||||
document.location.href += '';
|
||||
}, 10);
|
||||
},
|
||||
|
||||
/**
|
||||
* highlight the search words provided in the url in the text
|
||||
*/
|
||||
highlightSearchWords : function() {
|
||||
var params = $.getQueryParameters();
|
||||
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
|
||||
if (terms.length) {
|
||||
var body = $('div.body');
|
||||
if (!body.length) {
|
||||
body = $('body');
|
||||
}
|
||||
window.setTimeout(function() {
|
||||
$.each(terms, function() {
|
||||
body.highlightText(this.toLowerCase(), 'highlighted');
|
||||
});
|
||||
}, 10);
|
||||
$('<p class="highlight-link"><a href="javascript:Documentation.' +
|
||||
'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>')
|
||||
.appendTo($('#searchbox'));
|
||||
}
|
||||
},
|
||||
|
||||
ngettext: (singular, plural, n) => {
|
||||
const translated = Documentation.TRANSLATIONS[singular];
|
||||
if (typeof translated !== "undefined")
|
||||
return translated[Documentation.PLURAL_EXPR(n)];
|
||||
return n === 1 ? singular : plural;
|
||||
},
|
||||
|
||||
addTranslations: (catalog) => {
|
||||
Object.assign(Documentation.TRANSLATIONS, catalog.messages);
|
||||
Documentation.PLURAL_EXPR = new Function(
|
||||
"n",
|
||||
`return (${catalog.plural_expr})`
|
||||
);
|
||||
Documentation.LOCALE = catalog.locale;
|
||||
/**
|
||||
* init the domain index toggle buttons
|
||||
*/
|
||||
initIndexTable : function() {
|
||||
var togglers = $('img.toggler').click(function() {
|
||||
var src = $(this).attr('src');
|
||||
var idnum = $(this).attr('id').substr(7);
|
||||
$('tr.cg-' + idnum).toggle();
|
||||
if (src.substr(-9) === 'minus.png')
|
||||
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
|
||||
else
|
||||
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
|
||||
}).css('display', '');
|
||||
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
|
||||
togglers.click();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* helper function to focus on search bar
|
||||
* helper function to hide the search marks again
|
||||
*/
|
||||
focusSearchBar: () => {
|
||||
document.querySelectorAll("input[name=q]")[0]?.focus();
|
||||
hideSearchWords : function() {
|
||||
$('#searchbox .highlight-link').fadeOut(300);
|
||||
$('span.highlighted').removeClass('highlighted');
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialise the domain index toggle buttons
|
||||
* make the url absolute
|
||||
*/
|
||||
initDomainIndexTable: () => {
|
||||
const toggler = (el) => {
|
||||
const idNumber = el.id.substr(7);
|
||||
const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`);
|
||||
if (el.src.substr(-9) === "minus.png") {
|
||||
el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`;
|
||||
toggledRows.forEach((el) => (el.style.display = "none"));
|
||||
} else {
|
||||
el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`;
|
||||
toggledRows.forEach((el) => (el.style.display = ""));
|
||||
}
|
||||
};
|
||||
|
||||
const togglerElements = document.querySelectorAll("img.toggler");
|
||||
togglerElements.forEach((el) =>
|
||||
el.addEventListener("click", (event) => toggler(event.currentTarget))
|
||||
);
|
||||
togglerElements.forEach((el) => (el.style.display = ""));
|
||||
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler);
|
||||
makeURL : function(relativeURL) {
|
||||
return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
|
||||
},
|
||||
|
||||
initOnKeyListeners: () => {
|
||||
// only install a listener if it is really needed
|
||||
if (
|
||||
!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS &&
|
||||
!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS
|
||||
)
|
||||
return;
|
||||
/**
|
||||
* get the current relative url
|
||||
*/
|
||||
getCurrentURL : function() {
|
||||
var path = document.location.pathname;
|
||||
var parts = path.split(/\//);
|
||||
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
|
||||
if (this === '..')
|
||||
parts.pop();
|
||||
});
|
||||
var url = parts.join('/');
|
||||
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
|
||||
},
|
||||
|
||||
document.addEventListener("keydown", (event) => {
|
||||
// bail for input elements
|
||||
if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return;
|
||||
// bail with special keys
|
||||
if (event.altKey || event.ctrlKey || event.metaKey) return;
|
||||
|
||||
if (!event.shiftKey) {
|
||||
switch (event.key) {
|
||||
case "ArrowLeft":
|
||||
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
|
||||
|
||||
const prevLink = document.querySelector('link[rel="prev"]');
|
||||
if (prevLink && prevLink.href) {
|
||||
window.location.href = prevLink.href;
|
||||
event.preventDefault();
|
||||
initOnKeyListeners: function() {
|
||||
$(document).keyup(function(event) {
|
||||
var activeElementType = document.activeElement.tagName;
|
||||
// don't navigate when in search box or textarea
|
||||
if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') {
|
||||
switch (event.keyCode) {
|
||||
case 37: // left
|
||||
var prevHref = $('link[rel="prev"]').prop('href');
|
||||
if (prevHref) {
|
||||
window.location.href = prevHref;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case "ArrowRight":
|
||||
if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break;
|
||||
|
||||
const nextLink = document.querySelector('link[rel="next"]');
|
||||
if (nextLink && nextLink.href) {
|
||||
window.location.href = nextLink.href;
|
||||
event.preventDefault();
|
||||
case 39: // right
|
||||
var nextHref = $('link[rel="next"]').prop('href');
|
||||
if (nextHref) {
|
||||
window.location.href = nextHref;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// some keyboard layouts may need Shift to get /
|
||||
switch (event.key) {
|
||||
case "/":
|
||||
if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break;
|
||||
Documentation.focusSearchBar();
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
// quick alias for translations
|
||||
const _ = Documentation.gettext;
|
||||
_ = Documentation.gettext;
|
||||
|
||||
_ready(Documentation.init);
|
||||
$(document).ready(function() {
|
||||
Documentation.init();
|
||||
});
|
||||
|
|
4
docs/_static/documentation_options.js
vendored
|
@ -3,12 +3,8 @@ var DOCUMENTATION_OPTIONS = {
|
|||
VERSION: '',
|
||||
LANGUAGE: 'en',
|
||||
COLLAPSE_INDEX: false,
|
||||
BUILDER: 'html',
|
||||
FILE_SUFFIX: '.html',
|
||||
LINK_SUFFIX: '.html',
|
||||
HAS_SOURCE: true,
|
||||
SOURCELINK_SUFFIX: '.txt',
|
||||
NAVIGATION_WITH_KEYS: false,
|
||||
SHOW_SEARCH_SUMMARY: true,
|
||||
ENABLE_SEARCH_SHORTCUTS: true,
|
||||
};
|
BIN
docs/_static/down-pressed.png
vendored
Normal file
After Width: | Height: | Size: 222 B |
BIN
docs/_static/down.png
vendored
Normal file
After Width: | Height: | Size: 202 B |
BIN
docs/_static/fonts/Inconsolata-Bold.ttf
vendored
Normal file
BIN
docs/_static/fonts/Inconsolata-Regular.ttf
vendored
Normal file
BIN
docs/_static/fonts/Inconsolata.ttf
vendored
Normal file
BIN
docs/_static/fonts/Lato-Bold.ttf
vendored
Normal file
BIN
docs/_static/fonts/Lato-Regular.ttf
vendored
Normal file
BIN
docs/_static/fonts/Lato/lato-bold.eot
vendored
Normal file
BIN
docs/_static/fonts/Lato/lato-bold.ttf
vendored
Normal file
BIN
docs/_static/fonts/Lato/lato-bolditalic.eot
vendored
Normal file
BIN
docs/_static/fonts/Lato/lato-bolditalic.ttf
vendored
Normal file
BIN
docs/_static/fonts/Lato/lato-italic.eot
vendored
Normal file
BIN
docs/_static/fonts/Lato/lato-italic.ttf
vendored
Normal file
BIN
docs/_static/fonts/Lato/lato-regular.eot
vendored
Normal file
BIN
docs/_static/fonts/Lato/lato-regular.ttf
vendored
Normal file
BIN
docs/_static/fonts/RobotoSlab-Bold.ttf
vendored
Normal file
BIN
docs/_static/fonts/RobotoSlab-Regular.ttf
vendored
Normal file
BIN
docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot
vendored
Normal file
BIN
docs/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf
vendored
Normal file
BIN
docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot
vendored
Normal file
BIN
docs/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf
vendored
Normal file
Before Width: | Height: | Size: 434 KiB After Width: | Height: | Size: 434 KiB |
10253
docs/_static/jquery-3.2.1.js
vendored
Normal file
4
docs/_static/jquery.js
vendored
Normal file
1
docs/_static/js/badge_only.js
vendored
|
@ -1 +0,0 @@
|
|||
!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=4)}({4:function(e,t,r){}});
|
4
docs/_static/js/html5shiv-printshiv.min.js
vendored
|
@ -1,4 +0,0 @@
|
|||
/**
|
||||
* @preserve HTML5 Shiv 3.7.3-pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
||||
*/
|
||||
!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=y.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=y.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),y.elements=c+" "+a,j(b)}function f(a){var b=x[a[v]];return b||(b={},w++,a[v]=w,x[w]=b),b}function g(a,c,d){if(c||(c=b),q)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():u.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||t.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),q)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return y.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(y,b.frag)}function j(a){a||(a=b);var d=f(a);return!y.shivCSS||p||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),q||i(a,d),a}function k(a){for(var b,c=a.getElementsByTagName("*"),e=c.length,f=RegExp("^(?:"+d().join("|")+")$","i"),g=[];e--;)b=c[e],f.test(b.nodeName)&&g.push(b.applyElement(l(b)));return g}function l(a){for(var b,c=a.attributes,d=c.length,e=a.ownerDocument.createElement(A+":"+a.nodeName);d--;)b=c[d],b.specified&&e.setAttribute(b.nodeName,b.nodeValue);return e.style.cssText=a.style.cssText,e}function m(a){for(var b,c=a.split("{"),e=c.length,f=RegExp("(^|[\\s,>+~])("+d().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),g="$1"+A+"\\:$2";e--;)b=c[e]=c[e].split("}"),b[b.length-1]=b[b.length-1].replace(f,g),c[e]=b.join("}");return c.join("{")}function n(a){for(var b=a.length;b--;)a[b].removeNode()}function o(a){function b(){clearTimeout(g._removeSheetTimer),d&&d.removeNode(!0),d=null}var d,e,g=f(a),h=a.namespaces,i=a.parentWindow;return!B||a.printShived?a:("undefined"==typeof h[A]&&h.add(A),i.attachEvent("onbeforeprint",function(){b();for(var f,g,h,i=a.styleSheets,j=[],l=i.length,n=Array(l);l--;)n[l]=i[l];for(;h=n.pop();)if(!h.disabled&&z.test(h.media)){try{f=h.imports,g=f.length}catch(o){g=0}for(l=0;g>l;l++)n.push(f[l]);try{j.push(h.cssText)}catch(o){}}j=m(j.reverse().join("")),e=k(a),d=c(a,j)}),i.attachEvent("onafterprint",function(){n(e),clearTimeout(g._removeSheetTimer),g._removeSheetTimer=setTimeout(b,500)}),a.printShived=!0,a)}var p,q,r="3.7.3",s=a.html5||{},t=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,u=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,v="_html5shiv",w=0,x={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",p="hidden"in a,q=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){p=!0,q=!0}}();var y={elements:s.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:r,shivCSS:s.shivCSS!==!1,supportsUnknownElements:q,shivMethods:s.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=y,j(b);var z=/^$|\b(?:all|print)\b/,A="html5shiv",B=!q&&function(){var c=b.documentElement;return!("undefined"==typeof b.namespaces||"undefined"==typeof b.parentWindow||"undefined"==typeof c.applyElement||"undefined"==typeof c.removeNode||"undefined"==typeof a.attachEvent)}();y.type+=" print",y.shivPrint=o,o(b),"object"==typeof module&&module.exports&&(module.exports=y)}("undefined"!=typeof window?window:this,document);
|
4
docs/_static/js/html5shiv.min.js
vendored
|
@ -1,4 +0,0 @@
|
|||
/**
|
||||
* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
||||
*/
|
||||
!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3-pre",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document);
|
4
docs/_static/js/modernizr.min.js
vendored
Normal file
4
docs/_static/js/theme.js
vendored
106
docs/_static/language_data.js
vendored
|
@ -5,16 +5,15 @@
|
|||
* This script contains the language-specific data used by searchtools.js,
|
||||
* namely the list of stopwords, stemmer, scorer and splitter.
|
||||
*
|
||||
* :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS.
|
||||
* :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"];
|
||||
var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"];
|
||||
|
||||
|
||||
/* Non-minified version is copied as a separate JS file, is available */
|
||||
|
||||
/* Non-minified version JS is _stemmer.js if file is provided */
|
||||
/**
|
||||
* Porter Stemmer
|
||||
*/
|
||||
|
@ -197,3 +196,102 @@ var Stemmer = function() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
var splitChars = (function() {
|
||||
var result = {};
|
||||
var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648,
|
||||
1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702,
|
||||
2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971,
|
||||
2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345,
|
||||
3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761,
|
||||
3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823,
|
||||
4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125,
|
||||
8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695,
|
||||
11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587,
|
||||
43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141];
|
||||
var i, j, start, end;
|
||||
for (i = 0; i < singles.length; i++) {
|
||||
result[singles[i]] = true;
|
||||
}
|
||||
var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709],
|
||||
[722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161],
|
||||
[1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568],
|
||||
[1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807],
|
||||
[1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047],
|
||||
[2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383],
|
||||
[2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450],
|
||||
[2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547],
|
||||
[2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673],
|
||||
[2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820],
|
||||
[2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946],
|
||||
[2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023],
|
||||
[3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173],
|
||||
[3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332],
|
||||
[3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481],
|
||||
[3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718],
|
||||
[3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791],
|
||||
[3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095],
|
||||
[4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205],
|
||||
[4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687],
|
||||
[4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968],
|
||||
[4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869],
|
||||
[5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102],
|
||||
[6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271],
|
||||
[6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592],
|
||||
[6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822],
|
||||
[6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167],
|
||||
[7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959],
|
||||
[7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143],
|
||||
[8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318],
|
||||
[8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483],
|
||||
[8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101],
|
||||
[10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567],
|
||||
[11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292],
|
||||
[12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444],
|
||||
[12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783],
|
||||
[12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311],
|
||||
[19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511],
|
||||
[42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774],
|
||||
[42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071],
|
||||
[43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263],
|
||||
[43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519],
|
||||
[43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647],
|
||||
[43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967],
|
||||
[44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295],
|
||||
[57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274],
|
||||
[64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007],
|
||||
[65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381],
|
||||
[65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]];
|
||||
for (i = 0; i < ranges.length; i++) {
|
||||
start = ranges[i][0];
|
||||
end = ranges[i][1];
|
||||
for (j = start; j <= end; j++) {
|
||||
result[j] = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
})();
|
||||
|
||||
function splitQuery(query) {
|
||||
var result = [];
|
||||
var start = -1;
|
||||
for (var i = 0; i < query.length; i++) {
|
||||
if (splitChars[query.charCodeAt(i)]) {
|
||||
if (start !== -1) {
|
||||
result.push(query.slice(start, i));
|
||||
start = -1;
|
||||
}
|
||||
} else if (start === -1) {
|
||||
start = i;
|
||||
}
|
||||
}
|
||||
if (start !== -1) {
|
||||
result.push(query.slice(start));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
41
docs/_static/pygments.css
vendored
|
@ -1,26 +1,21 @@
|
|||
pre { line-height: 125%; }
|
||||
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||
.highlight .hll { background-color: #ffffcc }
|
||||
.highlight { background: #f8f8f8; }
|
||||
.highlight .c { color: #3D7B7B; font-style: italic } /* Comment */
|
||||
.highlight { background: #f8f8f8; }
|
||||
.highlight .c { color: #408080; font-style: italic } /* Comment */
|
||||
.highlight .err { border: 1px solid #FF0000 } /* Error */
|
||||
.highlight .k { color: #008000; font-weight: bold } /* Keyword */
|
||||
.highlight .o { color: #666666 } /* Operator */
|
||||
.highlight .ch { color: #3D7B7B; font-style: italic } /* Comment.Hashbang */
|
||||
.highlight .cm { color: #3D7B7B; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #9C6500 } /* Comment.Preproc */
|
||||
.highlight .cpf { color: #3D7B7B; font-style: italic } /* Comment.PreprocFile */
|
||||
.highlight .c1 { color: #3D7B7B; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #3D7B7B; font-style: italic } /* Comment.Special */
|
||||
.highlight .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
|
||||
.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #BC7A00 } /* Comment.Preproc */
|
||||
.highlight .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
|
||||
.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */
|
||||
.highlight .gd { color: #A00000 } /* Generic.Deleted */
|
||||
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #E40000 } /* Generic.Error */
|
||||
.highlight .gr { color: #FF0000 } /* Generic.Error */
|
||||
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
.highlight .gi { color: #008400 } /* Generic.Inserted */
|
||||
.highlight .go { color: #717171 } /* Generic.Output */
|
||||
.highlight .gi { color: #00A000 } /* Generic.Inserted */
|
||||
.highlight .go { color: #888888 } /* Generic.Output */
|
||||
.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
|
@ -33,15 +28,15 @@ span.linenos.special { color: #000000; background-color: #ffffc0; padding-left:
|
|||
.highlight .kt { color: #B00040 } /* Keyword.Type */
|
||||
.highlight .m { color: #666666 } /* Literal.Number */
|
||||
.highlight .s { color: #BA2121 } /* Literal.String */
|
||||
.highlight .na { color: #687822 } /* Name.Attribute */
|
||||
.highlight .na { color: #7D9029 } /* Name.Attribute */
|
||||
.highlight .nb { color: #008000 } /* Name.Builtin */
|
||||
.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */
|
||||
.highlight .no { color: #880000 } /* Name.Constant */
|
||||
.highlight .nd { color: #AA22FF } /* Name.Decorator */
|
||||
.highlight .ni { color: #717171; font-weight: bold } /* Name.Entity */
|
||||
.highlight .ne { color: #CB3F38; font-weight: bold } /* Name.Exception */
|
||||
.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */
|
||||
.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
|
||||
.highlight .nf { color: #0000FF } /* Name.Function */
|
||||
.highlight .nl { color: #767600 } /* Name.Label */
|
||||
.highlight .nl { color: #A0A000 } /* Name.Label */
|
||||
.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
|
||||
.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */
|
||||
.highlight .nv { color: #19177C } /* Name.Variable */
|
||||
|
@ -58,11 +53,11 @@ span.linenos.special { color: #000000; background-color: #ffffc0; padding-left:
|
|||
.highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */
|
||||
.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #BA2121 } /* Literal.String.Double */
|
||||
.highlight .se { color: #AA5D1F; font-weight: bold } /* Literal.String.Escape */
|
||||
.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #A45A77; font-weight: bold } /* Literal.String.Interpol */
|
||||
.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #008000 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #A45A77 } /* Literal.String.Regex */
|
||||
.highlight .sr { color: #BB6688 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #BA2121 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #19177C } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */
|
||||
|
|
775
docs/_static/searchtools.js
vendored
|
@ -4,24 +4,22 @@
|
|||
*
|
||||
* Sphinx JavaScript utilities for the full-text search.
|
||||
*
|
||||
* :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS.
|
||||
* :copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Simple result scoring code.
|
||||
*/
|
||||
if (typeof Scorer === "undefined") {
|
||||
if (!Scorer) {
|
||||
/**
|
||||
* Simple result scoring code.
|
||||
*/
|
||||
var Scorer = {
|
||||
// Implement the following function to further tweak the score for each result
|
||||
// The function takes a result array [docname, title, anchor, descr, score, filename]
|
||||
// The function takes a result array [filename, title, anchor, descr, score]
|
||||
// and returns the new score.
|
||||
/*
|
||||
score: result => {
|
||||
const [docname, title, anchor, descr, score, filename] = result
|
||||
return score
|
||||
score: function(result) {
|
||||
return result[4];
|
||||
},
|
||||
*/
|
||||
|
||||
|
@ -30,508 +28,423 @@ if (typeof Scorer === "undefined") {
|
|||
// or matches in the last dotted part of the object name
|
||||
objPartialMatch: 6,
|
||||
// Additive scores depending on the priority of the object
|
||||
objPrio: {
|
||||
0: 15, // used to be importantResults
|
||||
1: 5, // used to be objectResults
|
||||
2: -5, // used to be unimportantResults
|
||||
},
|
||||
objPrio: {0: 15, // used to be importantResults
|
||||
1: 5, // used to be objectResults
|
||||
2: -5}, // used to be unimportantResults
|
||||
// Used when the priority is not in the mapping.
|
||||
objPrioDefault: 0,
|
||||
|
||||
// query found in title
|
||||
title: 15,
|
||||
partialTitle: 7,
|
||||
// query found in terms
|
||||
term: 5,
|
||||
partialTerm: 2,
|
||||
term: 5
|
||||
};
|
||||
}
|
||||
|
||||
const _removeChildren = (element) => {
|
||||
while (element && element.lastChild) element.removeChild(element.lastChild);
|
||||
};
|
||||
|
||||
/**
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
|
||||
*/
|
||||
const _escapeRegExp = (string) =>
|
||||
string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
|
||||
|
||||
const _displayItem = (item, searchTerms) => {
|
||||
const docBuilder = DOCUMENTATION_OPTIONS.BUILDER;
|
||||
const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT;
|
||||
const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX;
|
||||
const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX;
|
||||
const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY;
|
||||
|
||||
const [docName, title, anchor, descr, score, _filename] = item;
|
||||
|
||||
let listItem = document.createElement("li");
|
||||
let requestUrl;
|
||||
let linkUrl;
|
||||
if (docBuilder === "dirhtml") {
|
||||
// dirhtml builder
|
||||
let dirname = docName + "/";
|
||||
if (dirname.match(/\/index\/$/))
|
||||
dirname = dirname.substring(0, dirname.length - 6);
|
||||
else if (dirname === "index/") dirname = "";
|
||||
requestUrl = docUrlRoot + dirname;
|
||||
linkUrl = requestUrl;
|
||||
} else {
|
||||
// normal html builders
|
||||
requestUrl = docUrlRoot + docName + docFileSuffix;
|
||||
linkUrl = docName + docLinkSuffix;
|
||||
if (!splitQuery) {
|
||||
function splitQuery(query) {
|
||||
return query.split(/\s+/);
|
||||
}
|
||||
let linkEl = listItem.appendChild(document.createElement("a"));
|
||||
linkEl.href = linkUrl + anchor;
|
||||
linkEl.dataset.score = score;
|
||||
linkEl.innerHTML = title;
|
||||
if (descr)
|
||||
listItem.appendChild(document.createElement("span")).innerHTML =
|
||||
" (" + descr + ")";
|
||||
else if (showSearchSummary)
|
||||
fetch(requestUrl)
|
||||
.then((responseData) => responseData.text())
|
||||
.then((data) => {
|
||||
if (data)
|
||||
listItem.appendChild(
|
||||
Search.makeSearchSummary(data, searchTerms)
|
||||
);
|
||||
});
|
||||
Search.output.appendChild(listItem);
|
||||
};
|
||||
const _finishSearch = (resultCount) => {
|
||||
Search.stopPulse();
|
||||
Search.title.innerText = _("Search Results");
|
||||
if (!resultCount)
|
||||
Search.status.innerText = Documentation.gettext(
|
||||
"Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories."
|
||||
);
|
||||
else
|
||||
Search.status.innerText = _(
|
||||
`Search finished, found ${resultCount} page(s) matching the search query.`
|
||||
);
|
||||
};
|
||||
const _displayNextItem = (
|
||||
results,
|
||||
resultCount,
|
||||
searchTerms
|
||||
) => {
|
||||
// results left, load the summary and display it
|
||||
// this is intended to be dynamic (don't sub resultsCount)
|
||||
if (results.length) {
|
||||
_displayItem(results.pop(), searchTerms);
|
||||
setTimeout(
|
||||
() => _displayNextItem(results, resultCount, searchTerms),
|
||||
5
|
||||
);
|
||||
}
|
||||
// search finished, update title and status message
|
||||
else _finishSearch(resultCount);
|
||||
};
|
||||
|
||||
/**
|
||||
* Default splitQuery function. Can be overridden in ``sphinx.search`` with a
|
||||
* custom function per language.
|
||||
*
|
||||
* The regular expression works by splitting the string on consecutive characters
|
||||
* that are not Unicode letters, numbers, underscores, or emoji characters.
|
||||
* This is the same as ``\W+`` in Python, preserving the surrogate pair area.
|
||||
*/
|
||||
if (typeof splitQuery === "undefined") {
|
||||
var splitQuery = (query) => query
|
||||
.split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu)
|
||||
.filter(term => term) // remove remaining empty strings
|
||||
}
|
||||
|
||||
/**
|
||||
* Search Module
|
||||
*/
|
||||
const Search = {
|
||||
_index: null,
|
||||
_queued_query: null,
|
||||
_pulse_status: -1,
|
||||
var Search = {
|
||||
|
||||
htmlToText: (htmlString) => {
|
||||
const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html');
|
||||
htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() });
|
||||
const docContent = htmlElement.querySelector('[role="main"]');
|
||||
if (docContent !== undefined) return docContent.textContent;
|
||||
console.warn(
|
||||
"Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template."
|
||||
);
|
||||
return "";
|
||||
_index : null,
|
||||
_queued_query : null,
|
||||
_pulse_status : -1,
|
||||
|
||||
init : function() {
|
||||
var params = $.getQueryParameters();
|
||||
if (params.q) {
|
||||
var query = params.q[0];
|
||||
$('input[name="q"]')[0].value = query;
|
||||
this.performSearch(query);
|
||||
}
|
||||
},
|
||||
|
||||
init: () => {
|
||||
const query = new URLSearchParams(window.location.search).get("q");
|
||||
document
|
||||
.querySelectorAll('input[name="q"]')
|
||||
.forEach((el) => (el.value = query));
|
||||
if (query) Search.performSearch(query);
|
||||
loadIndex : function(url) {
|
||||
$.ajax({type: "GET", url: url, data: null,
|
||||
dataType: "script", cache: true,
|
||||
complete: function(jqxhr, textstatus) {
|
||||
if (textstatus != "success") {
|
||||
document.getElementById("searchindexloader").src = url;
|
||||
}
|
||||
}});
|
||||
},
|
||||
|
||||
loadIndex: (url) =>
|
||||
(document.body.appendChild(document.createElement("script")).src = url),
|
||||
|
||||
setIndex: (index) => {
|
||||
Search._index = index;
|
||||
if (Search._queued_query !== null) {
|
||||
const query = Search._queued_query;
|
||||
Search._queued_query = null;
|
||||
Search.query(query);
|
||||
setIndex : function(index) {
|
||||
var q;
|
||||
this._index = index;
|
||||
if ((q = this._queued_query) !== null) {
|
||||
this._queued_query = null;
|
||||
Search.query(q);
|
||||
}
|
||||
},
|
||||
|
||||
hasIndex: () => Search._index !== null,
|
||||
hasIndex : function() {
|
||||
return this._index !== null;
|
||||
},
|
||||
|
||||
deferQuery: (query) => (Search._queued_query = query),
|
||||
deferQuery : function(query) {
|
||||
this._queued_query = query;
|
||||
},
|
||||
|
||||
stopPulse: () => (Search._pulse_status = -1),
|
||||
stopPulse : function() {
|
||||
this._pulse_status = 0;
|
||||
},
|
||||
|
||||
startPulse: () => {
|
||||
if (Search._pulse_status >= 0) return;
|
||||
|
||||
const pulse = () => {
|
||||
startPulse : function() {
|
||||
if (this._pulse_status >= 0)
|
||||
return;
|
||||
function pulse() {
|
||||
var i;
|
||||
Search._pulse_status = (Search._pulse_status + 1) % 4;
|
||||
Search.dots.innerText = ".".repeat(Search._pulse_status);
|
||||
if (Search._pulse_status >= 0) window.setTimeout(pulse, 500);
|
||||
};
|
||||
var dotString = '';
|
||||
for (i = 0; i < Search._pulse_status; i++)
|
||||
dotString += '.';
|
||||
Search.dots.text(dotString);
|
||||
if (Search._pulse_status > -1)
|
||||
window.setTimeout(pulse, 500);
|
||||
}
|
||||
pulse();
|
||||
},
|
||||
|
||||
/**
|
||||
* perform a search for something (or wait until index is loaded)
|
||||
*/
|
||||
performSearch: (query) => {
|
||||
performSearch : function(query) {
|
||||
// create the required interface elements
|
||||
const searchText = document.createElement("h2");
|
||||
searchText.textContent = _("Searching");
|
||||
const searchSummary = document.createElement("p");
|
||||
searchSummary.classList.add("search-summary");
|
||||
searchSummary.innerText = "";
|
||||
const searchList = document.createElement("ul");
|
||||
searchList.classList.add("search");
|
||||
this.out = $('#search-results');
|
||||
this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
|
||||
this.dots = $('<span></span>').appendTo(this.title);
|
||||
this.status = $('<p style="display: none"></p>').appendTo(this.out);
|
||||
this.output = $('<ul class="search"/>').appendTo(this.out);
|
||||
|
||||
const out = document.getElementById("search-results");
|
||||
Search.title = out.appendChild(searchText);
|
||||
Search.dots = Search.title.appendChild(document.createElement("span"));
|
||||
Search.status = out.appendChild(searchSummary);
|
||||
Search.output = out.appendChild(searchList);
|
||||
|
||||
const searchProgress = document.getElementById("search-progress");
|
||||
// Some themes don't use the search progress node
|
||||
if (searchProgress) {
|
||||
searchProgress.innerText = _("Preparing search...");
|
||||
}
|
||||
Search.startPulse();
|
||||
$('#search-progress').text(_('Preparing search...'));
|
||||
this.startPulse();
|
||||
|
||||
// index already loaded, the browser was quick!
|
||||
if (Search.hasIndex()) Search.query(query);
|
||||
else Search.deferQuery(query);
|
||||
if (this.hasIndex())
|
||||
this.query(query);
|
||||
else
|
||||
this.deferQuery(query);
|
||||
},
|
||||
|
||||
/**
|
||||
* execute search (requires search index to be loaded)
|
||||
*/
|
||||
query: (query) => {
|
||||
const filenames = Search._index.filenames;
|
||||
const docNames = Search._index.docnames;
|
||||
const titles = Search._index.titles;
|
||||
const allTitles = Search._index.alltitles;
|
||||
const indexEntries = Search._index.indexentries;
|
||||
query : function(query) {
|
||||
var i;
|
||||
|
||||
// stem the search terms and add them to the correct list
|
||||
const stemmer = new Stemmer();
|
||||
const searchTerms = new Set();
|
||||
const excludedTerms = new Set();
|
||||
const highlightTerms = new Set();
|
||||
const objectTerms = new Set(splitQuery(query.toLowerCase().trim()));
|
||||
splitQuery(query.trim()).forEach((queryTerm) => {
|
||||
const queryTermLower = queryTerm.toLowerCase();
|
||||
|
||||
// maybe skip this "word"
|
||||
// stopwords array is from language_data.js
|
||||
if (
|
||||
stopwords.indexOf(queryTermLower) !== -1 ||
|
||||
queryTerm.match(/^\d+$/)
|
||||
)
|
||||
return;
|
||||
// stem the searchterms and add them to the correct list
|
||||
var stemmer = new Stemmer();
|
||||
var searchterms = [];
|
||||
var excluded = [];
|
||||
var hlterms = [];
|
||||
var tmp = splitQuery(query);
|
||||
var objectterms = [];
|
||||
for (i = 0; i < tmp.length; i++) {
|
||||
if (tmp[i] !== "") {
|
||||
objectterms.push(tmp[i].toLowerCase());
|
||||
}
|
||||
|
||||
if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i].match(/^\d+$/) ||
|
||||
tmp[i] === "") {
|
||||
// skip this "word"
|
||||
continue;
|
||||
}
|
||||
// stem the word
|
||||
let word = stemmer.stemWord(queryTermLower);
|
||||
var word = stemmer.stemWord(tmp[i].toLowerCase());
|
||||
// prevent stemmer from cutting word smaller than two chars
|
||||
if(word.length < 3 && tmp[i].length >= 3) {
|
||||
word = tmp[i];
|
||||
}
|
||||
var toAppend;
|
||||
// select the correct list
|
||||
if (word[0] === "-") excludedTerms.add(word.substr(1));
|
||||
if (word[0] == '-') {
|
||||
toAppend = excluded;
|
||||
word = word.substr(1);
|
||||
}
|
||||
else {
|
||||
searchTerms.add(word);
|
||||
highlightTerms.add(queryTermLower);
|
||||
toAppend = searchterms;
|
||||
hlterms.push(tmp[i].toLowerCase());
|
||||
}
|
||||
});
|
||||
|
||||
if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js
|
||||
localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" "))
|
||||
// only add if not already in the list
|
||||
if (!$u.contains(toAppend, word))
|
||||
toAppend.push(word);
|
||||
}
|
||||
var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
|
||||
|
||||
// console.debug("SEARCH: searching for:");
|
||||
// console.info("required: ", [...searchTerms]);
|
||||
// console.info("excluded: ", [...excludedTerms]);
|
||||
// console.debug('SEARCH: searching for:');
|
||||
// console.info('required: ', searchterms);
|
||||
// console.info('excluded: ', excluded);
|
||||
|
||||
// array of [docname, title, anchor, descr, score, filename]
|
||||
let results = [];
|
||||
_removeChildren(document.getElementById("search-progress"));
|
||||
// prepare search
|
||||
var terms = this._index.terms;
|
||||
var titleterms = this._index.titleterms;
|
||||
|
||||
const queryLower = query.toLowerCase();
|
||||
for (const [title, foundTitles] of Object.entries(allTitles)) {
|
||||
if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) {
|
||||
for (const [file, id] of foundTitles) {
|
||||
let score = Math.round(100 * queryLower.length / title.length)
|
||||
results.push([
|
||||
docNames[file],
|
||||
titles[file] !== title ? `${titles[file]} > ${title}` : title,
|
||||
id !== null ? "#" + id : "",
|
||||
null,
|
||||
score,
|
||||
filenames[file],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// search for explicit entries in index directives
|
||||
for (const [entry, foundEntries] of Object.entries(indexEntries)) {
|
||||
if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) {
|
||||
for (const [file, id] of foundEntries) {
|
||||
let score = Math.round(100 * queryLower.length / entry.length)
|
||||
results.push([
|
||||
docNames[file],
|
||||
titles[file],
|
||||
id ? "#" + id : "",
|
||||
null,
|
||||
score,
|
||||
filenames[file],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// array of [filename, title, anchor, descr, score]
|
||||
var results = [];
|
||||
$('#search-progress').empty();
|
||||
|
||||
// lookup as object
|
||||
objectTerms.forEach((term) =>
|
||||
results.push(...Search.performObjectSearch(term, objectTerms))
|
||||
);
|
||||
for (i = 0; i < objectterms.length; i++) {
|
||||
var others = [].concat(objectterms.slice(0, i),
|
||||
objectterms.slice(i+1, objectterms.length));
|
||||
results = results.concat(this.performObjectSearch(objectterms[i], others));
|
||||
}
|
||||
|
||||
// lookup as search terms in fulltext
|
||||
results.push(...Search.performTermsSearch(searchTerms, excludedTerms));
|
||||
results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms));
|
||||
|
||||
// let the scorer override scores with a custom scoring function
|
||||
if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item)));
|
||||
if (Scorer.score) {
|
||||
for (i = 0; i < results.length; i++)
|
||||
results[i][4] = Scorer.score(results[i]);
|
||||
}
|
||||
|
||||
// now sort the results by score (in opposite order of appearance, since the
|
||||
// display function below uses pop() to retrieve items) and then
|
||||
// alphabetically
|
||||
results.sort((a, b) => {
|
||||
const leftScore = a[4];
|
||||
const rightScore = b[4];
|
||||
if (leftScore === rightScore) {
|
||||
results.sort(function(a, b) {
|
||||
var left = a[4];
|
||||
var right = b[4];
|
||||
if (left > right) {
|
||||
return 1;
|
||||
} else if (left < right) {
|
||||
return -1;
|
||||
} else {
|
||||
// same score: sort alphabetically
|
||||
const leftTitle = a[1].toLowerCase();
|
||||
const rightTitle = b[1].toLowerCase();
|
||||
if (leftTitle === rightTitle) return 0;
|
||||
return leftTitle > rightTitle ? -1 : 1; // inverted is intentional
|
||||
left = a[1].toLowerCase();
|
||||
right = b[1].toLowerCase();
|
||||
return (left > right) ? -1 : ((left < right) ? 1 : 0);
|
||||
}
|
||||
return leftScore > rightScore ? 1 : -1;
|
||||
});
|
||||
|
||||
// remove duplicate search results
|
||||
// note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept
|
||||
let seen = new Set();
|
||||
results = results.reverse().reduce((acc, result) => {
|
||||
let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(',');
|
||||
if (!seen.has(resultStr)) {
|
||||
acc.push(result);
|
||||
seen.add(resultStr);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
results = results.reverse();
|
||||
|
||||
// for debugging
|
||||
//Search.lastresults = results.slice(); // a copy
|
||||
// console.info("search results:", Search.lastresults);
|
||||
//console.info('search results:', Search.lastresults);
|
||||
|
||||
// print the results
|
||||
_displayNextItem(results, results.length, searchTerms);
|
||||
var resultCount = results.length;
|
||||
function displayNextItem() {
|
||||
// results left, load the summary and display it
|
||||
if (results.length) {
|
||||
var item = results.pop();
|
||||
var listItem = $('<li style="display:none"></li>');
|
||||
if (DOCUMENTATION_OPTIONS.FILE_SUFFIX === '') {
|
||||
// dirhtml builder
|
||||
var dirname = item[0] + '/';
|
||||
if (dirname.match(/\/index\/$/)) {
|
||||
dirname = dirname.substring(0, dirname.length-6);
|
||||
} else if (dirname == 'index/') {
|
||||
dirname = '';
|
||||
}
|
||||
listItem.append($('<a/>').attr('href',
|
||||
DOCUMENTATION_OPTIONS.URL_ROOT + dirname +
|
||||
highlightstring + item[2]).html(item[1]));
|
||||
} else {
|
||||
// normal html builders
|
||||
listItem.append($('<a/>').attr('href',
|
||||
item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
|
||||
highlightstring + item[2]).html(item[1]));
|
||||
}
|
||||
if (item[3]) {
|
||||
listItem.append($('<span> (' + item[3] + ')</span>'));
|
||||
Search.output.append(listItem);
|
||||
listItem.slideDown(5, function() {
|
||||
displayNextItem();
|
||||
});
|
||||
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
|
||||
var suffix = DOCUMENTATION_OPTIONS.SOURCELINK_SUFFIX;
|
||||
if (suffix === undefined) {
|
||||
suffix = '.txt';
|
||||
}
|
||||
$.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[5] + (item[5].slice(-suffix.length) === suffix ? '' : suffix),
|
||||
dataType: "text",
|
||||
complete: function(jqxhr, textstatus) {
|
||||
var data = jqxhr.responseText;
|
||||
if (data !== '' && data !== undefined) {
|
||||
listItem.append(Search.makeSearchSummary(data, searchterms, hlterms));
|
||||
}
|
||||
Search.output.append(listItem);
|
||||
listItem.slideDown(5, function() {
|
||||
displayNextItem();
|
||||
});
|
||||
}});
|
||||
} else {
|
||||
// no source available, just display title
|
||||
Search.output.append(listItem);
|
||||
listItem.slideDown(5, function() {
|
||||
displayNextItem();
|
||||
});
|
||||
}
|
||||
}
|
||||
// search finished, update title and status message
|
||||
else {
|
||||
Search.stopPulse();
|
||||
Search.title.text(_('Search Results'));
|
||||
if (!resultCount)
|
||||
Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
|
||||
else
|
||||
Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
|
||||
Search.status.fadeIn(500);
|
||||
}
|
||||
}
|
||||
displayNextItem();
|
||||
},
|
||||
|
||||
/**
|
||||
* search for object names
|
||||
*/
|
||||
performObjectSearch: (object, objectTerms) => {
|
||||
const filenames = Search._index.filenames;
|
||||
const docNames = Search._index.docnames;
|
||||
const objects = Search._index.objects;
|
||||
const objNames = Search._index.objnames;
|
||||
const titles = Search._index.titles;
|
||||
performObjectSearch : function(object, otherterms) {
|
||||
var filenames = this._index.filenames;
|
||||
var docnames = this._index.docnames;
|
||||
var objects = this._index.objects;
|
||||
var objnames = this._index.objnames;
|
||||
var titles = this._index.titles;
|
||||
|
||||
const results = [];
|
||||
var i;
|
||||
var results = [];
|
||||
|
||||
const objectSearchCallback = (prefix, match) => {
|
||||
const name = match[4]
|
||||
const fullname = (prefix ? prefix + "." : "") + name;
|
||||
const fullnameLower = fullname.toLowerCase();
|
||||
if (fullnameLower.indexOf(object) < 0) return;
|
||||
for (var prefix in objects) {
|
||||
for (var name in objects[prefix]) {
|
||||
var fullname = (prefix ? prefix + '.' : '') + name;
|
||||
if (fullname.toLowerCase().indexOf(object) > -1) {
|
||||
var score = 0;
|
||||
var parts = fullname.split('.');
|
||||
// check for different match types: exact matches of full name or
|
||||
// "last name" (i.e. last dotted part)
|
||||
if (fullname == object || parts[parts.length - 1] == object) {
|
||||
score += Scorer.objNameMatch;
|
||||
// matches in last name
|
||||
} else if (parts[parts.length - 1].indexOf(object) > -1) {
|
||||
score += Scorer.objPartialMatch;
|
||||
}
|
||||
var match = objects[prefix][name];
|
||||
var objname = objnames[match[1]][2];
|
||||
var title = titles[match[0]];
|
||||
// If more than one term searched for, we require other words to be
|
||||
// found in the name/title/description
|
||||
if (otherterms.length > 0) {
|
||||
var haystack = (prefix + ' ' + name + ' ' +
|
||||
objname + ' ' + title).toLowerCase();
|
||||
var allfound = true;
|
||||
for (i = 0; i < otherterms.length; i++) {
|
||||
if (haystack.indexOf(otherterms[i]) == -1) {
|
||||
allfound = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!allfound) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
var descr = objname + _(', in ') + title;
|
||||
|
||||
let score = 0;
|
||||
const parts = fullnameLower.split(".");
|
||||
|
||||
// check for different match types: exact matches of full name or
|
||||
// "last name" (i.e. last dotted part)
|
||||
if (fullnameLower === object || parts.slice(-1)[0] === object)
|
||||
score += Scorer.objNameMatch;
|
||||
else if (parts.slice(-1)[0].indexOf(object) > -1)
|
||||
score += Scorer.objPartialMatch; // matches in last name
|
||||
|
||||
const objName = objNames[match[1]][2];
|
||||
const title = titles[match[0]];
|
||||
|
||||
// If more than one term searched for, we require other words to be
|
||||
// found in the name/title/description
|
||||
const otherTerms = new Set(objectTerms);
|
||||
otherTerms.delete(object);
|
||||
if (otherTerms.size > 0) {
|
||||
const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase();
|
||||
if (
|
||||
[...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0)
|
||||
)
|
||||
return;
|
||||
var anchor = match[3];
|
||||
if (anchor === '')
|
||||
anchor = fullname;
|
||||
else if (anchor == '-')
|
||||
anchor = objnames[match[1]][1] + '-' + fullname;
|
||||
// add custom score for some objects according to scorer
|
||||
if (Scorer.objPrio.hasOwnProperty(match[2])) {
|
||||
score += Scorer.objPrio[match[2]];
|
||||
} else {
|
||||
score += Scorer.objPrioDefault;
|
||||
}
|
||||
results.push([docnames[match[0]], fullname, '#'+anchor, descr, score, filenames[match[0]]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let anchor = match[3];
|
||||
if (anchor === "") anchor = fullname;
|
||||
else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname;
|
||||
|
||||
const descr = objName + _(", in ") + title;
|
||||
|
||||
// add custom score for some objects according to scorer
|
||||
if (Scorer.objPrio.hasOwnProperty(match[2]))
|
||||
score += Scorer.objPrio[match[2]];
|
||||
else score += Scorer.objPrioDefault;
|
||||
|
||||
results.push([
|
||||
docNames[match[0]],
|
||||
fullname,
|
||||
"#" + anchor,
|
||||
descr,
|
||||
score,
|
||||
filenames[match[0]],
|
||||
]);
|
||||
};
|
||||
Object.keys(objects).forEach((prefix) =>
|
||||
objects[prefix].forEach((array) =>
|
||||
objectSearchCallback(prefix, array)
|
||||
)
|
||||
);
|
||||
return results;
|
||||
},
|
||||
|
||||
/**
|
||||
* search for full-text terms in the index
|
||||
*/
|
||||
performTermsSearch: (searchTerms, excludedTerms) => {
|
||||
// prepare search
|
||||
const terms = Search._index.terms;
|
||||
const titleTerms = Search._index.titleterms;
|
||||
const filenames = Search._index.filenames;
|
||||
const docNames = Search._index.docnames;
|
||||
const titles = Search._index.titles;
|
||||
performTermsSearch : function(searchterms, excluded, terms, titleterms) {
|
||||
var docnames = this._index.docnames;
|
||||
var filenames = this._index.filenames;
|
||||
var titles = this._index.titles;
|
||||
|
||||
const scoreMap = new Map();
|
||||
const fileMap = new Map();
|
||||
var i, j, file;
|
||||
var fileMap = {};
|
||||
var scoreMap = {};
|
||||
var results = [];
|
||||
|
||||
// perform the search on the required terms
|
||||
searchTerms.forEach((word) => {
|
||||
const files = [];
|
||||
const arr = [
|
||||
{ files: terms[word], score: Scorer.term },
|
||||
{ files: titleTerms[word], score: Scorer.title },
|
||||
for (i = 0; i < searchterms.length; i++) {
|
||||
var word = searchterms[i];
|
||||
var files = [];
|
||||
var _o = [
|
||||
{files: terms[word], score: Scorer.term},
|
||||
{files: titleterms[word], score: Scorer.title}
|
||||
];
|
||||
// add support for partial matches
|
||||
if (word.length > 2) {
|
||||
const escapedWord = _escapeRegExp(word);
|
||||
Object.keys(terms).forEach((term) => {
|
||||
if (term.match(escapedWord) && !terms[word])
|
||||
arr.push({ files: terms[term], score: Scorer.partialTerm });
|
||||
});
|
||||
Object.keys(titleTerms).forEach((term) => {
|
||||
if (term.match(escapedWord) && !titleTerms[word])
|
||||
arr.push({ files: titleTerms[word], score: Scorer.partialTitle });
|
||||
});
|
||||
}
|
||||
|
||||
// no match but word was a required one
|
||||
if (arr.every((record) => record.files === undefined)) return;
|
||||
|
||||
if ($u.every(_o, function(o){return o.files === undefined;})) {
|
||||
break;
|
||||
}
|
||||
// found search word in contents
|
||||
arr.forEach((record) => {
|
||||
if (record.files === undefined) return;
|
||||
$u.each(_o, function(o) {
|
||||
var _files = o.files;
|
||||
if (_files === undefined)
|
||||
return
|
||||
|
||||
let recordFiles = record.files;
|
||||
if (recordFiles.length === undefined) recordFiles = [recordFiles];
|
||||
files.push(...recordFiles);
|
||||
if (_files.length === undefined)
|
||||
_files = [_files];
|
||||
files = files.concat(_files);
|
||||
|
||||
// set score for the word in each file
|
||||
recordFiles.forEach((file) => {
|
||||
if (!scoreMap.has(file)) scoreMap.set(file, {});
|
||||
scoreMap.get(file)[word] = record.score;
|
||||
});
|
||||
// set score for the word in each file to Scorer.term
|
||||
for (j = 0; j < _files.length; j++) {
|
||||
file = _files[j];
|
||||
if (!(file in scoreMap))
|
||||
scoreMap[file] = {}
|
||||
scoreMap[file][word] = o.score;
|
||||
}
|
||||
});
|
||||
|
||||
// create the mapping
|
||||
files.forEach((file) => {
|
||||
if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1)
|
||||
fileMap.get(file).push(word);
|
||||
else fileMap.set(file, [word]);
|
||||
});
|
||||
});
|
||||
for (j = 0; j < files.length; j++) {
|
||||
file = files[j];
|
||||
if (file in fileMap)
|
||||
fileMap[file].push(word);
|
||||
else
|
||||
fileMap[file] = [word];
|
||||
}
|
||||
}
|
||||
|
||||
// now check if the files don't contain excluded terms
|
||||
const results = [];
|
||||
for (const [file, wordList] of fileMap) {
|
||||
// check if all requirements are matched
|
||||
for (file in fileMap) {
|
||||
var valid = true;
|
||||
|
||||
// as search terms with length < 3 are discarded
|
||||
const filteredTermCount = [...searchTerms].filter(
|
||||
(term) => term.length > 2
|
||||
).length;
|
||||
if (
|
||||
wordList.length !== searchTerms.size &&
|
||||
wordList.length !== filteredTermCount
|
||||
)
|
||||
continue;
|
||||
// check if all requirements are matched
|
||||
if (fileMap[file].length != searchterms.length)
|
||||
continue;
|
||||
|
||||
// ensure that none of the excluded terms is in the search result
|
||||
if (
|
||||
[...excludedTerms].some(
|
||||
(term) =>
|
||||
terms[term] === file ||
|
||||
titleTerms[term] === file ||
|
||||
(terms[term] || []).includes(file) ||
|
||||
(titleTerms[term] || []).includes(file)
|
||||
)
|
||||
)
|
||||
break;
|
||||
for (i = 0; i < excluded.length; i++) {
|
||||
if (terms[excluded[i]] == file ||
|
||||
titleterms[excluded[i]] == file ||
|
||||
$u.contains(terms[excluded[i]] || [], file) ||
|
||||
$u.contains(titleterms[excluded[i]] || [], file)) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// select one (max) score for the file.
|
||||
const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w]));
|
||||
// add result to the result list
|
||||
results.push([
|
||||
docNames[file],
|
||||
titles[file],
|
||||
"",
|
||||
null,
|
||||
score,
|
||||
filenames[file],
|
||||
]);
|
||||
// if we have still a valid result we can add it to the result list
|
||||
if (valid) {
|
||||
// select one (max) score for the file.
|
||||
// for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
|
||||
var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
|
||||
results.push([docnames[file], titles[file], '', null, score, filenames[file]]);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
},
|
||||
|
@ -539,28 +452,30 @@ const Search = {
|
|||
/**
|
||||
* helper function to return a node containing the
|
||||
* search summary for a given text. keywords is a list
|
||||
* of stemmed words.
|
||||
* of stemmed words, hlwords is the list of normal, unstemmed
|
||||
* words. the first one is used to find the occurrence, the
|
||||
* latter for highlighting it.
|
||||
*/
|
||||
makeSearchSummary: (htmlText, keywords) => {
|
||||
const text = Search.htmlToText(htmlText);
|
||||
if (text === "") return null;
|
||||
|
||||
const textLower = text.toLowerCase();
|
||||
const actualStartPosition = [...keywords]
|
||||
.map((k) => textLower.indexOf(k.toLowerCase()))
|
||||
.filter((i) => i > -1)
|
||||
.slice(-1)[0];
|
||||
const startWithContext = Math.max(actualStartPosition - 120, 0);
|
||||
|
||||
const top = startWithContext === 0 ? "" : "...";
|
||||
const tail = startWithContext + 240 < text.length ? "..." : "";
|
||||
|
||||
let summary = document.createElement("p");
|
||||
summary.classList.add("context");
|
||||
summary.textContent = top + text.substr(startWithContext, 240).trim() + tail;
|
||||
|
||||
return summary;
|
||||
},
|
||||
makeSearchSummary : function(text, keywords, hlwords) {
|
||||
var textLower = text.toLowerCase();
|
||||
var start = 0;
|
||||
$.each(keywords, function() {
|
||||
var i = textLower.indexOf(this.toLowerCase());
|
||||
if (i > -1)
|
||||
start = i;
|
||||
});
|
||||
start = Math.max(start - 120, 0);
|
||||
var excerpt = ((start > 0) ? '...' : '') +
|
||||
$.trim(text.substr(start, 240)) +
|
||||
((start + 240 - text.length) ? '...' : '');
|
||||
var rv = $('<div class="context"></div>').text(excerpt);
|
||||
$.each(hlwords, function() {
|
||||
rv = rv.highlightText(this, 'highlighted');
|
||||
});
|
||||
return rv;
|
||||
}
|
||||
};
|
||||
|
||||
_ready(Search.init);
|
||||
$(document).ready(function() {
|
||||
Search.init();
|
||||
});
|
||||
|
|