├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ └── docs.yml ├── .gitignore ├── Docs~ ├── Doxyfile ├── Icon.png ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── apple-touch-icon.png ├── doxygen-awesome-css │ ├── .github │ │ └── workflows │ │ │ └── publish.yaml │ ├── .gitignore │ ├── Doxyfile │ ├── LICENSE │ ├── README.md │ ├── docs │ │ ├── customization.md │ │ ├── extensions.md │ │ ├── img │ │ │ ├── darkmode_toggle.png │ │ │ ├── fancy_scrollbars_firefox.png │ │ │ ├── fancy_scrollbars_webkit.gif │ │ │ ├── fragment_copy_button.png │ │ │ └── paragraph_link.png │ │ └── tricks.md │ ├── doxygen-awesome-darkmode-toggle.js │ ├── doxygen-awesome-fragment-copy-button.js │ ├── doxygen-awesome-paragraph-link.js │ ├── doxygen-awesome-sidebar-only-darkmode-toggle.css │ ├── doxygen-awesome-sidebar-only.css │ ├── doxygen-awesome.css │ ├── doxygen-custom │ │ ├── custom-alternative.css │ │ ├── custom.css │ │ ├── header.html │ │ └── toggle-alternative-theme.js │ ├── img │ │ ├── screenshot.png │ │ └── theme-variants.drawio.svg │ ├── include │ │ └── MyLibrary │ │ │ ├── example.hpp │ │ │ └── subclass-example.hpp │ └── logo.drawio.svg ├── favicon-16x16.png ├── favicon-32x32.png ├── favicon.ico ├── header.html └── site.webmanifest ├── LICENSE ├── LICENSE.meta ├── README.md ├── README.md.meta ├── Samples~ ├── Prefabs.meta ├── Prefabs │ ├── HexButton_Horizontal.prefab │ ├── HexButton_Horizontal.prefab.meta │ ├── HexButton_Vertical.prefab │ └── HexButton_Vertical.prefab.meta ├── Scenes.meta ├── Scenes │ ├── HexLayoutGroupExample.unity │ └── HexLayoutGroupExample.unity.meta ├── Sprites.meta └── Sprites │ ├── Hexagon_Horizontal.png │ ├── Hexagon_Horizontal.png.meta │ ├── Hexagon_Vertical.png │ └── Hexagon_Vertical.png.meta ├── Scripts.meta ├── Scripts ├── Editor.meta ├── Editor │ ├── HexLayoutGroupEditor.cs │ ├── HexLayoutGroupEditor.cs.meta │ ├── MPewsey.HexagonalUI.Editor.asmdef │ └── MPewsey.HexagonalUI.Editor.asmdef.meta ├── Runtime.meta └── Runtime │ ├── HexButton.cs │ ├── HexButton.cs.meta │ ├── HexLayoutGroup.cs │ ├── HexLayoutGroup.cs.meta │ ├── MPewsey.HexagonalUI.asmdef │ └── MPewsey.HexagonalUI.asmdef.meta ├── package.json └── package.json.meta /.gitattributes: -------------------------------------------------------------------------------- 1 | Docs~/** linguist-documentation 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Docs 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-20.04 11 | concurrency: 12 | group: ${{ github.workflow }}-${{ github.ref }} 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - uses: mpewsey/doxygen-action@v1.9.2 17 | with: 18 | working-directory: 'Docs~/' 19 | doxyfile-path: 'Doxyfile' 20 | 21 | - name: Deploy 22 | uses: mpewsey/actions-gh-pages@v3 23 | if: ${{ github.ref == 'refs/heads/main' }} 24 | with: 25 | github_token: ${{ secrets.GITHUB_TOKEN }} 26 | publish_dir: ./Docs~/output/html 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This .gitignore file should be placed at the root of your Unity project directory 2 | # 3 | # Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore 4 | # 5 | /[Ll]ibrary/ 6 | /[Tt]emp/ 7 | /[Oo]bj/ 8 | /[Bb]uild/ 9 | /[Bb]uilds/ 10 | /[Ll]ogs/ 11 | /[Mm]emoryCaptures/ 12 | /[Dd]ocs~/[Oo]utput/ 13 | 14 | .DS_Store 15 | 16 | # Asset meta data should only be ignored when the corresponding asset is also ignored 17 | !/[Aa]ssets/**/*.meta 18 | 19 | # Uncomment this line if you wish to ignore the asset store tools plugin 20 | # /[Aa]ssets/AssetStoreTools* 21 | 22 | # Autogenerated Jetbrains Rider plugin 23 | [Aa]ssets/Plugins/Editor/JetBrains* 24 | 25 | # Visual Studio cache directory 26 | .vs/ 27 | 28 | # Gradle cache directory 29 | .gradle/ 30 | 31 | # Autogenerated VS/MD/Consulo solution and project files 32 | ExportedObj/ 33 | .consulo/ 34 | *.csproj 35 | *.unityproj 36 | *.sln 37 | *.suo 38 | *.tmp 39 | *.user 40 | *.userprefs 41 | *.pidb 42 | *.booproj 43 | *.svd 44 | *.pdb 45 | *.mdb 46 | *.opendb 47 | *.VC.db 48 | 49 | # Unity3D generated meta files 50 | *.pidb.meta 51 | *.pdb.meta 52 | *.mdb.meta 53 | 54 | # Unity3D generated file on crash reports 55 | sysinfo.txt 56 | 57 | # Builds 58 | *.apk 59 | *.unitypackage 60 | 61 | # Crashlytics generated file 62 | crashlytics-build.properties 63 | 64 | -------------------------------------------------------------------------------- /Docs~/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpewsey/HexagonalUI/c99404ac0f23f91a6d2cd582c3e722f9e9eefb95/Docs~/Icon.png -------------------------------------------------------------------------------- /Docs~/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpewsey/HexagonalUI/c99404ac0f23f91a6d2cd582c3e722f9e9eefb95/Docs~/android-chrome-192x192.png -------------------------------------------------------------------------------- /Docs~/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpewsey/HexagonalUI/c99404ac0f23f91a6d2cd582c3e722f9e9eefb95/Docs~/android-chrome-512x512.png -------------------------------------------------------------------------------- /Docs~/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpewsey/HexagonalUI/c99404ac0f23f91a6d2cd582c3e722f9e9eefb95/Docs~/apple-touch-icon.png -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/.github/workflows/publish.yaml: -------------------------------------------------------------------------------- 1 | name: publish 2 | on: 3 | release: 4 | types: [published] 5 | jobs: 6 | deploy: 7 | runs-on: ubuntu-20.04 8 | steps: 9 | - name: Checkout repository 10 | uses: actions/checkout@v2 11 | with: 12 | fetch-depth: 0 13 | - name: install Doxygen 1.9.2 14 | run: | 15 | sudo apt-get update 16 | sudo apt-get install -y graphviz libclang-cpp1-9 libclang1-9 17 | wget https://www.doxygen.nl/files/doxygen-1.9.2.linux.bin.tar.gz 18 | tar -xvzf doxygen-1.9.2.linux.bin.tar.gz 19 | ln -s doxygen-1.9.2/bin/doxygen doxygen 20 | - name: set version 21 | run: echo "PROJECT_NUMBER = `git describe --tags`" >> Doxyfile 22 | - name: Generate Documentation 23 | run: ./doxygen Doxyfile 24 | - name: Publish generated content to GitHub Pages 25 | uses: tsunematsu21/actions-publish-gh-pages@v1.0.1 26 | with: 27 | dir: docs/html 28 | branch: gh-pages 29 | token: ${{ secrets.ACCESS_TOKEN }} -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/.gitignore: -------------------------------------------------------------------------------- 1 | docs/html 2 | .DS_Store 3 | .idea -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 jothepro 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/README.md: -------------------------------------------------------------------------------- 1 | # Doxygen Awesome 2 | 3 | [![GitHub release (latest by date)](https://img.shields.io/github/v/release/jothepro/doxygen-awesome-css)](https://github.com/jothepro/doxygen-awesome-css/releases/latest) 4 | [![GitHub](https://img.shields.io/github/license/jothepro/doxygen-awesome-css)](https://github.com/jothepro/doxygen-awesome-css/blob/main/LICENSE) 5 | ![GitHub Repo stars](https://img.shields.io/github/stars/jothepro/doxygen-awesome-css) 6 | 7 |
8 | 9 | ![Screenshot of Doxygen Awesome CSS](img/screenshot.png) 10 | 11 |
12 | 13 | **Doxygen Awesome** is a custom **CSS theme for Doxygen HTML-documentation** with lots of customization parameters. 14 | 15 | ## Motivation 16 | 17 | I really like how the Doxygen HTML-documentation is structured! But IMHO it looks a bit outdated. 18 | 19 | This theme is an attemt to update the visuals of Doxygen without changing it's overall layout too much. 20 | 21 | ## Features 22 | 23 | - 🌈 Clean, modern design 24 | - 🚀 Heavily customizable by adjusting CSS-variables 25 | - 🧩 No changes to the HTML structure of Doxygen required 26 | - 📱 Improved mobile usability 27 | - 🌘 Dark mode support! 28 | - 🥇 Works best with **doxygen 1.9.1** - **1.9.3** 29 | 30 | ## Examples 31 | 32 | - Sidebar-Only theme: [Documentation of this repository](https://jothepro.github.io/doxygen-awesome-css/) 33 | - Base theme: [libsl3](https://a4z.github.io/libsl3/) 34 | 35 | ## Installation 36 | 37 | Copy the file `doxygen-awesome.css` from this repository into your project or add this repository as submodule and check out the latest release: 38 | 39 | ```bash 40 | git submodule add https://github.com/jothepro/doxygen-awesome-css.git 41 | cd doxygen-awesome-css 42 | git checkout v2.0.2 43 | ``` 44 | 45 | Choose one of the theme variants and configure Doxygen accordingly: 46 | 47 | 48 | 49 | ![Available theme variants](img/theme-variants.drawio.svg) 50 | 51 | 52 | 53 | 1. **Base theme**: 54 | ``` 55 | # Doxyfile 56 | GENERATE_TREEVIEW = YES # optional. Also works without treeview 57 | HTML_EXTRA_STYLESHEET = doxygen-awesome-css/doxygen-awesome.css 58 | ``` 59 | 60 | 2. **Sidebar-only theme**: 61 | ``` 62 | # Doxyfile 63 | GENERATE_TREEVIEW = YES # required! 64 | HTML_EXTRA_STYLESHEET = doxygen-awesome-css/doxygen-awesome.css \ 65 | doxygen-awesome-css/doxygen-awesome-sidebar-only.css 66 | ``` 67 | 68 | Further installation instructions: 69 | 70 | - [How to install extensions](docs/extensions.md) 71 | - [How to customize the theme (colors, spacing, border-radius, ...)](docs/customization.md) 72 | - [Tips and Tricks for further configuration](docs/tricks.md) 73 | 74 | ## Browser support 75 | 76 | Tested with 77 | 78 | - Chrome 98, Chrome 98 for Android, Chrome 87 for iOS 79 | - Safari 15, Safari for iOS 15 80 | - Firefox 97, Firefox Daylight 97 for Android, Firefox Daylight 96 for iOS 81 | 82 | ## Credits 83 | 84 | - This theme is inspired by the [vuepress](https://vuepress.vuejs.org/) static site generator default theme. 85 | - Thank you for all the feedback on github! 86 | 87 | 88 | 89 | Read Next: [Extensions](docs/extensions.md) 90 | -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/docs/customization.md: -------------------------------------------------------------------------------- 1 | # Customization 2 | 3 | [TOC] 4 | 5 | 6 | ## CSS-Variables 7 | 8 | This theme is highly customizable because a lot of things are parameterized with CSS variables. 9 | 10 | Just to give you an idea on how flexible the styling is, click this button: 11 | 12 |
Alter theme
13 | 14 | ### Setup 15 | 16 | It is recommended to add your own `custom.css` and overwrite the variables there: 17 | ``` 18 | HTML_EXTRA_STYLESHEET = doxygen-awesome.css custom.css 19 | ``` 20 | 21 | Make sure to override the variables in the correct spot. All variables should be customized where they have been defined, in the `html` tag selector: 22 | 23 | ```css 24 | html { 25 | /* override light-mode variables here */ 26 | } 27 | ``` 28 | 29 | For dark-mode overrides you have to choose where to put them, depending on wether the dark-mode toggle extension is installed or not: 30 | 31 | - dark-mode toggle is installed: 32 | ```css 33 | html.dark-mode { 34 | /* define dark-mode variable overrides here if you DO use doxygen-awesome-darkmode-toggle.js */ 35 | } 36 | ``` 37 | - dark-mode toggle is **NOT** installed. The dark-mode is enabled automatically depending on the system preference: 38 | ```css 39 | @media (prefers-color-scheme: dark) { 40 | html:not(.light-mode) { 41 | /* define dark-mode variable overrides here if you DON'T use doxygen-awesome-darkmode-toggle.js */ 42 | } 43 | } 44 | ``` 45 | 46 | ### Available variables 47 | 48 | The following list gives an overview of the variables defined in [`doxygen-awesome.css`](https://github.com/jothepro/doxygen-awesome-css/blob/main/doxygen-awesome.css). 49 | 50 | The list is not complete. To explore all available variables, have a look at the CSS starting from [here](https://github.com/jothepro/doxygen-awesome-css/blob/main/doxygen-awesome.css#L30). 51 | All variables are defined at the beginning of the stylesheet. 52 | 53 | | Parameter | Default (Light) | Default (Dark) | 54 | | :-------------------------------- | :---------------------------------------------------------- | ----------------------------------------------------------- | 55 | | **Color Scheme**:
primary theme colors. This will affect the entire websites color scheme: links, arrows, labels, ... ||| 56 | | `--primary-color` | #1779c4 | #1982d2 | 57 | | `--primary-dark-color` | #335c80 | #5ca8e2 | 58 | | `--primary-light-color` | #70b1e9 | #4779ac | 59 | | **Page Colors**:
background and foreground (text-color) of the documentation. ||| 60 | | `--page-background-color` | white | #1C1D1F | 61 | | `--page-foreground-color` | #2f4153 | #d2dbde | 62 | | `--page-secondary-foreground-color`| #637485| #859399 | 63 | | **Spacing:**
default spacings. Most ui components reference these values for spacing, to provide uniform spacing on the page. ||| 64 | | `--spacing-small` | `5px` | | 65 | | `--spacing-medium` | `10px` | | 66 | | `--spacing-large` | `16px` | | 67 | | **Border Radius**:
border radius for all rounded ui components. Will affect many components, like dropdowns, memitems, codeblocks, ... ||| 68 | | `--border-radius-small` | `4px` | | 69 | | `--border-radius-medium` | `6px` | | 70 | | `--border-radius-large` | `8px` | | 71 | | **Content Width**:
The content is centered and constrained in its width. To make the content fill the whole page, set the following variable to `auto`. ||| 72 | | `--content-maxwidth` | `1000px` | | 73 | | **Code Fragment Colors**:
Color-Scheme of multiline codeblocks ||| 74 | | `--fragment-background` | #F8F9FA | #282c34 | 75 | | `--fragment-foreground` | #37474F | #dbe4eb | 76 | | **Arrow Opacity**:
By default the arrows in the sidebar are only visible on hover. You can override this behaviour so they are visible all the time. ||| 77 | | `--side-nav-arrow-opacity` | `0` | | 78 | | `--side-nav-arrow-hover-opacity` | `0.9` | | 79 | | ...and many more ||| 80 | 81 | 82 | If you miss a configuration option or find a bug, please consider [opening an issue](https://github.com/jothepro/doxygen-awesome-css/issues)! 83 | 84 | ## Doxygen generator 85 | 86 | The theme overrides most colors with the `--primary-color-*` variables. 87 | 88 | But there is a few small images and graphics that the theme cannot adjust or replace. To make these blend in better with 89 | the rest, it is recommended to adjust the [doxygen color settings](https://www.doxygen.nl/manual/customize.html#minor_tweaks_colors) 90 | to something that matches the chosen color-scheme. 91 | 92 | For the default color-scheme, these values work out quite well: 93 | 94 | ``` 95 | # Doxyfile 96 | HTML_COLORSTYLE_HUE = 209 97 | HTML_COLORSTYLE_SAT = 255 98 | HTML_COLORSTYLE_GAMMA = 113 99 | ``` 100 | 101 | ## Share your customizations 102 | 103 | If you customized the theme with custom colors, spacings, font-sizes, etc. and you want to share your creation with others, you can to this [here](https://github.com/jothepro/doxygen-awesome-css/discussions/13). 104 | 105 | I am always curious to learn about how you made the theme look even better! 106 | 107 | 108 | 109 | Read Next: [Tips & Tricks](tricks.md) 110 | -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/docs/extensions.md: -------------------------------------------------------------------------------- 1 | # Extensions 2 | 3 | [TOC] 4 | 5 | On top of the base theme provided by `doxygen-awesome.css`, this repository comes with Javascript extensions that require additional setup steps to get them running. 6 | 7 | The extensions require customizations in the header HTML-template. 8 | This is how you can create the default template with Doxygen: 9 | 10 | 1. Create default header template: 11 | ```sh 12 | doxygen -w html header.html delete_me.html delete_me.css 13 | ``` 14 | 15 | 2. Reference the template in your `Doxyfile`: 16 | ``` 17 | HTML_HEADER = header.html 18 | ``` 19 | 20 | [More details on header customization](https://www.doxygen.nl/manual/customize.html#minor_tweaks_header_css) 21 | 22 | ## Dark Mode Toggle 23 | 24 | Adds a button next to the search bar to enable and disable the dark theme variant manually. 25 | 26 | 27 | 28 | ### Installation 29 | 30 | 1. Add the required resources in your `Doxyfile`: 31 | - **HTML_EXTRA_FILES:** `doxygen-awesome-darkmode-toggle.js` 32 | - **HTML_EXTRA_STYLESHEET:** `doxygen-awesome-sidebar-only-darkmode-toggle.css` 33 | (ONLY required for the sidebar-only theme variant!) 34 | 2. In the `header.html` template, include `doxygen-awesome-darkmode-toggle.js` at the end of the `` and then initialize it: 35 | ```html 36 | 37 | 38 | 39 | 40 | 43 | 44 | 45 | ``` 46 | 3. The button can be customized to some extend: 47 | - Change the tooltip of the button: 48 | ```js 49 | DoxygenAwesomeDarkModeToggle.title = "Zwischen hellem/dunklem Modus wechseln" 50 | ``` 51 | - Change Icons. Both Emoji or SVG icons are supported: 52 | ```js 53 | DoxygenAwesomeDarkModeToggle.lightModeIcon = '🌞' 54 | // icon from https://fonts.google.com/icons 55 | DoxygenAwesomeDarkModeToggle.darkModeIcon = `` 56 | ``` 57 | 58 | All customizations must be applied before calling `DoxygenAwesomeDarkModeToggle.init()`! 59 | 60 | 61 | ## Fragment Copy Button 62 | 63 | ***This feature is experimental!*** 64 | 65 | Shows a copy button when the user hovers over a code fragment: 66 | 67 | 68 | 69 | ### Installation 70 | 71 | 1. Add the required resources in your `Doxyfile`: 72 | - **HTML_EXTRA_FILES:** `doxygen-awesome-fragment-copy-button.js` 73 | 2. In the `header.html` template, include `doxygen-awesome-fragment-copy-button.js` at the end of the `` and then initialize it: 74 | ```html 75 | 76 | 77 | 78 | 79 | 82 | 83 | 84 | ``` 85 | 3. The button can be customized to some extend: 86 | - Change the tooltip of the button: 87 | ```js 88 | DoxygenAwesomeFragmentCopyButton.title = "In die Zwischenablage kopieren" 89 | ``` 90 | - Change Icons: 91 | ```js 92 | DoxygenAwesomeFragmentCopyButton.copyIcon = `` 93 | DoxygenAwesomeFragmentCopyButton.successIcon = `` 94 | ``` 95 | 96 | All customizations must be applied before calling `DoxygenAwesomeDarkModeToggle.init()`! 97 | 98 | ## Paragraph Linking 99 | 100 | ***This feature is experimental!*** 101 | 102 | Provides a button on hover behind every headline to allow easy creation of a permanent link to the headline: 103 | 104 | 105 | 106 | Works for all headlines and for many documentation section titles. 107 | 108 | ### Installation 109 | 110 | 1. Add the required resources in your `Doxyfile`: 111 | - **HTML_EXTRA_FILES:** `doxygen-awesome-paragraph-link.js` 112 | 2. In the `header.html` template, include `doxygen-awesome-paragraph-link.js` at the end of the `` and then initialize it: 113 | ```html 114 | 115 | 116 | 117 | 118 | 121 | 122 | 123 | ``` 124 | 3. The button can be customized to some extend: 125 | - Change the tooltip of the button: 126 | ```js 127 | DoxygenAwesomeParagraphLink.title = "Abschnitt verknüpfen" 128 | ``` 129 | - Change Icon. Both plain characters or SVG icons are supported: 130 | ```js 131 | DoxygenAwesomeParagraphLink.icon = "¶" 132 | ``` 133 | 134 | All customizations must be applied before calling `DoxygenAwesomeParagraphLink.init()`! 135 | 136 | 137 | 138 | 139 | Read Next: [Customization](customization.md) 140 | -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/docs/img/darkmode_toggle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpewsey/HexagonalUI/c99404ac0f23f91a6d2cd582c3e722f9e9eefb95/Docs~/doxygen-awesome-css/docs/img/darkmode_toggle.png -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/docs/img/fancy_scrollbars_firefox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpewsey/HexagonalUI/c99404ac0f23f91a6d2cd582c3e722f9e9eefb95/Docs~/doxygen-awesome-css/docs/img/fancy_scrollbars_firefox.png -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/docs/img/fancy_scrollbars_webkit.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpewsey/HexagonalUI/c99404ac0f23f91a6d2cd582c3e722f9e9eefb95/Docs~/doxygen-awesome-css/docs/img/fancy_scrollbars_webkit.gif -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/docs/img/fragment_copy_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpewsey/HexagonalUI/c99404ac0f23f91a6d2cd582c3e722f9e9eefb95/Docs~/doxygen-awesome-css/docs/img/fragment_copy_button.png -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/docs/img/paragraph_link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpewsey/HexagonalUI/c99404ac0f23f91a6d2cd582c3e722f9e9eefb95/Docs~/doxygen-awesome-css/docs/img/paragraph_link.png -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/docs/tricks.md: -------------------------------------------------------------------------------- 1 | # Tips & Tricks 2 | 3 | [TOC] 4 | 5 | ## Class Diagrams with Graphviz 6 | 7 | To get the best looking class diagrams for your documentation, generate them with Graphviz as vector graphics with transparent background: 8 | 9 | ``` 10 | # Doxyfile 11 | HAVE_DOT = YES 12 | DOT_IMAGE_FORMAT = svg 13 | DOT_TRANSPARENT = YES 14 | ``` 15 | 16 | ## Disable Dark Mode 17 | 18 | If for some reason you don't want the theme to automatically switch to dark mode depending on the browser preference, 19 | you can disable dark mode by adding the `light-mode` class to the html-tag in the header template: 20 | 21 | ```html 22 | 23 | ``` 24 | 25 | The same can be done to always enable dark-mode: 26 | 27 | ```html 28 | 29 | ``` 30 | 31 | 32 | **This only works if you don't use the dark-mode toggle extension.** 33 | 34 | ## Choosing Sidebar Width 35 | 36 | If you have enabled the sidebar-only theme variant, make sure to carefully choose a proper width for your sidebar. 37 | It should be wide enough to hold the icon, project title and version number. If the content is too wide, it will be 38 | cut off. 39 | 40 | ```css 41 | html { 42 | /* Make sure sidebar is wide enough to contain the page title (logo + title + version) */ 43 | --side-nav-fixed-width: 335px; 44 | } 45 | ``` 46 | 47 | The choosen width should also be set in the Doxyfile: 48 | 49 | ``` 50 | # Doxyfile 51 | TREEVIEW_WIDTH = 335 52 | ``` 53 | 54 | 55 | 56 | Read Next: [Example](https://jothepro.github.io/doxygen-awesome-css/class_my_library_1_1_example.html) 57 | -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/doxygen-awesome-darkmode-toggle.js: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | Doxygen Awesome 4 | https://github.com/jothepro/doxygen-awesome-css 5 | 6 | MIT License 7 | 8 | Copyright (c) 2021 - 2022 jothepro 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | */ 29 | 30 | class DoxygenAwesomeDarkModeToggle extends HTMLElement { 31 | // SVG icons from https://fonts.google.com/icons 32 | // Licensed under the Apache 2.0 license: 33 | // https://www.apache.org/licenses/LICENSE-2.0.html 34 | static lightModeIcon = `` 35 | static darkModeIcon = `` 36 | static title = "Toggle Light/Dark Mode" 37 | 38 | static prefersLightModeInDarkModeKey = "prefers-light-mode-in-dark-mode" 39 | static prefersDarkModeInLightModeKey = "prefers-dark-mode-in-light-mode" 40 | 41 | static _staticConstructor = function() { 42 | DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.userPreference) 43 | // Update the color scheme when the browsers preference changes 44 | // without user interaction on the website. 45 | window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { 46 | DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged() 47 | }) 48 | // Update the color scheme when the tab is made visible again. 49 | // It is possible that the appearance was changed in another tab 50 | // while this tab was in the background. 51 | document.addEventListener("visibilitychange", visibilityState => { 52 | if (document.visibilityState === 'visible') { 53 | DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged() 54 | } 55 | }); 56 | }() 57 | 58 | static init() { 59 | $(function() { 60 | $(document).ready(function() { 61 | const toggleButton = document.createElement('doxygen-awesome-dark-mode-toggle') 62 | toggleButton.title = DoxygenAwesomeDarkModeToggle.title 63 | toggleButton.updateIcon() 64 | 65 | window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { 66 | toggleButton.updateIcon() 67 | }) 68 | document.addEventListener("visibilitychange", visibilityState => { 69 | if (document.visibilityState === 'visible') { 70 | toggleButton.updateIcon() 71 | } 72 | }); 73 | 74 | $(document).ready(function(){ 75 | document.getElementById("MSearchBox").parentNode.appendChild(toggleButton) 76 | }) 77 | $(window).resize(function(){ 78 | document.getElementById("MSearchBox").parentNode.appendChild(toggleButton) 79 | }) 80 | }) 81 | }) 82 | } 83 | 84 | constructor() { 85 | super(); 86 | this.onclick=this.toggleDarkMode 87 | } 88 | 89 | /** 90 | * @returns `true` for dark-mode, `false` for light-mode system preference 91 | */ 92 | static get systemPreference() { 93 | return window.matchMedia('(prefers-color-scheme: dark)').matches 94 | } 95 | 96 | /** 97 | * @returns `true` for dark-mode, `false` for light-mode user preference 98 | */ 99 | static get userPreference() { 100 | return (!DoxygenAwesomeDarkModeToggle.systemPreference && localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)) || 101 | (DoxygenAwesomeDarkModeToggle.systemPreference && !localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey)) 102 | } 103 | 104 | static set userPreference(userPreference) { 105 | DoxygenAwesomeDarkModeToggle.darkModeEnabled = userPreference 106 | if(!userPreference) { 107 | if(DoxygenAwesomeDarkModeToggle.systemPreference) { 108 | localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey, true) 109 | } else { 110 | localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey) 111 | } 112 | } else { 113 | if(!DoxygenAwesomeDarkModeToggle.systemPreference) { 114 | localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey, true) 115 | } else { 116 | localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey) 117 | } 118 | } 119 | DoxygenAwesomeDarkModeToggle.onUserPreferenceChanged() 120 | } 121 | 122 | static enableDarkMode(enable) { 123 | if(enable) { 124 | DoxygenAwesomeDarkModeToggle.darkModeEnabled = true 125 | document.documentElement.classList.add("dark-mode") 126 | document.documentElement.classList.remove("light-mode") 127 | } else { 128 | DoxygenAwesomeDarkModeToggle.darkModeEnabled = false 129 | document.documentElement.classList.remove("dark-mode") 130 | document.documentElement.classList.add("light-mode") 131 | } 132 | } 133 | 134 | static onSystemPreferenceChanged() { 135 | DoxygenAwesomeDarkModeToggle.darkModeEnabled = DoxygenAwesomeDarkModeToggle.userPreference 136 | DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled) 137 | } 138 | 139 | static onUserPreferenceChanged() { 140 | DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled) 141 | } 142 | 143 | toggleDarkMode() { 144 | DoxygenAwesomeDarkModeToggle.userPreference = !DoxygenAwesomeDarkModeToggle.userPreference 145 | this.updateIcon() 146 | } 147 | 148 | updateIcon() { 149 | if(DoxygenAwesomeDarkModeToggle.darkModeEnabled) { 150 | this.innerHTML = DoxygenAwesomeDarkModeToggle.darkModeIcon 151 | } else { 152 | this.innerHTML = DoxygenAwesomeDarkModeToggle.lightModeIcon 153 | } 154 | } 155 | } 156 | 157 | customElements.define("doxygen-awesome-dark-mode-toggle", DoxygenAwesomeDarkModeToggle); 158 | -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/doxygen-awesome-fragment-copy-button.js: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | Doxygen Awesome 4 | https://github.com/jothepro/doxygen-awesome-css 5 | 6 | MIT License 7 | 8 | Copyright (c) 2022 jothepro 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | */ 29 | 30 | class DoxygenAwesomeFragmentCopyButton extends HTMLElement { 31 | constructor() { 32 | super(); 33 | this.onclick=this.copyContent 34 | } 35 | static title = "Copy to clipboard" 36 | static copyIcon = `` 37 | static successIcon = `` 38 | static successDuration = 980 39 | static init() { 40 | $(function() { 41 | $(document).ready(function() { 42 | if(navigator.clipboard) { 43 | const fragments = document.getElementsByClassName("fragment") 44 | for(const fragment of fragments) { 45 | const fragmentWrapper = document.createElement("div") 46 | fragmentWrapper.className = "doxygen-awesome-fragment-wrapper" 47 | const fragmentCopyButton = document.createElement("doxygen-awesome-fragment-copy-button") 48 | fragmentCopyButton.innerHTML = DoxygenAwesomeFragmentCopyButton.copyIcon 49 | fragmentCopyButton.title = DoxygenAwesomeFragmentCopyButton.title 50 | 51 | fragment.parentNode.replaceChild(fragmentWrapper, fragment) 52 | fragmentWrapper.appendChild(fragment) 53 | fragmentWrapper.appendChild(fragmentCopyButton) 54 | 55 | } 56 | } 57 | }) 58 | }) 59 | } 60 | 61 | 62 | copyContent() { 63 | const content = this.previousSibling.cloneNode(true) 64 | // filter out line number from file listings 65 | content.querySelectorAll(".lineno, .ttc").forEach((node) => { 66 | node.remove() 67 | }) 68 | let textContent = content.textContent 69 | // remove trailing newlines that appear in file listings 70 | let numberOfTrailingNewlines = 0 71 | while(textContent.charAt(textContent.length - (numberOfTrailingNewlines + 1)) == '\n') { 72 | numberOfTrailingNewlines++; 73 | } 74 | textContent = textContent.substring(0, textContent.length - numberOfTrailingNewlines) 75 | navigator.clipboard.writeText(textContent); 76 | this.classList.add("success") 77 | this.innerHTML = DoxygenAwesomeFragmentCopyButton.successIcon 78 | window.setTimeout(() => { 79 | this.classList.remove("success") 80 | this.innerHTML = DoxygenAwesomeFragmentCopyButton.copyIcon 81 | }, DoxygenAwesomeFragmentCopyButton.successDuration); 82 | } 83 | } 84 | 85 | customElements.define("doxygen-awesome-fragment-copy-button", DoxygenAwesomeFragmentCopyButton) 86 | -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/doxygen-awesome-paragraph-link.js: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | Doxygen Awesome 4 | https://github.com/jothepro/doxygen-awesome-css 5 | 6 | MIT License 7 | 8 | Copyright (c) 2022 jothepro 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | */ 29 | 30 | class DoxygenAwesomeParagraphLink { 31 | // Icon from https://fonts.google.com/icons 32 | // Licensed under the Apache 2.0 license: 33 | // https://www.apache.org/licenses/LICENSE-2.0.html 34 | static icon = `` 35 | static title = "Permanent Link" 36 | static init() { 37 | $(function() { 38 | $(document).ready(function() { 39 | document.querySelectorAll(".contents a.anchor[id], .contents .groupheader > a[id]").forEach((node) => { 40 | let anchorlink = document.createElement("a") 41 | anchorlink.setAttribute("href", `#${node.getAttribute("id")}`) 42 | anchorlink.setAttribute("title", DoxygenAwesomeParagraphLink.title) 43 | anchorlink.classList.add("anchorlink") 44 | node.classList.add("anchor") 45 | anchorlink.innerHTML = DoxygenAwesomeParagraphLink.icon 46 | node.parentElement.appendChild(anchorlink) 47 | }) 48 | }) 49 | }) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/doxygen-awesome-sidebar-only-darkmode-toggle.css: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | 4 | Doxygen Awesome 5 | https://github.com/jothepro/doxygen-awesome-css 6 | 7 | MIT License 8 | 9 | Copyright (c) 2021 jothepro 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy 12 | of this software and associated documentation files (the "Software"), to deal 13 | in the Software without restriction, including without limitation the rights 14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all 19 | copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | 29 | */ 30 | 31 | @media screen and (min-width: 768px) { 32 | 33 | #MSearchBox { 34 | width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - var(--searchbar-height) - 1px); 35 | } 36 | 37 | #MSearchField { 38 | width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 66px - var(--searchbar-height)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/doxygen-awesome-sidebar-only.css: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | Doxygen Awesome 4 | https://github.com/jothepro/doxygen-awesome-css 5 | 6 | MIT License 7 | 8 | Copyright (c) 2021 jothepro 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | */ 29 | 30 | html { 31 | /* side nav width. MUST be = `TREEVIEW_WIDTH`. 32 | * Make sure it is wide enough to contain the page title (logo + title + version) 33 | */ 34 | --side-nav-fixed-width: 335px; 35 | --menu-display: none; 36 | 37 | --top-height: 120px; 38 | } 39 | 40 | #projectname { 41 | white-space: nowrap; 42 | } 43 | 44 | 45 | @media screen and (min-width: 768px) { 46 | html { 47 | --searchbar-background: var(--page-background-color); 48 | } 49 | 50 | #side-nav { 51 | min-width: var(--side-nav-fixed-width); 52 | max-width: var(--side-nav-fixed-width); 53 | top: var(--top-height); 54 | overflow: visible; 55 | } 56 | 57 | #nav-tree, #side-nav { 58 | height: calc(100vh - var(--top-height)) !important; 59 | } 60 | 61 | #nav-tree { 62 | padding: 0; 63 | } 64 | 65 | #top { 66 | display: block; 67 | border-bottom: none; 68 | height: var(--top-height); 69 | margin-bottom: calc(0px - var(--top-height)); 70 | max-width: var(--side-nav-fixed-width); 71 | overflow: hidden; 72 | background: var(--side-nav-background); 73 | } 74 | #main-nav { 75 | float: left; 76 | padding-right: 0; 77 | } 78 | 79 | .ui-resizable-handle { 80 | cursor: default; 81 | width: 1px !important; 82 | box-shadow: 0 calc(-2 * var(--top-height)) 0 0 var(--separator-color); 83 | } 84 | 85 | #nav-path { 86 | position: fixed; 87 | right: 0; 88 | left: var(--side-nav-fixed-width); 89 | bottom: 0; 90 | width: auto; 91 | } 92 | 93 | #doc-content { 94 | height: calc(100vh - 31px) !important; 95 | padding-bottom: calc(3 * var(--spacing-large)); 96 | padding-top: calc(var(--top-height) - 80px); 97 | box-sizing: border-box; 98 | margin-left: var(--side-nav-fixed-width) !important; 99 | } 100 | 101 | #MSearchBox { 102 | width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium))); 103 | } 104 | 105 | #MSearchField { 106 | width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 65px); 107 | } 108 | 109 | #MSearchResultsWindow { 110 | left: var(--spacing-medium) !important; 111 | right: auto; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/doxygen-awesome.css: -------------------------------------------------------------------------------- 1 | /** 2 | 3 | Doxygen Awesome 4 | https://github.com/jothepro/doxygen-awesome-css 5 | 6 | MIT License 7 | 8 | Copyright (c) 2021 - 2022 jothepro 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | */ 29 | 30 | html { 31 | /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */ 32 | --primary-color: #1779c4; 33 | --primary-dark-color: #335c80; 34 | --primary-light-color: #70b1e9; 35 | 36 | /* page base colors */ 37 | --page-background-color: white; 38 | --page-foreground-color: #2f4153; 39 | --page-secondary-foreground-color: #637485; 40 | 41 | /* color for all separators on the website: hr, borders, ... */ 42 | --separator-color: #dedede; 43 | 44 | /* border radius for all rounded components. Will affect many components, like dropdowns, memitems, codeblocks, ... */ 45 | --border-radius-large: 8px; 46 | --border-radius-small: 4px; 47 | --border-radius-medium: 6px; 48 | 49 | /* default spacings. Most compontest reference these values for spacing, to provide uniform spacing on the page. */ 50 | --spacing-small: 5px; 51 | --spacing-medium: 10px; 52 | --spacing-large: 16px; 53 | 54 | /* default box shadow used for raising an element above the normal content. Used in dropdowns, Searchresult, ... */ 55 | --box-shadow: 0 2px 8px 0 rgba(0,0,0,.075); 56 | 57 | --odd-color: rgba(0,0,0,.028); 58 | 59 | /* font-families. will affect all text on the website 60 | * font-family: the normal font for text, headlines, menus 61 | * font-family-monospace: used for preformatted text in memtitle, code, fragments 62 | */ 63 | --font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif; 64 | --font-family-monospace: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace; 65 | 66 | /* font sizes */ 67 | --page-font-size: 15.6px; 68 | --navigation-font-size: 14.4px; 69 | --code-font-size: 14px; /* affects code, fragment */ 70 | --title-font-size: 22px; 71 | 72 | /* content text properties. These only affect the page content, not the navigation or any other ui elements */ 73 | --content-line-height: 27px; 74 | /* The content is centered and constraint in it's width. To make the content fill the whole page, set the variable to auto.*/ 75 | --content-maxwidth: 1000px; 76 | 77 | /* colors for various content boxes: @warning, @note, @deprecated @bug */ 78 | --warning-color: #f8d1cc; 79 | --warning-color-dark: #b61825; 80 | --warning-color-darker: #75070f; 81 | --note-color: #faf3d8; 82 | --note-color-dark: #f3a600; 83 | --note-color-darker: #5f4204; 84 | --todo-color: #e4f3ff; 85 | --todo-color-dark: #1879C4; 86 | --todo-color-darker: #274a5c; 87 | --deprecated-color: #ecf0f3; 88 | --deprecated-color-dark: #5b6269; 89 | --deprecated-color-darker: #43454a; 90 | --bug-color: #e4dafd; 91 | --bug-color-dark: #5b2bdd; 92 | --bug-color-darker: #2a0d72; 93 | --invariant-color: #d8f1e3; 94 | --invariant-color-dark: #44b86f; 95 | --invariant-color-darker: #265532; 96 | 97 | /* blockquote colors */ 98 | --blockquote-background: #f8f9fa; 99 | --blockquote-foreground: #636568; 100 | 101 | /* table colors */ 102 | --tablehead-background: #f1f1f1; 103 | --tablehead-foreground: var(--page-foreground-color); 104 | 105 | /* menu-display: block | none 106 | * Visibility of the top navigation on screens >= 768px. On smaller screen the menu is always visible. 107 | * `GENERATE_TREEVIEW` MUST be enabled! 108 | */ 109 | --menu-display: block; 110 | 111 | --menu-focus-foreground: var(--page-background-color); 112 | --menu-focus-background: var(--primary-color); 113 | --menu-selected-background: rgba(0,0,0,.05); 114 | 115 | 116 | --header-background: var(--page-background-color); 117 | --header-foreground: var(--page-foreground-color); 118 | 119 | /* searchbar colors */ 120 | --searchbar-background: var(--side-nav-background); 121 | --searchbar-foreground: var(--page-foreground-color); 122 | 123 | /* searchbar size 124 | * (`searchbar-width` is only applied on screens >= 768px. 125 | * on smaller screens the searchbar will always fill the entire screen width) */ 126 | --searchbar-height: 33px; 127 | --searchbar-width: 210px; 128 | --searchbar-border-radius: var(--searchbar-height); 129 | 130 | /* code block colors */ 131 | --code-background: #f5f5f5; 132 | --code-foreground: var(--page-foreground-color); 133 | 134 | /* fragment colors */ 135 | --fragment-background: #F8F9FA; 136 | --fragment-foreground: #37474F; 137 | --fragment-keyword: #bb6bb2; 138 | --fragment-keywordtype: #8258b3; 139 | --fragment-keywordflow: #d67c3b; 140 | --fragment-token: #438a59; 141 | --fragment-comment: #969696; 142 | --fragment-link: #5383d6; 143 | --fragment-preprocessor: #46aaa5; 144 | --fragment-linenumber-color: #797979; 145 | --fragment-linenumber-background: #f4f4f5; 146 | --fragment-linenumber-border: #e3e5e7; 147 | --fragment-lineheight: 20px; 148 | 149 | /* sidebar navigation (treeview) colors */ 150 | --side-nav-background: #fbfbfb; 151 | --side-nav-foreground: var(--page-foreground-color); 152 | --side-nav-arrow-opacity: 0; 153 | --side-nav-arrow-hover-opacity: 0.9; 154 | 155 | --toc-background: var(--side-nav-background); 156 | --toc-foreground: var(--side-nav-foreground); 157 | 158 | /* height of an item in any tree / collapsable table */ 159 | --tree-item-height: 30px; 160 | 161 | --memname-font-size: var(--code-font-size); 162 | --memtitle-font-size: 18px; 163 | 164 | --webkit-scrollbar-size: 7px; 165 | --webkit-scrollbar-padding: 4px; 166 | --webkit-scrollbar-color: var(--separator-color); 167 | } 168 | 169 | @media screen and (max-width: 767px) { 170 | html { 171 | --page-font-size: 16px; 172 | --navigation-font-size: 16px; 173 | --code-font-size: 15px; /* affects code, fragment */ 174 | --title-font-size: 22px; 175 | } 176 | } 177 | 178 | @media (prefers-color-scheme: dark) { 179 | html:not(.light-mode) { 180 | color-scheme: dark; 181 | 182 | --primary-color: #1982d2; 183 | --primary-dark-color: #86a9c4; 184 | --primary-light-color: #4779ac; 185 | 186 | --box-shadow: 0 2px 8px 0 rgba(0,0,0,.35); 187 | 188 | --odd-color: rgba(100,100,100,.06); 189 | 190 | --menu-selected-background: rgba(0,0,0,.4); 191 | 192 | --page-background-color: #1C1D1F; 193 | --page-foreground-color: #d2dbde; 194 | --page-secondary-foreground-color: #859399; 195 | --separator-color: #38393b; 196 | --side-nav-background: #252628; 197 | 198 | --code-background: #2a2c2f; 199 | 200 | --tablehead-background: #2a2c2f; 201 | 202 | --blockquote-background: #222325; 203 | --blockquote-foreground: #7e8c92; 204 | 205 | --warning-color: #2e1917; 206 | --warning-color-dark: #ad2617; 207 | --warning-color-darker: #f5b1aa; 208 | --note-color: #3b2e04; 209 | --note-color-dark: #f1b602; 210 | --note-color-darker: #ceb670; 211 | --todo-color: #163750; 212 | --todo-color-dark: #1982D2; 213 | --todo-color-darker: #dcf0fa; 214 | --deprecated-color: #2e323b; 215 | --deprecated-color-dark: #738396; 216 | --deprecated-color-darker: #abb0bd; 217 | --bug-color: #2a2536; 218 | --bug-color-dark: #7661b3; 219 | --bug-color-darker: #ae9ed6; 220 | --invariant-color: #303a35; 221 | --invariant-color-dark: #76ce96; 222 | --invariant-color-darker: #cceed5; 223 | 224 | --fragment-background: #282c34; 225 | --fragment-foreground: #dbe4eb; 226 | --fragment-keyword: #cc99cd; 227 | --fragment-keywordtype: #ab99cd; 228 | --fragment-keywordflow: #e08000; 229 | --fragment-token: #7ec699; 230 | --fragment-comment: #999999; 231 | --fragment-link: #98c0e3; 232 | --fragment-preprocessor: #65cabe; 233 | --fragment-linenumber-color: #cccccc; 234 | --fragment-linenumber-background: #35393c; 235 | --fragment-linenumber-border: #1f1f1f; 236 | } 237 | } 238 | 239 | /* dark mode variables are defined twice, to support both the dark-mode without and with doxygen-awesome-darkmode-toggle.js */ 240 | html.dark-mode { 241 | color-scheme: dark; 242 | 243 | --primary-color: #1982d2; 244 | --primary-dark-color: #86a9c4; 245 | --primary-light-color: #4779ac; 246 | 247 | --box-shadow: 0 2px 8px 0 rgba(0,0,0,.30); 248 | 249 | --odd-color: rgba(100,100,100,.06); 250 | 251 | --menu-selected-background: rgba(0,0,0,.4); 252 | 253 | --page-background-color: #1C1D1F; 254 | --page-foreground-color: #d2dbde; 255 | --page-secondary-foreground-color: #859399; 256 | --separator-color: #38393b; 257 | --side-nav-background: #252628; 258 | 259 | --code-background: #2a2c2f; 260 | 261 | --tablehead-background: #2a2c2f; 262 | 263 | --blockquote-background: #222325; 264 | --blockquote-foreground: #7e8c92; 265 | 266 | --warning-color: #2e1917; 267 | --warning-color-dark: #ad2617; 268 | --warning-color-darker: #f5b1aa; 269 | --note-color: #3b2e04; 270 | --note-color-dark: #f1b602; 271 | --note-color-darker: #ceb670; 272 | --todo-color: #163750; 273 | --todo-color-dark: #1982D2; 274 | --todo-color-darker: #dcf0fa; 275 | --deprecated-color: #2e323b; 276 | --deprecated-color-dark: #738396; 277 | --deprecated-color-darker: #abb0bd; 278 | --bug-color: #2a2536; 279 | --bug-color-dark: #7661b3; 280 | --bug-color-darker: #ae9ed6; 281 | --invariant-color: #303a35; 282 | --invariant-color-dark: #76ce96; 283 | --invariant-color-darker: #cceed5; 284 | 285 | --fragment-background: #282c34; 286 | --fragment-foreground: #dbe4eb; 287 | --fragment-keyword: #cc99cd; 288 | --fragment-keywordtype: #ab99cd; 289 | --fragment-keywordflow: #e08000; 290 | --fragment-token: #7ec699; 291 | --fragment-comment: #999999; 292 | --fragment-link: #98c0e3; 293 | --fragment-preprocessor: #65cabe; 294 | --fragment-linenumber-color: #cccccc; 295 | --fragment-linenumber-background: #35393c; 296 | --fragment-linenumber-border: #1f1f1f; 297 | } 298 | 299 | body { 300 | color: var(--page-foreground-color); 301 | background-color: var(--page-background-color); 302 | font-size: var(--page-font-size); 303 | } 304 | 305 | body, table, div, p, dl, #nav-tree .label, .title, .sm-dox a, .sm-dox a:hover, .sm-dox a:focus, #projectname, .SelectItem, #MSearchField, .navpath li.navelem a, .navpath li.navelem a:hover { 306 | font-family: var(--font-family); 307 | } 308 | 309 | h1, h2, h3, h4, h5 { 310 | margin-top: .9em; 311 | font-weight: 600; 312 | line-height: initial; 313 | } 314 | 315 | p, div, table, dl { 316 | font-size: var(--page-font-size); 317 | } 318 | 319 | a:link, a:visited, a:hover, a:focus, a:active { 320 | color: var(--primary-color) !important; 321 | font-weight: 500; 322 | } 323 | 324 | a.anchor { 325 | scroll-margin-top: var(--spacing-large); 326 | } 327 | 328 | /* 329 | Title and top navigation 330 | */ 331 | 332 | #top { 333 | background: var(--header-background); 334 | border-bottom: 1px solid var(--separator-color); 335 | } 336 | 337 | @media screen and (min-width: 768px) { 338 | #top { 339 | display: flex; 340 | flex-wrap: wrap; 341 | justify-content: space-between; 342 | align-items: center; 343 | } 344 | } 345 | 346 | #main-nav { 347 | flex-grow: 5; 348 | padding: var(--spacing-small) var(--spacing-medium); 349 | } 350 | 351 | #titlearea { 352 | width: auto; 353 | padding: var(--spacing-medium) var(--spacing-large); 354 | background: none; 355 | color: var(--header-foreground); 356 | border-bottom: none; 357 | } 358 | 359 | @media screen and (max-width: 767px) { 360 | #titlearea { 361 | padding-bottom: var(--spacing-small); 362 | } 363 | } 364 | 365 | #titlearea table tbody tr { 366 | height: auto !important; 367 | } 368 | 369 | #projectname { 370 | font-size: var(--title-font-size); 371 | font-weight: 600; 372 | } 373 | 374 | #projectnumber { 375 | font-family: inherit; 376 | font-size: 60%; 377 | } 378 | 379 | #projectbrief { 380 | font-family: inherit; 381 | font-size: 80%; 382 | } 383 | 384 | #projectlogo { 385 | vertical-align: middle; 386 | } 387 | 388 | #projectlogo img { 389 | max-height: calc(var(--title-font-size) * 2); 390 | margin-right: var(--spacing-small); 391 | } 392 | 393 | .sm-dox, .tabs, .tabs2, .tabs3 { 394 | background: none; 395 | padding: 0; 396 | } 397 | 398 | .tabs, .tabs2, .tabs3 { 399 | border-bottom: 1px solid var(--separator-color); 400 | margin-bottom: -1px; 401 | } 402 | 403 | @media screen and (max-width: 767px) { 404 | .sm-dox a span.sub-arrow { 405 | background: var(--code-background); 406 | } 407 | 408 | #main-menu a.has-submenu span.sub-arrow { 409 | color: var(--page-secondary-foreground-color); 410 | border-radius: var(--border-radius-medium); 411 | } 412 | 413 | #main-menu a.has-submenu:hover span.sub-arrow { 414 | color: var(--page-foreground-color); 415 | } 416 | } 417 | 418 | @media screen and (min-width: 768px) { 419 | .sm-dox li, .tablist li { 420 | display: var(--menu-display); 421 | } 422 | 423 | .sm-dox a span.sub-arrow { 424 | border-color: var(--header-foreground) transparent transparent transparent; 425 | } 426 | 427 | .sm-dox a:hover span.sub-arrow { 428 | border-color: var(--menu-focus-foreground) transparent transparent transparent; 429 | } 430 | 431 | .sm-dox ul a span.sub-arrow { 432 | border-color: transparent transparent transparent var(--page-foreground-color); 433 | } 434 | 435 | .sm-dox ul a:hover span.sub-arrow { 436 | border-color: transparent transparent transparent var(--menu-focus-foreground); 437 | } 438 | } 439 | 440 | .sm-dox ul { 441 | background: var(--page-background-color); 442 | box-shadow: var(--box-shadow); 443 | border: 1px solid var(--separator-color); 444 | border-radius: var(--border-radius-medium) !important; 445 | padding: var(--spacing-small); 446 | animation: ease-out 150ms slideInMenu; 447 | } 448 | 449 | @keyframes slideInMenu { 450 | from { 451 | opacity: 0; 452 | transform: translate(0px, -2px); 453 | } 454 | 455 | to { 456 | opacity: 1; 457 | transform: translate(0px, 0px); 458 | } 459 | } 460 | 461 | .sm-dox ul a { 462 | color: var(--page-foreground-color) !important; 463 | background: var(--page-background-color); 464 | font-size: var(--navigation-font-size); 465 | } 466 | 467 | .sm-dox>li>ul:after { 468 | border-bottom-color: var(--page-background-color) !important; 469 | } 470 | 471 | .sm-dox>li>ul:before { 472 | border-bottom-color: var(--separator-color) !important; 473 | } 474 | 475 | .sm-dox ul a:hover, .sm-dox ul a:active, .sm-dox ul a:focus { 476 | font-size: var(--navigation-font-size) !important; 477 | color: var(--menu-focus-foreground) !important; 478 | text-shadow: none; 479 | background-color: var(--menu-focus-background); 480 | border-radius: var(--border-radius-small) !important; 481 | } 482 | 483 | .sm-dox a, .sm-dox a:focus, .tablist li, .tablist li a, .tablist li.current a { 484 | text-shadow: none; 485 | background: transparent; 486 | background-image: none !important; 487 | color: var(--header-foreground) !important; 488 | font-weight: normal; 489 | font-size: var(--navigation-font-size); 490 | border-radius: var(--border-radius-small) !important; 491 | } 492 | 493 | .sm-dox a:focus { 494 | outline: auto; 495 | } 496 | 497 | .sm-dox a:hover, .sm-dox a:active, .tablist li a:hover { 498 | text-shadow: none; 499 | font-weight: normal; 500 | background: var(--menu-focus-background); 501 | color: var(--menu-focus-foreground) !important; 502 | border-radius: var(--border-radius-small) !important; 503 | font-size: var(--navigation-font-size); 504 | } 505 | 506 | .tablist li.current { 507 | border-radius: var(--border-radius-small); 508 | background: var(--menu-selected-background); 509 | } 510 | 511 | .tablist li { 512 | margin: var(--spacing-small) 0 var(--spacing-small) var(--spacing-small); 513 | } 514 | 515 | .tablist a { 516 | padding: 0 var(--spacing-large); 517 | } 518 | 519 | 520 | /* 521 | Search box 522 | */ 523 | 524 | #MSearchBox { 525 | height: var(--searchbar-height); 526 | background: var(--searchbar-background); 527 | border-radius: var(--searchbar-border-radius); 528 | border: 1px solid var(--separator-color); 529 | overflow: hidden; 530 | width: var(--searchbar-width); 531 | position: relative; 532 | box-shadow: none; 533 | display: block; 534 | margin-top: 0; 535 | } 536 | 537 | .left #MSearchSelect { 538 | left: 0; 539 | user-select: none; 540 | } 541 | 542 | .SelectionMark { 543 | user-select: none; 544 | } 545 | 546 | .tabs .left #MSearchSelect { 547 | padding-left: 0; 548 | } 549 | 550 | .tabs #MSearchBox { 551 | position: absolute; 552 | right: var(--spacing-medium); 553 | } 554 | 555 | @media screen and (max-width: 767px) { 556 | .tabs #MSearchBox { 557 | position: relative; 558 | right: 0; 559 | margin-left: var(--spacing-medium); 560 | margin-top: 0; 561 | } 562 | } 563 | 564 | #MSearchSelectWindow, #MSearchResultsWindow { 565 | z-index: 9999; 566 | } 567 | 568 | #MSearchBox.MSearchBoxActive { 569 | border-color: var(--primary-color); 570 | box-shadow: inset 0 0 0 1px var(--primary-color); 571 | } 572 | 573 | #main-menu > li:last-child { 574 | margin-right: 0; 575 | } 576 | 577 | @media screen and (max-width: 767px) { 578 | #main-menu > li:last-child { 579 | height: 50px; 580 | } 581 | } 582 | 583 | #MSearchField { 584 | font-size: var(--navigation-font-size); 585 | height: calc(var(--searchbar-height) - 2px); 586 | background: transparent; 587 | width: calc(var(--searchbar-width) - 64px); 588 | } 589 | 590 | .MSearchBoxActive #MSearchField { 591 | color: var(--searchbar-foreground); 592 | } 593 | 594 | #MSearchSelect { 595 | top: calc(calc(var(--searchbar-height) / 2) - 11px); 596 | } 597 | 598 | .left #MSearchSelect { 599 | padding-left: 8px; 600 | } 601 | 602 | #MSearchBox span.left, #MSearchBox span.right { 603 | background: none; 604 | } 605 | 606 | #MSearchBox span.right { 607 | padding-top: calc(calc(var(--searchbar-height) / 2) - 12px); 608 | position: absolute; 609 | right: var(--spacing-small); 610 | } 611 | 612 | .tabs #MSearchBox span.right { 613 | top: calc(calc(var(--searchbar-height) / 2) - 12px); 614 | } 615 | 616 | @keyframes slideInSearchResults { 617 | from { 618 | opacity: 0; 619 | transform: translate(0, 15px); 620 | } 621 | 622 | to { 623 | opacity: 1; 624 | transform: translate(0, 20px); 625 | } 626 | } 627 | 628 | #MSearchResultsWindow { 629 | left: auto !important; 630 | right: var(--spacing-medium); 631 | border-radius: var(--border-radius-large); 632 | border: 1px solid var(--separator-color); 633 | transform: translate(0, 20px); 634 | box-shadow: var(--box-shadow); 635 | animation: ease-out 280ms slideInSearchResults; 636 | background: var(--page-background-color); 637 | } 638 | 639 | iframe#MSearchResults { 640 | margin: 4px; 641 | } 642 | 643 | iframe { 644 | color-scheme: normal; 645 | } 646 | 647 | @media (prefers-color-scheme: dark) { 648 | html:not(.light-mode) iframe#MSearchResults { 649 | filter: invert() hue-rotate(180deg); 650 | } 651 | } 652 | 653 | html.dark-mode iframe#MSearchResults { 654 | filter: invert() hue-rotate(180deg); 655 | } 656 | 657 | #MSearchSelectWindow { 658 | border: 1px solid var(--separator-color); 659 | border-radius: var(--border-radius-medium); 660 | box-shadow: var(--box-shadow); 661 | background: var(--page-background-color); 662 | padding-top: var(--spacing-small); 663 | padding-bottom: var(--spacing-small); 664 | } 665 | 666 | #MSearchSelectWindow a.SelectItem { 667 | font-size: var(--navigation-font-size); 668 | line-height: var(--content-line-height); 669 | margin: 0 var(--spacing-small); 670 | border-radius: var(--border-radius-small); 671 | color: var(--page-foreground-color) !important; 672 | font-weight: normal; 673 | } 674 | 675 | #MSearchSelectWindow a.SelectItem:hover { 676 | background: var(--menu-focus-background); 677 | color: var(--menu-focus-foreground) !important; 678 | } 679 | 680 | @media screen and (max-width: 767px) { 681 | #MSearchBox { 682 | margin-top: var(--spacing-medium); 683 | margin-bottom: var(--spacing-medium); 684 | width: calc(100vw - 30px); 685 | } 686 | 687 | #main-menu > li:last-child { 688 | float: none !important; 689 | } 690 | 691 | #MSearchField { 692 | width: calc(100vw - 110px); 693 | } 694 | 695 | @keyframes slideInSearchResultsMobile { 696 | from { 697 | opacity: 0; 698 | transform: translate(0, 15px); 699 | } 700 | 701 | to { 702 | opacity: 1; 703 | transform: translate(0, 20px); 704 | } 705 | } 706 | 707 | #MSearchResultsWindow { 708 | left: var(--spacing-medium) !important; 709 | right: var(--spacing-medium); 710 | overflow: auto; 711 | transform: translate(0, 20px); 712 | animation: ease-out 280ms slideInSearchResultsMobile; 713 | } 714 | 715 | /* 716 | * Overwrites for fixing the searchbox on mobile in doxygen 1.9.2 717 | */ 718 | label.main-menu-btn ~ #searchBoxPos1 { 719 | top: 3px !important; 720 | right: 6px !important; 721 | left: 45px; 722 | display: flex; 723 | } 724 | 725 | label.main-menu-btn ~ #searchBoxPos1 > #MSearchBox { 726 | margin-top: 0; 727 | margin-bottom: 0; 728 | flex-grow: 2; 729 | float: left; 730 | } 731 | } 732 | 733 | /* 734 | Tree view 735 | */ 736 | 737 | #side-nav { 738 | padding: 0 !important; 739 | background: var(--side-nav-background); 740 | } 741 | 742 | @media screen and (max-width: 767px) { 743 | #side-nav { 744 | display: none; 745 | } 746 | 747 | #doc-content { 748 | margin-left: 0 !important; 749 | } 750 | } 751 | 752 | #nav-tree { 753 | background: transparent; 754 | } 755 | 756 | #nav-tree .label { 757 | font-size: var(--navigation-font-size); 758 | } 759 | 760 | #nav-tree .item { 761 | height: var(--tree-item-height); 762 | line-height: var(--tree-item-height); 763 | } 764 | 765 | #nav-sync { 766 | bottom: 12px; 767 | right: 12px; 768 | top: auto !important; 769 | user-select: none; 770 | } 771 | 772 | #nav-tree .selected { 773 | text-shadow: none; 774 | background-image: none; 775 | background-color: transparent; 776 | box-shadow: inset 4px 0 0 0 var(--primary-color); 777 | } 778 | 779 | #nav-tree a { 780 | color: var(--side-nav-foreground) !important; 781 | font-weight: normal; 782 | } 783 | 784 | #nav-tree a:focus { 785 | outline-style: auto; 786 | } 787 | 788 | #nav-tree .arrow { 789 | opacity: var(--side-nav-arrow-opacity); 790 | } 791 | 792 | .arrow { 793 | color: inherit; 794 | cursor: pointer; 795 | font-size: 45%; 796 | vertical-align: middle; 797 | margin-right: 2px; 798 | font-family: serif; 799 | height: auto; 800 | text-align: right; 801 | } 802 | 803 | #nav-tree div.item:hover .arrow, #nav-tree a:focus .arrow { 804 | opacity: var(--side-nav-arrow-hover-opacity); 805 | } 806 | 807 | #nav-tree .selected a { 808 | color: var(--primary-color) !important; 809 | font-weight: bolder; 810 | font-weight: 600; 811 | } 812 | 813 | .ui-resizable-e { 814 | background: var(--separator-color); 815 | width: 1px; 816 | } 817 | 818 | /* 819 | Contents 820 | */ 821 | 822 | div.header { 823 | border-bottom: 1px solid var(--separator-color); 824 | background-color: var(--page-background-color); 825 | background-image: none; 826 | } 827 | 828 | div.contents, div.header .title, div.header .summary { 829 | max-width: var(--content-maxwidth); 830 | } 831 | 832 | div.contents, div.header .title { 833 | line-height: initial; 834 | margin: calc(var(--spacing-medium) + .2em) auto var(--spacing-medium) auto; 835 | } 836 | 837 | div.header .summary { 838 | margin: var(--spacing-medium) auto 0 auto; 839 | } 840 | 841 | div.headertitle { 842 | padding: 0; 843 | } 844 | 845 | div.header .title { 846 | font-weight: 600; 847 | font-size: 210%; 848 | padding: var(--spacing-medium) var(--spacing-large); 849 | word-break: break-word; 850 | } 851 | 852 | div.header .summary { 853 | width: auto; 854 | display: block; 855 | float: none; 856 | padding: 0 var(--spacing-large); 857 | } 858 | 859 | td.memSeparator { 860 | border-color: var(--separator-color); 861 | } 862 | 863 | span.mlabel { 864 | background: var(--primary-color); 865 | border: none; 866 | padding: 4px 9px; 867 | border-radius: 12px; 868 | margin-right: var(--spacing-medium); 869 | } 870 | 871 | span.mlabel:last-of-type { 872 | margin-right: 2px; 873 | } 874 | 875 | div.contents { 876 | padding: 0 var(--spacing-large); 877 | } 878 | 879 | div.contents p, div.contents li { 880 | line-height: var(--content-line-height); 881 | } 882 | 883 | div.contents div.dyncontent { 884 | margin: var(--spacing-medium) 0; 885 | } 886 | 887 | @media (prefers-color-scheme: dark) { 888 | html:not(.light-mode) div.contents div.dyncontent img, 889 | html:not(.light-mode) div.contents center img, 890 | html:not(.light-mode) div.contents table img, 891 | html:not(.light-mode) div.contents div.dyncontent iframe, 892 | html:not(.light-mode) div.contents center iframe, 893 | html:not(.light-mode) div.contents table iframe { 894 | filter: hue-rotate(180deg) invert(); 895 | } 896 | } 897 | 898 | html.dark-mode div.contents div.dyncontent img, 899 | html.dark-mode div.contents center img, 900 | html.dark-mode div.contents table img, 901 | html.dark-mode div.contents div.dyncontent iframe, 902 | html.dark-mode div.contents center iframe, 903 | html.dark-mode div.contents table iframe { 904 | filter: hue-rotate(180deg) invert(); 905 | } 906 | 907 | h2.groupheader { 908 | border-bottom: 0px; 909 | color: var(--page-foreground-color); 910 | box-shadow: 911 | 100px 0 var(--page-background-color), 912 | -100px 0 var(--page-background-color), 913 | 100px 0.75px var(--separator-color), 914 | -100px 0.75px var(--separator-color), 915 | 500px 0 var(--page-background-color), 916 | -500px 0 var(--page-background-color), 917 | 500px 0.75px var(--separator-color), 918 | -500px 0.75px var(--separator-color), 919 | 1500px 0 var(--page-background-color), 920 | -1500px 0 var(--page-background-color), 921 | 1500px 0.75px var(--separator-color), 922 | -1500px 0.75px var(--separator-color), 923 | 2000px 0 var(--page-background-color), 924 | -2000px 0 var(--page-background-color), 925 | 2000px 0.75px var(--separator-color), 926 | -2000px 0.75px var(--separator-color); 927 | } 928 | 929 | blockquote { 930 | margin: 0 var(--spacing-medium) 0 var(--spacing-medium); 931 | padding: var(--spacing-small) var(--spacing-large); 932 | background: var(--blockquote-background); 933 | color: var(--blockquote-foreground); 934 | border-left: 0; 935 | overflow: visible; 936 | border-radius: var(--border-radius-medium); 937 | overflow: visible; 938 | position: relative; 939 | } 940 | 941 | blockquote::before, blockquote::after { 942 | font-weight: bold; 943 | font-family: serif; 944 | font-size: 360%; 945 | opacity: .15; 946 | position: absolute; 947 | } 948 | 949 | blockquote::before { 950 | content: "“"; 951 | left: -10px; 952 | top: 4px; 953 | } 954 | 955 | blockquote::after { 956 | content: "”"; 957 | right: -8px; 958 | bottom: -25px; 959 | } 960 | 961 | blockquote p { 962 | margin: var(--spacing-small) 0 var(--spacing-medium) 0; 963 | } 964 | .paramname { 965 | font-weight: 600; 966 | color: var(--primary-dark-color); 967 | } 968 | 969 | .paramname > code { 970 | border: 0; 971 | } 972 | 973 | table.params .paramname { 974 | font-weight: 600; 975 | font-family: var(--font-family-monospace); 976 | font-size: var(--code-font-size); 977 | padding-right: var(--spacing-small); 978 | } 979 | 980 | .glow { 981 | text-shadow: 0 0 15px var(--primary-light-color) !important; 982 | } 983 | 984 | .alphachar a { 985 | color: var(--page-foreground-color); 986 | } 987 | 988 | /* 989 | Table of Contents 990 | */ 991 | 992 | div.toc { 993 | z-index: 10; 994 | position: relative; 995 | background-color: var(--toc-background); 996 | border: 1px solid var(--separator-color); 997 | border-radius: var(--border-radius-medium); 998 | box-shadow: var(--box-shadow); 999 | padding: 0 var(--spacing-large); 1000 | margin: 0 0 var(--spacing-medium) var(--spacing-medium); 1001 | } 1002 | 1003 | div.toc h3 { 1004 | color: var(--toc-foreground); 1005 | font-size: var(--navigation-font-size); 1006 | margin: var(--spacing-large) 0; 1007 | } 1008 | 1009 | div.toc li { 1010 | font-size: var(--navigation-font-size); 1011 | padding: 0; 1012 | background: none; 1013 | } 1014 | 1015 | div.toc li:before { 1016 | content: '↓'; 1017 | font-weight: 800; 1018 | font-family: var(--font-family); 1019 | margin-right: var(--spacing-small); 1020 | color: var(--toc-foreground); 1021 | opacity: .4; 1022 | } 1023 | 1024 | div.toc ul li.level1 { 1025 | margin: 0; 1026 | } 1027 | 1028 | div.toc ul li.level2, div.toc ul li.level3 { 1029 | margin-top: 0; 1030 | } 1031 | 1032 | 1033 | @media screen and (max-width: 767px) { 1034 | div.toc { 1035 | float: none; 1036 | width: auto; 1037 | margin: 0 0 var(--spacing-medium) 0; 1038 | } 1039 | } 1040 | 1041 | /* 1042 | Code & Fragments 1043 | */ 1044 | 1045 | code, div.fragment, pre.fragment { 1046 | border-radius: var(--border-radius-small); 1047 | border: 1px solid var(--separator-color); 1048 | overflow: hidden; 1049 | } 1050 | 1051 | code { 1052 | display: inline; 1053 | background: var(--code-background); 1054 | color: var(--code-foreground); 1055 | padding: 2px 6px; 1056 | word-break: break-word; 1057 | } 1058 | 1059 | div.fragment, pre.fragment { 1060 | margin: var(--spacing-medium) 0; 1061 | padding: calc(var(--spacing-large) - (var(--spacing-large) / 6)) var(--spacing-large); 1062 | background: var(--fragment-background); 1063 | color: var(--fragment-foreground); 1064 | overflow-x: auto; 1065 | } 1066 | 1067 | @media screen and (max-width: 767px) { 1068 | div.fragment, pre.fragment { 1069 | border-top-right-radius: 0; 1070 | border-bottom-right-radius: 0; 1071 | border-right: 0; 1072 | } 1073 | 1074 | .contents > div.fragment, 1075 | .textblock > div.fragment, 1076 | .textblock > pre.fragment, 1077 | .contents > .doxygen-awesome-fragment-wrapper > div.fragment, 1078 | .textblock > .doxygen-awesome-fragment-wrapper > div.fragment, 1079 | .textblock > .doxygen-awesome-fragment-wrapper > pre.fragment { 1080 | margin: var(--spacing-medium) calc(0px - var(--spacing-large)); 1081 | border-radius: 0; 1082 | border-left: 0; 1083 | } 1084 | 1085 | .textblock li > .fragment, 1086 | .textblock li > .doxygen-awesome-fragment-wrapper > .fragment { 1087 | margin: var(--spacing-medium) calc(0px - var(--spacing-large)); 1088 | } 1089 | 1090 | .memdoc li > .fragment, 1091 | .memdoc li > .doxygen-awesome-fragment-wrapper > .fragment { 1092 | margin: var(--spacing-medium) calc(0px - var(--spacing-medium)); 1093 | } 1094 | 1095 | .textblock ul, .memdoc ul { 1096 | overflow: initial; 1097 | } 1098 | 1099 | .memdoc > div.fragment, 1100 | .memdoc > pre.fragment, 1101 | dl dd > div.fragment, 1102 | dl dd pre.fragment, 1103 | .memdoc > .doxygen-awesome-fragment-wrapper > div.fragment, 1104 | .memdoc > .doxygen-awesome-fragment-wrapper > pre.fragment, 1105 | dl dd > .doxygen-awesome-fragment-wrapper > div.fragment, 1106 | dl dd .doxygen-awesome-fragment-wrapper > pre.fragment { 1107 | margin: var(--spacing-medium) calc(0px - var(--spacing-medium)); 1108 | border-radius: 0; 1109 | border-left: 0; 1110 | } 1111 | } 1112 | 1113 | code, code a, pre.fragment, div.fragment, div.fragment .line, div.fragment span, div.fragment .line a, div.fragment .line span { 1114 | font-family: var(--font-family-monospace); 1115 | font-size: var(--code-font-size) !important; 1116 | } 1117 | 1118 | div.line:after { 1119 | margin-right: var(--spacing-medium); 1120 | } 1121 | 1122 | div.fragment .line, pre.fragment { 1123 | white-space: pre; 1124 | word-wrap: initial; 1125 | line-height: var(--fragment-lineheight); 1126 | } 1127 | 1128 | div.fragment span.keyword { 1129 | color: var(--fragment-keyword); 1130 | } 1131 | 1132 | div.fragment span.keywordtype { 1133 | color: var(--fragment-keywordtype); 1134 | } 1135 | 1136 | div.fragment span.keywordflow { 1137 | color: var(--fragment-keywordflow); 1138 | } 1139 | 1140 | div.fragment span.stringliteral { 1141 | color: var(--fragment-token) 1142 | } 1143 | 1144 | div.fragment span.comment { 1145 | color: var(--fragment-comment); 1146 | } 1147 | 1148 | div.fragment a.code { 1149 | color: var(--fragment-link) !important; 1150 | } 1151 | 1152 | div.fragment span.preprocessor { 1153 | color: var(--fragment-preprocessor); 1154 | } 1155 | 1156 | div.fragment span.lineno { 1157 | display: inline-block; 1158 | width: 27px; 1159 | border-right: none; 1160 | background: var(--fragment-linenumber-background); 1161 | color: var(--fragment-linenumber-color); 1162 | } 1163 | 1164 | div.fragment span.lineno a { 1165 | background: none; 1166 | color: var(--fragment-link) !important; 1167 | } 1168 | 1169 | div.fragment .line:first-child .lineno { 1170 | box-shadow: -999999px 0px 0 999999px var(--fragment-linenumber-background), -999998px 0px 0 999999px var(--fragment-linenumber-border); 1171 | } 1172 | 1173 | /* 1174 | dl warning, attention, note, deprecated, bug, ... 1175 | */ 1176 | 1177 | dl.bug dt a, dl.deprecated dt a, dl.todo dt a { 1178 | font-weight: bold !important; 1179 | } 1180 | 1181 | dl.warning, dl.attention, dl.note, dl.deprecated, dl.bug, dl.invariant, dl.pre, dl.todo, dl.remark { 1182 | padding: var(--spacing-medium); 1183 | margin: var(--spacing-medium) 0; 1184 | color: var(--page-background-color); 1185 | overflow: hidden; 1186 | margin-left: 0; 1187 | border-radius: var(--border-radius-small); 1188 | } 1189 | 1190 | dl.section dd { 1191 | margin-bottom: 2px; 1192 | } 1193 | 1194 | dl.warning, dl.attention { 1195 | background: var(--warning-color); 1196 | border-left: 8px solid var(--warning-color-dark); 1197 | color: var(--warning-color-darker); 1198 | } 1199 | 1200 | dl.warning dt, dl.attention dt { 1201 | color: var(--warning-color-dark); 1202 | } 1203 | 1204 | dl.note, dl.remark { 1205 | background: var(--note-color); 1206 | border-left: 8px solid var(--note-color-dark); 1207 | color: var(--note-color-darker); 1208 | } 1209 | 1210 | dl.note dt, dl.remark dt { 1211 | color: var(--note-color-dark); 1212 | } 1213 | 1214 | dl.todo { 1215 | background: var(--todo-color); 1216 | border-left: 8px solid var(--todo-color-dark); 1217 | color: var(--todo-color-darker); 1218 | } 1219 | 1220 | dl.todo dt { 1221 | color: var(--todo-color-dark); 1222 | } 1223 | 1224 | dl.bug dt a { 1225 | color: var(--todo-color-dark) !important; 1226 | } 1227 | 1228 | dl.bug { 1229 | background: var(--bug-color); 1230 | border-left: 8px solid var(--bug-color-dark); 1231 | color: var(--bug-color-darker); 1232 | } 1233 | 1234 | dl.bug dt a { 1235 | color: var(--bug-color-dark) !important; 1236 | } 1237 | 1238 | dl.deprecated { 1239 | background: var(--deprecated-color); 1240 | border-left: 8px solid var(--deprecated-color-dark); 1241 | color: var(--deprecated-color-darker); 1242 | } 1243 | 1244 | dl.deprecated dt a { 1245 | color: var(--deprecated-color-dark) !important; 1246 | } 1247 | 1248 | dl.section dd, dl.bug dd, dl.deprecated dd, dl.todo dd { 1249 | margin-inline-start: 0px; 1250 | } 1251 | 1252 | dl.invariant, dl.pre { 1253 | background: var(--invariant-color); 1254 | border-left: 8px solid var(--invariant-color-dark); 1255 | color: var(--invariant-color-darker); 1256 | } 1257 | 1258 | dl.invariant dt, dl.pre dt { 1259 | color: var(--invariant-color-dark); 1260 | } 1261 | 1262 | /* 1263 | memitem 1264 | */ 1265 | 1266 | div.memdoc, div.memproto, h2.memtitle { 1267 | box-shadow: none; 1268 | background-image: none; 1269 | border: none; 1270 | } 1271 | 1272 | div.memdoc { 1273 | padding: 0 var(--spacing-medium); 1274 | background: var(--page-background-color); 1275 | } 1276 | 1277 | h2.memtitle, div.memitem { 1278 | border: 1px solid var(--separator-color); 1279 | box-shadow: var(--box-shadow); 1280 | } 1281 | 1282 | h2.memtitle { 1283 | box-shadow: 0px var(--spacing-medium) 0 -1px var(--fragment-background), var(--box-shadow); 1284 | } 1285 | 1286 | div.memitem { 1287 | transition: none; 1288 | } 1289 | 1290 | div.memproto, h2.memtitle { 1291 | background: var(--fragment-background); 1292 | text-shadow: none; 1293 | } 1294 | 1295 | h2.memtitle { 1296 | font-weight: 500; 1297 | font-size: var(--memtitle-font-size); 1298 | font-family: var(--font-family-monospace); 1299 | border-bottom: none; 1300 | border-top-left-radius: var(--border-radius-medium); 1301 | border-top-right-radius: var(--border-radius-medium); 1302 | word-break: break-all; 1303 | position: relative; 1304 | } 1305 | 1306 | h2.memtitle:after { 1307 | content: ""; 1308 | display: block; 1309 | background: var(--fragment-background); 1310 | height: var(--spacing-medium); 1311 | bottom: calc(0px - var(--spacing-medium)); 1312 | left: 0; 1313 | right: -14px; 1314 | position: absolute; 1315 | border-top-right-radius: var(--border-radius-medium); 1316 | } 1317 | 1318 | h2.memtitle > span.permalink { 1319 | font-size: inherit; 1320 | } 1321 | 1322 | h2.memtitle > span.permalink > a { 1323 | text-decoration: none; 1324 | padding-left: 3px; 1325 | margin-right: -4px; 1326 | user-select: none; 1327 | display: inline-block; 1328 | margin-top: -6px; 1329 | } 1330 | 1331 | h2.memtitle > span.permalink > a:hover { 1332 | color: var(--primary-dark-color) !important; 1333 | } 1334 | 1335 | a:target + h2.memtitle, a:target + h2.memtitle + div.memitem { 1336 | border-color: var(--primary-light-color); 1337 | } 1338 | 1339 | div.memitem { 1340 | border-top-right-radius: var(--border-radius-medium); 1341 | border-bottom-right-radius: var(--border-radius-medium); 1342 | border-bottom-left-radius: var(--border-radius-medium); 1343 | overflow: hidden; 1344 | display: block !important; 1345 | } 1346 | 1347 | div.memdoc { 1348 | border-radius: 0; 1349 | } 1350 | 1351 | div.memproto { 1352 | border-radius: 0 var(--border-radius-small) 0 0; 1353 | overflow: auto; 1354 | border-bottom: 1px solid var(--separator-color); 1355 | padding: var(--spacing-medium); 1356 | margin-bottom: -1px; 1357 | } 1358 | 1359 | div.memtitle { 1360 | border-top-right-radius: var(--border-radius-medium); 1361 | border-top-left-radius: var(--border-radius-medium); 1362 | } 1363 | 1364 | div.memproto table.memname { 1365 | font-family: var(--font-family-monospace); 1366 | color: var(--page-foreground-color); 1367 | font-size: var(--memname-font-size); 1368 | } 1369 | 1370 | div.memproto div.memtemplate { 1371 | font-family: var(--font-family-monospace); 1372 | color: var(--primary-dark-color); 1373 | font-size: var(--memname-font-size); 1374 | margin-left: 2px; 1375 | } 1376 | 1377 | table.mlabels, table.mlabels > tbody { 1378 | display: block; 1379 | } 1380 | 1381 | td.mlabels-left { 1382 | width: auto; 1383 | } 1384 | 1385 | td.mlabels-right { 1386 | margin-top: 3px; 1387 | position: sticky; 1388 | left: 0; 1389 | } 1390 | 1391 | table.mlabels > tbody > tr:first-child { 1392 | display: flex; 1393 | justify-content: space-between; 1394 | flex-wrap: wrap; 1395 | } 1396 | 1397 | .memname, .memitem span.mlabels { 1398 | margin: 0 1399 | } 1400 | 1401 | /* 1402 | reflist 1403 | */ 1404 | 1405 | dl.reflist { 1406 | box-shadow: var(--box-shadow); 1407 | border-radius: var(--border-radius-medium); 1408 | border: 1px solid var(--separator-color); 1409 | overflow: hidden; 1410 | padding: 0; 1411 | } 1412 | 1413 | 1414 | dl.reflist dt, dl.reflist dd { 1415 | box-shadow: none; 1416 | text-shadow: none; 1417 | background-image: none; 1418 | border: none; 1419 | padding: 12px; 1420 | } 1421 | 1422 | 1423 | dl.reflist dt { 1424 | font-weight: 500; 1425 | border-radius: 0; 1426 | background: var(--code-background); 1427 | border-bottom: 1px solid var(--separator-color); 1428 | color: var(--page-foreground-color) 1429 | } 1430 | 1431 | 1432 | dl.reflist dd { 1433 | background: none; 1434 | } 1435 | 1436 | /* 1437 | Table 1438 | */ 1439 | 1440 | .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) { 1441 | display: inline-block; 1442 | max-width: 100%; 1443 | } 1444 | 1445 | .contents > table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex) { 1446 | margin-left: calc(0px - var(--spacing-large)); 1447 | margin-right: calc(0px - var(--spacing-large)); 1448 | max-width: calc(100% + 2 * var(--spacing-large)); 1449 | } 1450 | 1451 | table.markdownTable, table.fieldtable { 1452 | border: none; 1453 | margin: var(--spacing-medium) 0; 1454 | box-shadow: 0 0 0 1px var(--separator-color); 1455 | border-radius: var(--border-radius-small); 1456 | } 1457 | 1458 | table.fieldtable { 1459 | width: 100%; 1460 | } 1461 | 1462 | th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone { 1463 | background: var(--tablehead-background); 1464 | color: var(--tablehead-foreground); 1465 | font-weight: 600; 1466 | font-size: var(--page-font-size); 1467 | } 1468 | 1469 | th.markdownTableHeadLeft:first-child, th.markdownTableHeadRight:first-child, th.markdownTableHeadCenter:first-child, th.markdownTableHeadNone:first-child { 1470 | border-top-left-radius: var(--border-radius-small); 1471 | } 1472 | 1473 | th.markdownTableHeadLeft:last-child, th.markdownTableHeadRight:last-child, th.markdownTableHeadCenter:last-child, th.markdownTableHeadNone:last-child { 1474 | border-top-right-radius: var(--border-radius-small); 1475 | } 1476 | 1477 | table.markdownTable td, table.markdownTable th, table.fieldtable dt { 1478 | border: none; 1479 | border-right: 1px solid var(--separator-color); 1480 | padding: var(--spacing-small) var(--spacing-medium); 1481 | } 1482 | 1483 | table.markdownTable td:last-child, table.markdownTable th:last-child, table.fieldtable dt:last-child { 1484 | border: none; 1485 | } 1486 | 1487 | table.markdownTable tr, table.markdownTable tr { 1488 | border-bottom: 1px solid var(--separator-color); 1489 | } 1490 | 1491 | table.markdownTable tr:last-child, table.markdownTable tr:last-child { 1492 | border-bottom: none; 1493 | } 1494 | 1495 | table.fieldtable th { 1496 | font-size: var(--page-font-size); 1497 | font-weight: 600; 1498 | background-image: none; 1499 | background-color: var(--tablehead-background); 1500 | color: var(--tablehead-foreground); 1501 | border-bottom: 1px solid var(--separator-color); 1502 | } 1503 | 1504 | .fieldtable td.fieldtype, .fieldtable td.fieldname { 1505 | border-bottom: 1px solid var(--separator-color); 1506 | border-right: 1px solid var(--separator-color); 1507 | } 1508 | 1509 | .fieldtable td.fielddoc { 1510 | border-bottom: 1px solid var(--separator-color); 1511 | } 1512 | 1513 | .memberdecls td.glow, .fieldtable tr.glow { 1514 | background-color: var(--primary-light-color); 1515 | box-shadow: 0 0 15px var(--primary-light-color); 1516 | } 1517 | 1518 | table.memberdecls { 1519 | display: block; 1520 | } 1521 | 1522 | table.memberdecls tr[class^='memitem'] { 1523 | font-family: var(--font-family-monospace); 1524 | font-size: var(--code-font-size); 1525 | } 1526 | 1527 | table.memberdecls tr[class^='memitem'] .memTemplParams { 1528 | font-family: var(--font-family-monospace); 1529 | font-size: var(--code-font-size); 1530 | color: var(--primary-dark-color); 1531 | } 1532 | 1533 | table.memberdecls .memItemLeft, 1534 | table.memberdecls .memItemRight, 1535 | table.memberdecls .memTemplItemLeft, 1536 | table.memberdecls .memTemplItemRight, 1537 | table.memberdecls .memTemplParams { 1538 | transition: none; 1539 | padding-top: var(--spacing-small); 1540 | padding-bottom: var(--spacing-small); 1541 | border-top: 1px solid var(--separator-color); 1542 | border-bottom: 1px solid var(--separator-color); 1543 | background-color: var(--fragment-background); 1544 | } 1545 | 1546 | table.memberdecls .memTemplItemLeft, 1547 | table.memberdecls .memTemplItemRight { 1548 | padding-top: 2px; 1549 | } 1550 | 1551 | table.memberdecls .memTemplParams { 1552 | border-bottom: 0; 1553 | border-left: 1px solid var(--separator-color); 1554 | border-right: 1px solid var(--separator-color); 1555 | border-radius: var(--border-radius-small) var(--border-radius-small) 0 0; 1556 | padding-bottom: 0; 1557 | } 1558 | 1559 | table.memberdecls .memTemplItemLeft { 1560 | border-radius: 0 0 0 var(--border-radius-small); 1561 | border-left: 1px solid var(--separator-color); 1562 | border-top: 0; 1563 | } 1564 | 1565 | table.memberdecls .memTemplItemRight { 1566 | border-radius: 0 0 var(--border-radius-small) 0; 1567 | border-right: 1px solid var(--separator-color); 1568 | border-top: 0; 1569 | } 1570 | 1571 | table.memberdecls .memItemLeft { 1572 | border-radius: var(--border-radius-small) 0 0 var(--border-radius-small); 1573 | border-left: 1px solid var(--separator-color); 1574 | padding-left: var(--spacing-medium); 1575 | padding-right: 0; 1576 | } 1577 | 1578 | table.memberdecls .memItemRight { 1579 | border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0; 1580 | border-right: 1px solid var(--separator-color); 1581 | padding-right: var(--spacing-medium); 1582 | padding-left: 0; 1583 | 1584 | } 1585 | 1586 | table.memberdecls .mdescLeft, table.memberdecls .mdescRight { 1587 | background: none; 1588 | color: var(--page-foreground-color); 1589 | padding: var(--spacing-small) 0; 1590 | } 1591 | 1592 | table.memberdecls .memSeparator { 1593 | background: var(--page-background-color); 1594 | height: var(--spacing-large); 1595 | border: 0; 1596 | transition: none; 1597 | } 1598 | 1599 | table.memberdecls .groupheader { 1600 | margin-bottom: var(--spacing-large); 1601 | } 1602 | 1603 | table.memberdecls .inherit_header td { 1604 | padding: 0 0 var(--spacing-medium) 0; 1605 | text-indent: -12px; 1606 | line-height: 1.5em; 1607 | color: var(--page-secondary-foreground-color); 1608 | } 1609 | 1610 | @media screen and (max-width: 767px) { 1611 | 1612 | table.memberdecls .memItemLeft, 1613 | table.memberdecls .memItemRight, 1614 | table.memberdecls .mdescLeft, 1615 | table.memberdecls .mdescRight, 1616 | table.memberdecls .memTemplItemLeft, 1617 | table.memberdecls .memTemplItemRight, 1618 | table.memberdecls .memTemplParams { 1619 | display: block; 1620 | text-align: left; 1621 | padding-left: var(--spacing-large); 1622 | margin: 0 calc(0px - var(--spacing-large)) 0 calc(0px - var(--spacing-large)); 1623 | border-right: none; 1624 | border-left: none; 1625 | border-radius: 0; 1626 | } 1627 | 1628 | table.memberdecls .memItemLeft, 1629 | table.memberdecls .mdescLeft, 1630 | table.memberdecls .memTemplItemLeft { 1631 | border-bottom: 0; 1632 | padding-bottom: 0; 1633 | } 1634 | 1635 | table.memberdecls .memTemplItemLeft { 1636 | padding-top: 0; 1637 | } 1638 | 1639 | table.memberdecls .mdescLeft { 1640 | margin-top: calc(0px - var(--page-font-size)); 1641 | } 1642 | 1643 | table.memberdecls .memItemRight, 1644 | table.memberdecls .mdescRight, 1645 | table.memberdecls .memTemplItemRight { 1646 | border-top: 0; 1647 | padding-top: 0; 1648 | padding-right: var(--spacing-large); 1649 | overflow-x: auto; 1650 | } 1651 | 1652 | table.memberdecls tr[class^='memitem']:not(.inherit) { 1653 | display: block; 1654 | width: calc(100vw - 2 * var(--spacing-large)); 1655 | } 1656 | 1657 | table.memberdecls .mdescRight { 1658 | color: var(--page-foreground-color); 1659 | } 1660 | 1661 | table.memberdecls tr.inherit { 1662 | visibility: hidden; 1663 | } 1664 | 1665 | table.memberdecls tr[style="display: table-row;"] { 1666 | display: block !important; 1667 | visibility: visible; 1668 | width: calc(100vw - 2 * var(--spacing-large)); 1669 | animation: fade .5s; 1670 | } 1671 | 1672 | @keyframes fade { 1673 | 0% { 1674 | opacity: 0; 1675 | max-height: 0; 1676 | } 1677 | 1678 | 100% { 1679 | opacity: 1; 1680 | max-height: 200px; 1681 | } 1682 | } 1683 | } 1684 | 1685 | 1686 | /* 1687 | Horizontal Rule 1688 | */ 1689 | 1690 | hr { 1691 | margin-top: var(--spacing-large); 1692 | margin-bottom: var(--spacing-large); 1693 | height: 1px; 1694 | background-color: var(--separator-color); 1695 | border: 0; 1696 | } 1697 | 1698 | .contents hr { 1699 | box-shadow: 100px 0 0 var(--separator-color), 1700 | -100px 0 0 var(--separator-color), 1701 | 500px 0 0 var(--separator-color), 1702 | -500px 0 0 var(--separator-color), 1703 | 1500px 0 0 var(--separator-color), 1704 | -1500px 0 0 var(--separator-color), 1705 | 2000px 0 0 var(--separator-color), 1706 | -2000px 0 0 var(--separator-color); 1707 | } 1708 | 1709 | .contents img, .contents .center, .contents center, .contents div.image object { 1710 | max-width: 100%; 1711 | overflow: auto; 1712 | } 1713 | 1714 | @media screen and (max-width: 767px) { 1715 | .contents .dyncontent > .center, .contents > center { 1716 | margin-left: calc(0px - var(--spacing-large)); 1717 | margin-right: calc(0px - var(--spacing-large)); 1718 | max-width: calc(100% + 2 * var(--spacing-large)); 1719 | } 1720 | } 1721 | 1722 | /* 1723 | Directories 1724 | */ 1725 | div.directory { 1726 | border-top: 1px solid var(--separator-color); 1727 | border-bottom: 1px solid var(--separator-color); 1728 | width: auto; 1729 | } 1730 | 1731 | table.directory { 1732 | font-family: var(--font-family); 1733 | font-size: var(--page-font-size); 1734 | font-weight: normal; 1735 | width: 100%; 1736 | } 1737 | 1738 | table.directory td.entry { 1739 | padding: var(--spacing-small); 1740 | } 1741 | 1742 | table.directory td.desc { 1743 | min-width: 250px; 1744 | } 1745 | 1746 | table.directory tr.even { 1747 | background-color: var(--odd-color); 1748 | } 1749 | 1750 | .icona { 1751 | width: auto; 1752 | height: auto; 1753 | margin: 0 var(--spacing-small); 1754 | } 1755 | 1756 | .icon { 1757 | background: var(--primary-color); 1758 | width: 18px; 1759 | height: 18px; 1760 | line-height: 18px; 1761 | } 1762 | 1763 | .iconfopen, .icondoc, .iconfclosed { 1764 | background-position: center; 1765 | margin-bottom: 0; 1766 | } 1767 | 1768 | .icondoc { 1769 | filter: saturate(0.2); 1770 | } 1771 | 1772 | @media screen and (max-width: 767px) { 1773 | div.directory { 1774 | margin-left: calc(0px - var(--spacing-large)); 1775 | margin-right: calc(0px - var(--spacing-large)); 1776 | } 1777 | } 1778 | 1779 | @media (prefers-color-scheme: dark) { 1780 | html:not(.light-mode) .iconfopen, html:not(.light-mode) .iconfclosed { 1781 | filter: hue-rotate(180deg) invert(); 1782 | } 1783 | } 1784 | 1785 | html.dark-mode .iconfopen, html.dark-mode .iconfclosed { 1786 | filter: hue-rotate(180deg) invert(); 1787 | } 1788 | 1789 | /* 1790 | Class list 1791 | */ 1792 | 1793 | .classindex dl.odd { 1794 | background: var(--odd-color); 1795 | border-radius: var(--border-radius-small); 1796 | } 1797 | 1798 | /* 1799 | Class Index Doxygen 1.8 1800 | */ 1801 | 1802 | table.classindex { 1803 | margin-left: 0; 1804 | margin-right: 0; 1805 | width: 100%; 1806 | } 1807 | 1808 | table.classindex table div.ah { 1809 | background-image: none; 1810 | background-color: initial; 1811 | border-color: var(--separator-color); 1812 | color: var(--page-foreground-color); 1813 | box-shadow: var(--box-shadow); 1814 | border-radius: var(--border-radius-large); 1815 | padding: var(--spacing-small); 1816 | } 1817 | 1818 | div.qindex { 1819 | background-color: var(--odd-color); 1820 | border-radius: var(--border-radius-small); 1821 | border: 1px solid var(--separator-color); 1822 | padding: var(--spacing-small) 0; 1823 | } 1824 | 1825 | /* 1826 | Footer and nav-path 1827 | */ 1828 | 1829 | #nav-path { 1830 | width: 100%; 1831 | } 1832 | 1833 | #nav-path ul { 1834 | background-image: none; 1835 | background: var(--page-background-color); 1836 | border: none; 1837 | border-top: 1px solid var(--separator-color); 1838 | border-bottom: 1px solid var(--separator-color); 1839 | border-bottom: 0; 1840 | box-shadow: 0 0.75px 0 var(--separator-color); 1841 | font-size: var(--navigation-font-size); 1842 | } 1843 | 1844 | img.footer { 1845 | width: 60px; 1846 | } 1847 | 1848 | .navpath li.footer { 1849 | color: var(--page-secondary-foreground-color); 1850 | } 1851 | 1852 | address.footer { 1853 | color: var(--page-secondary-foreground-color); 1854 | margin-bottom: var(--spacing-large); 1855 | } 1856 | 1857 | #nav-path li.navelem { 1858 | background-image: none; 1859 | display: flex; 1860 | align-items: center; 1861 | } 1862 | 1863 | .navpath li.navelem a { 1864 | text-shadow: none; 1865 | display: inline-block; 1866 | color: var(--primary-color) !important; 1867 | } 1868 | 1869 | .navpath li.navelem b { 1870 | color: var(--primary-dark-color); 1871 | font-weight: 500; 1872 | } 1873 | 1874 | li.navelem { 1875 | padding: 0; 1876 | margin-left: -8px; 1877 | } 1878 | 1879 | li.navelem:first-child { 1880 | margin-left: var(--spacing-large); 1881 | } 1882 | 1883 | li.navelem:first-child:before { 1884 | display: none; 1885 | } 1886 | 1887 | #nav-path li.navelem:after { 1888 | content: ''; 1889 | border: 5px solid var(--page-background-color); 1890 | border-bottom-color: transparent; 1891 | border-right-color: transparent; 1892 | border-top-color: transparent; 1893 | transform: translateY(-1px) scaleY(4.2); 1894 | z-index: 10; 1895 | margin-left: 6px; 1896 | } 1897 | 1898 | #nav-path li.navelem:before { 1899 | content: ''; 1900 | border: 5px solid var(--separator-color); 1901 | border-bottom-color: transparent; 1902 | border-right-color: transparent; 1903 | border-top-color: transparent; 1904 | transform: translateY(-1px) scaleY(3.2); 1905 | margin-right: var(--spacing-small); 1906 | } 1907 | 1908 | .navpath li.navelem a:hover { 1909 | color: var(--primary-color); 1910 | } 1911 | 1912 | /* 1913 | Scrollbars for Webkit 1914 | */ 1915 | 1916 | #nav-tree::-webkit-scrollbar, 1917 | div.fragment::-webkit-scrollbar, 1918 | pre.fragment::-webkit-scrollbar, 1919 | div.memproto::-webkit-scrollbar, 1920 | .contents center::-webkit-scrollbar, 1921 | .contents .center::-webkit-scrollbar, 1922 | .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname)::-webkit-scrollbar { 1923 | width: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); 1924 | height: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); 1925 | } 1926 | 1927 | #nav-tree::-webkit-scrollbar-thumb, 1928 | div.fragment::-webkit-scrollbar-thumb, 1929 | pre.fragment::-webkit-scrollbar-thumb, 1930 | div.memproto::-webkit-scrollbar-thumb, 1931 | .contents center::-webkit-scrollbar-thumb, 1932 | .contents .center::-webkit-scrollbar-thumb, 1933 | .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname)::-webkit-scrollbar-thumb { 1934 | background-color: transparent; 1935 | border: var(--webkit-scrollbar-padding) solid transparent; 1936 | border-radius: calc(var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding)); 1937 | background-clip: padding-box; 1938 | } 1939 | 1940 | #nav-tree:hover::-webkit-scrollbar-thumb, 1941 | div.fragment:hover::-webkit-scrollbar-thumb, 1942 | pre.fragment:hover::-webkit-scrollbar-thumb, 1943 | div.memproto:hover::-webkit-scrollbar-thumb, 1944 | .contents center:hover::-webkit-scrollbar-thumb, 1945 | .contents .center:hover::-webkit-scrollbar-thumb, 1946 | .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):hover::-webkit-scrollbar-thumb { 1947 | background-color: var(--webkit-scrollbar-color); 1948 | } 1949 | 1950 | #nav-tree::-webkit-scrollbar-track, 1951 | div.fragment::-webkit-scrollbar-track, 1952 | pre.fragment::-webkit-scrollbar-track, 1953 | div.memproto::-webkit-scrollbar-track, 1954 | .contents center::-webkit-scrollbar-track, 1955 | .contents .center::-webkit-scrollbar-track, 1956 | .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname)::-webkit-scrollbar-track { 1957 | background: transparent; 1958 | } 1959 | 1960 | #nav-tree::-webkit-scrollbar-corner { 1961 | background-color: var(--side-nav-background); 1962 | } 1963 | 1964 | #nav-tree, 1965 | div.fragment, 1966 | pre.fragment, 1967 | div.memproto, 1968 | .contents center, 1969 | .contents .center, 1970 | .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) { 1971 | overflow-x: auto; 1972 | overflow-x: overlay; 1973 | } 1974 | 1975 | /* 1976 | Scrollbars for Firefox 1977 | */ 1978 | 1979 | #nav-tree, 1980 | div.fragment, 1981 | pre.fragment, 1982 | div.memproto, 1983 | .contents center, 1984 | .contents .center, 1985 | .contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) { 1986 | scrollbar-width: thin; 1987 | } 1988 | 1989 | /* 1990 | Optional Dark mode toggle button 1991 | */ 1992 | 1993 | doxygen-awesome-dark-mode-toggle { 1994 | display: inline-block; 1995 | margin: 0 0 0 var(--spacing-small); 1996 | padding: 0; 1997 | width: var(--searchbar-height); 1998 | height: var(--searchbar-height); 1999 | background: none; 2000 | border: none; 2001 | border-radius: var(--searchbar-height); 2002 | vertical-align: middle; 2003 | text-align: center; 2004 | line-height: var(--searchbar-height); 2005 | font-size: 22px; 2006 | display: flex; 2007 | align-items: center; 2008 | justify-content: center; 2009 | user-select: none; 2010 | cursor: pointer; 2011 | } 2012 | 2013 | doxygen-awesome-dark-mode-toggle > svg { 2014 | transition: transform .1s ease-in-out; 2015 | } 2016 | 2017 | doxygen-awesome-dark-mode-toggle:active > svg { 2018 | transform: scale(.5); 2019 | } 2020 | 2021 | doxygen-awesome-dark-mode-toggle:hover { 2022 | background-color: rgba(0,0,0,.03); 2023 | } 2024 | 2025 | html.dark-mode doxygen-awesome-dark-mode-toggle:hover { 2026 | background-color: rgba(0,0,0,.18); 2027 | } 2028 | 2029 | /* 2030 | Optional fragment copy button 2031 | */ 2032 | .doxygen-awesome-fragment-wrapper { 2033 | position: relative; 2034 | } 2035 | 2036 | doxygen-awesome-fragment-copy-button { 2037 | opacity: 0; 2038 | background: var(--fragment-background); 2039 | width: 28px; 2040 | height: 28px; 2041 | position: absolute; 2042 | right: calc(var(--spacing-large) - (var(--spacing-large) / 2.5)); 2043 | top: calc(var(--spacing-large) - (var(--spacing-large) / 2.5)); 2044 | border: 1px solid var(--fragment-foreground); 2045 | cursor: pointer; 2046 | border-radius: var(--border-radius-small); 2047 | display: flex; 2048 | justify-content: center; 2049 | align-items: center; 2050 | } 2051 | 2052 | .doxygen-awesome-fragment-wrapper:hover doxygen-awesome-fragment-copy-button, doxygen-awesome-fragment-copy-button.success { 2053 | opacity: .28; 2054 | } 2055 | 2056 | doxygen-awesome-fragment-copy-button:hover, doxygen-awesome-fragment-copy-button.success { 2057 | opacity: 1 !important; 2058 | } 2059 | 2060 | doxygen-awesome-fragment-copy-button:active:not([class~=success]) svg { 2061 | transform: scale(.91); 2062 | } 2063 | 2064 | doxygen-awesome-fragment-copy-button svg { 2065 | fill: var(--fragment-foreground); 2066 | width: 18px; 2067 | height: 18px; 2068 | } 2069 | 2070 | doxygen-awesome-fragment-copy-button.success svg { 2071 | fill: rgb(14, 168, 14); 2072 | } 2073 | 2074 | doxygen-awesome-fragment-copy-button.success { 2075 | border-color: rgb(14, 168, 14); 2076 | } 2077 | 2078 | @media screen and (max-width: 767px) { 2079 | .textblock > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, 2080 | .textblock li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, 2081 | .memdoc li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, 2082 | .memdoc > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button, 2083 | dl dd > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button { 2084 | right: 0; 2085 | } 2086 | } 2087 | 2088 | /* 2089 | Optional paragraph link button 2090 | */ 2091 | 2092 | a.anchorlink { 2093 | font-size: 90%; 2094 | margin-left: var(--spacing-small); 2095 | color: var(--page-foreground-color) !important; 2096 | text-decoration: none; 2097 | opacity: .15; 2098 | display: none; 2099 | transition: opacity .1s ease-in-out, color .1s ease-in-out; 2100 | } 2101 | 2102 | a.anchorlink svg { 2103 | fill: var(--page-foreground-color); 2104 | } 2105 | 2106 | h3 a.anchorlink svg, h4 a.anchorlink svg { 2107 | margin-bottom: -3px; 2108 | margin-top: -4px; 2109 | } 2110 | 2111 | a.anchorlink:hover { 2112 | opacity: .45; 2113 | } 2114 | 2115 | h2:hover a.anchorlink, h1:hover a.anchorlink, h3:hover a.anchorlink, h4:hover a.anchorlink { 2116 | display: inline-block; 2117 | } 2118 | -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/doxygen-custom/custom-alternative.css: -------------------------------------------------------------------------------- 1 | html.alternative { 2 | /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */ 3 | --primary-color: #AF7FE4; 4 | --primary-dark-color: #9270E4; 5 | --primary-light-color: #7aabd6; 6 | --primary-lighter-color: #cae1f1; 7 | --primary-lightest-color: #e9f1f8; 8 | 9 | /* page base colors */ 10 | --page-background-color: white; 11 | --page-foreground-color: #2c3e50; 12 | --page-secondary-foreground-color: #67727e; 13 | 14 | 15 | --border-radius-large: 22px; 16 | --border-radius-small: 9px; 17 | --border-radius-medium: 14px; 18 | --spacing-small: 8px; 19 | --spacing-medium: 14px; 20 | --spacing-large: 19px; 21 | 22 | --top-height: 125px; 23 | 24 | --side-nav-background: #324067; 25 | --side-nav-foreground: #F1FDFF; 26 | --header-foreground: var(--side-nav-foreground); 27 | --searchbar-background: var(--side-nav-foreground); 28 | --searchbar-border-radius: var(--border-radius-medium); 29 | --header-background: var(--side-nav-background); 30 | --header-foreground: var(--side-nav-foreground); 31 | 32 | --toc-background: rgb(243, 240, 252); 33 | --toc-foreground: var(--page-foreground-color); 34 | } 35 | 36 | html.alternative.dark-mode { 37 | color-scheme: dark; 38 | 39 | --primary-color: #AF7FE4; 40 | --primary-dark-color: #9270E4; 41 | --primary-light-color: #4779ac; 42 | --primary-lighter-color: #191e21; 43 | --primary-lightest-color: #191a1c; 44 | 45 | --page-background-color: #1C1D1F; 46 | --page-foreground-color: #d2dbde; 47 | --page-secondary-foreground-color: #859399; 48 | --separator-color: #3a3246; 49 | --side-nav-background: #171D32; 50 | --side-nav-foreground: #F1FDFF; 51 | --toc-background: #20142C; 52 | --searchbar-background: var(--page-background-color); 53 | 54 | } -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/doxygen-custom/custom.css: -------------------------------------------------------------------------------- 1 | .github-corner svg { 2 | fill: var(--primary-light-color); 3 | color: var(--page-background-color); 4 | width: 72px; 5 | height: 72px; 6 | } 7 | 8 | @media screen and (max-width: 767px) { 9 | .github-corner svg { 10 | width: 50px; 11 | height: 50px; 12 | } 13 | #projectnumber { 14 | margin-right: 22px; 15 | } 16 | } 17 | 18 | .alter-theme-button { 19 | display: inline-block; 20 | cursor: pointer; 21 | background: var(--primary-color); 22 | color: var(--page-background-color) !important; 23 | border-radius: var(--border-radius-medium); 24 | padding: var(--spacing-small) var(--spacing-medium); 25 | text-decoration: none; 26 | } 27 | 28 | .next_section_button { 29 | display: block; 30 | padding: var(--spacing-large) 0 var(--spacing-small) 0; 31 | color: var(--page-background-color); 32 | user-select: none; 33 | } 34 | 35 | .next_section_button::after { 36 | /* clearfix */ 37 | content: ""; 38 | clear: both; 39 | display: table; 40 | } 41 | 42 | .next_section_button a { 43 | overflow: hidden; 44 | float: right; 45 | border: 1px solid var(--separator-color); 46 | padding: var(--spacing-medium) calc(var(--spacing-large) / 2) var(--spacing-medium) var(--spacing-large); 47 | border-radius: var(--border-radius-medium); 48 | color: var(--page-secondary-foreground-color) !important; 49 | text-decoration: none; 50 | background-color: var(--page-background-color); 51 | transition: color .08s ease-in-out, background-color .1s ease-in-out; 52 | } 53 | 54 | .next_section_button a:hover { 55 | color: var(--page-foreground-color) !important; 56 | background-color: var(--odd-color); 57 | } 58 | 59 | .next_section_button a::after { 60 | content: '〉'; 61 | color: var(--page-secondary-foreground-color) !important; 62 | padding-left: var(--spacing-large); 63 | display: inline-block; 64 | transition: color .08s ease-in-out, transform .09s ease-in-out; 65 | } 66 | 67 | .next_section_button a:hover::after { 68 | color: var(--page-foreground-color) !important; 69 | transform: translateX(3px); 70 | } 71 | 72 | .alter-theme-button:hover { 73 | background: var(--primary-dark-color); 74 | } 75 | 76 | html.dark-mode #variants_image img { 77 | filter: brightness(87%) hue-rotate(180deg) invert(); 78 | } -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/doxygen-custom/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | $projectname: $title 23 | $title 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 37 | $treeview 38 | $search 39 | $mathjax 40 | 41 | $extrastylesheet 42 | 43 | 44 | 45 | 46 | 47 | 49 | 50 | 51 |
52 | 53 | 54 |
55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 68 | 69 | 70 | 71 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 |
63 |
$projectname 64 |  $projectnumber 65 |
66 |
$projectbrief
67 |
72 |
$projectbrief
73 |
$searchbox
84 |
85 | 86 | 87 | -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/doxygen-custom/toggle-alternative-theme.js: -------------------------------------------------------------------------------- 1 | 2 | let original_theme_active = true; 3 | 4 | function toggle_alternative_theme() { 5 | if(original_theme_active) { 6 | document.documentElement.classList.add("alternative") 7 | original_theme_active = false; 8 | } else { 9 | document.documentElement.classList.remove("alternative") 10 | original_theme_active = true; 11 | } 12 | } -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/img/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpewsey/HexagonalUI/c99404ac0f23f91a6d2cd582c3e722f9e9eefb95/Docs~/doxygen-awesome-css/img/screenshot.png -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/img/theme-variants.drawio.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |
10 |
11 | 1. Base Theme 12 |
13 |
14 |
15 |
16 | 17 | 1. Base Theme 18 | 19 |
20 |
21 | 22 | 23 | 24 | 25 |
26 |
27 |
28 | 2. Sidebar-Only Theme 29 |
30 |
31 |
32 |
33 | 34 | 2. Sidebar-Only Theme 35 | 36 |
37 |
38 | 39 | 40 | 41 | 42 | 43 |
44 |
45 |
46 | Content 47 |
48 |
49 |
50 |
51 | 52 | Content 53 | 54 |
55 |
56 | 57 | 58 | 59 | 60 |
61 |
62 |
63 | Sidebar 64 |
65 | (Title + Navigation) 66 |
67 |
68 |
69 |
70 | 71 | Sidebar... 72 | 73 |
74 |
75 | 76 | 77 | 78 | 79 |
80 |
81 |
82 | Footer (Breadcrumps) 83 |
84 |
85 |
86 |
87 | 88 | Footer (Breadcrumps) 89 | 90 |
91 |
92 | 93 | 94 | 95 | 96 |
97 |
98 |
99 | Search 100 |
101 |
102 |
103 |
104 | 105 | Search 106 | 107 |
108 |
109 | 110 | 111 | 112 |
113 |
114 |
115 | 116 | Title 117 | 118 |
119 |
120 |
121 |
122 | 123 | Tit... 124 | 125 |
126 |
127 | 128 | 129 | 130 | 131 | 132 |
133 |
134 |
135 | Content 136 |
137 |
138 |
139 |
140 | 141 | Content 142 | 143 |
144 |
145 | 146 | 147 | 148 | 149 |
150 |
151 |
152 | Titlebar (Navigation + Search) 153 |
154 |
155 |
156 |
157 | 158 | Titlebar (Navigation + Search) 159 | 160 |
161 |
162 | 163 | 164 | 165 | 166 |
167 |
168 |
169 | Sidebar (Navigation) 170 |
171 |
172 |
173 |
174 | 175 | Sidebar (Navigation) 176 | 177 |
178 |
179 | 180 | 181 | 182 | 183 |
184 |
185 |
186 | Footer (Breadcrumps) 187 |
188 |
189 |
190 |
191 | 192 | Footer (Breadcrumps) 193 | 194 |
195 |
196 | 197 | 198 | 199 | 200 |
201 |
202 |
203 | Search 204 |
205 |
206 |
207 |
208 | 209 | Search 210 | 211 |
212 |
213 | 214 | 215 | 216 |
217 |
218 |
219 | 220 | Title 221 | 222 |
223 |
224 |
225 |
226 | 227 | Tit... 228 | 229 |
230 |
231 |
232 | 233 | 234 | 235 | 236 | Viewer does not support full SVG 1.1 237 | 238 | 239 | 240 |
-------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/include/MyLibrary/example.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace MyLibrary { 5 | 6 | enum Color { red, green, blue }; 7 | 8 | /** 9 | * @brief Example class to demonstrate the features of the custom CSS. 10 | * 11 | * @author jothepro 12 | * 13 | */ 14 | class Example { 15 | public: 16 | /** 17 | * @brief brief summary 18 | * 19 | * doxygen test documentation 20 | * 21 | * @param test this is the only parameter of this test function. It does nothing! 22 | * 23 | * # Supported elements 24 | * 25 | * These elements have been tested with the custom CSS. 26 | * 27 | * ## Tables 28 | * 29 | * The table content is scrollable if the table gets too wide. 30 | * 31 | * | first_column | second_column | third_column | fourth_column | fifth_column | sixth_column | seventh_column | eighth_column | ninth_column | 32 | * |--------------|---------------|--------------|---------------|--------------|--------------|----------------|---------------|--------------| 33 | * | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 34 | * 35 | * 36 | * ## Lists 37 | * 38 | * - element 1 39 | * - element 2 40 | * 41 | * 1. element 1 42 | * ``` 43 | * code in lists 44 | * ``` 45 | * 2. element 2 46 | * 47 | * ## Quotes 48 | * 49 | * > Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt 50 | * > ut labore et dolore magna aliqua. Vitae proin sagittis nisl rhoncus mattis rhoncus urna neque viverra. 51 | * > Velit sed ullamcorper morbi tincidunt ornare. 52 | * > 53 | * > Lorem ipsum dolor sit amet consectetur adipiscing elit duis. 54 | * *- jothepro* 55 | * 56 | * ## Code block 57 | * 58 | * ```cpp 59 | * auto x = "code within md fences (```)"; 60 | * ``` 61 | * 62 | * @code{.cpp} 63 | * // code within @code block 64 | * while(true) { 65 | * auto example = std::make_shared(5); 66 | * example->test("test"); 67 | * } 68 | * 69 | * @endcode 70 | * 71 | * // code within indented code block 72 | * auto test = std::shared_ptr 3 | #include "example.hpp" 4 | #include 5 | 6 | namespace MyLibrary { 7 | 8 | /** 9 | * @brief some subclass 10 | */ 11 | class SubclassExample : public Example { 12 | public: 13 | 14 | /** 15 | * @bug second bug 16 | * @return 17 | */ 18 | int virtualfunc() override; 19 | 20 | /** 21 | * @brief Extra long function with lots of parameters 22 | * @param param1 first parameter 23 | * @param param2 second parameter 24 | * @param parameter3 third parameter 25 | */ 26 | template 27 | std::shared_ptr long_function_with_many_parameters(std::shared_ptr& param1, std::shared_ptr& param2, bool parameter3) { 28 | if(true) { 29 | std::cout << "this even has some code." << std::endl; 30 | } 31 | } 32 | 33 | }; 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /Docs~/doxygen-awesome-css/logo.drawio.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Docs~/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpewsey/HexagonalUI/c99404ac0f23f91a6d2cd582c3e722f9e9eefb95/Docs~/favicon-16x16.png -------------------------------------------------------------------------------- /Docs~/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpewsey/HexagonalUI/c99404ac0f23f91a6d2cd582c3e722f9e9eefb95/Docs~/favicon-32x32.png -------------------------------------------------------------------------------- /Docs~/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpewsey/HexagonalUI/c99404ac0f23f91a6d2cd582c3e722f9e9eefb95/Docs~/favicon.ico -------------------------------------------------------------------------------- /Docs~/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | $projectname: $title 17 | $title 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | $treeview 27 | $search 28 | $mathjax 29 | 30 | $extrastylesheet 31 | 32 | 33 | 34 | 37 | 38 | 39 | 40 | 41 | 42 |
43 | 44 | 45 | 46 |
47 | 48 | 49 |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 62 | 63 | 64 | 65 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 |
58 |
$projectname $projectnumber 59 |
60 |
$projectbrief
61 |
66 |
$projectbrief
67 |
$searchbox
$searchbox
85 |
86 | 87 | 88 | -------------------------------------------------------------------------------- /Docs~/site.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020, Matt Pewsey 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e58cf9dd61e024c2bb4e02e9fc10fb6e 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HexagonalUI 2 | 3 | [![Docs](https://github.com/mpewsey/HexagonalUI/workflows/Docs/badge.svg?event=push)](https://mpewsey.github.io/HexagonalUI) 4 | 5 | ## Purpose 6 | 7 | Unity currently does not offer a built-in layout group for creating stackings of hexagonal elements, such as those sometimes used for skill grids. This package aims to fill that gap by providing a hexagonal layout group that will page UI elements into a grid. 8 | 9 | ![HexLayoutGroup](https://user-images.githubusercontent.com/23442063/163601049-a1522652-6063-4976-ae87-35b92b21187e.png) 10 | 11 | ## Installation 12 | 13 | In Unity, select `Window > Package Manager`. 14 | 15 | ![HexagonalUI](https://user-images.githubusercontent.com/23442063/163601100-191d8699-f4fd-42cc-96d4-f6aa5a8ae29b.png) 16 | 17 | Select `Add package from git URL...` and paste the following URL: 18 | 19 | ``` 20 | https://github.com/mpewsey/HexagonalUI.git 21 | ``` 22 | 23 | To lock into a specific version, append `#{VERSION_TAG}` to the end of the URL. For example: 24 | 25 | ``` 26 | https://github.com/mpewsey/HexagonalUI.git#v1.3.1 27 | ``` 28 | 29 | ## Usage 30 | 31 | To use, simply attach the `HexLayoutGroup` component to a Game Object, as you would with Unity's built-in layout group components. The cell orientation component setting is based on the direction of the hexagonal element's long diagonal. In the image above, the hexagons on the top feature a horizontal cell orientation, whereas the hexagons on the bottom feature a vertical orientation. 32 | 33 | Due to the staggering of the hexagonal elements, the default `Button` component input navigation tends to navigate randomly. Therefore, if buttons will serve as the children of the layout group, it is recommended that the `HexButton` component, which provides more regular navigation behaviour, be used instead. 34 | 35 | ## Tile Art Creation Guidance 36 | 37 | To match the dimensions assigned by the hexagonal layout group, it is recommended that hexagonal tile art have their long diagonals to short diagonals proportioned to 1 : 0.86602540378. For instance, the example tile images in this package are 100 px by 87 px, including the required rounding to the nearest pixel. 38 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3288ca16c42494a82a9acfb4141c9684 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Samples~/Prefabs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7008eef9316024460acce7df2e4704c8 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/Prefabs/HexButton_Horizontal.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1 &1414110579747643580 4 | GameObject: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | serializedVersion: 6 10 | m_Component: 11 | - component: {fileID: 9179871002707573841} 12 | - component: {fileID: 1893308076118620010} 13 | m_Layer: 5 14 | m_Name: HexButton_Horizontal 15 | m_TagString: Untagged 16 | m_Icon: {fileID: 0} 17 | m_NavMeshLayer: 0 18 | m_StaticEditorFlags: 0 19 | m_IsActive: 1 20 | --- !u!224 &9179871002707573841 21 | RectTransform: 22 | m_ObjectHideFlags: 0 23 | m_CorrespondingSourceObject: {fileID: 0} 24 | m_PrefabInstance: {fileID: 0} 25 | m_PrefabAsset: {fileID: 0} 26 | m_GameObject: {fileID: 1414110579747643580} 27 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 28 | m_LocalPosition: {x: 0, y: 0, z: 0} 29 | m_LocalScale: {x: 1, y: 1, z: 1} 30 | m_Children: 31 | - {fileID: 6686599077041454343} 32 | m_Father: {fileID: 0} 33 | m_RootOrder: 0 34 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 35 | m_AnchorMin: {x: 0.5, y: 0.5} 36 | m_AnchorMax: {x: 0.5, y: 0.5} 37 | m_AnchoredPosition: {x: 0, y: 0} 38 | m_SizeDelta: {x: 100, y: 86.6} 39 | m_Pivot: {x: 0.5, y: 0.5} 40 | --- !u!114 &1893308076118620010 41 | MonoBehaviour: 42 | m_ObjectHideFlags: 0 43 | m_CorrespondingSourceObject: {fileID: 0} 44 | m_PrefabInstance: {fileID: 0} 45 | m_PrefabAsset: {fileID: 0} 46 | m_GameObject: {fileID: 1414110579747643580} 47 | m_Enabled: 1 48 | m_EditorHideFlags: 0 49 | m_Script: {fileID: 11500000, guid: 8b95c1f04db9249c68fe7f31e9ec5b97, type: 3} 50 | m_Name: 51 | m_EditorClassIdentifier: 52 | m_Navigation: 53 | m_Mode: 3 54 | m_SelectOnUp: {fileID: 0} 55 | m_SelectOnDown: {fileID: 0} 56 | m_SelectOnLeft: {fileID: 0} 57 | m_SelectOnRight: {fileID: 0} 58 | m_Transition: 1 59 | m_Colors: 60 | m_NormalColor: {r: 1, g: 1, b: 1, a: 1} 61 | m_HighlightedColor: {r: 0, g: 0.6422635, b: 0.7924528, a: 1} 62 | m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1} 63 | m_SelectedColor: {r: 0, g: 0.754717, b: 0.31667313, a: 1} 64 | m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} 65 | m_ColorMultiplier: 1 66 | m_FadeDuration: 0.1 67 | m_SpriteState: 68 | m_HighlightedSprite: {fileID: 0} 69 | m_PressedSprite: {fileID: 0} 70 | m_SelectedSprite: {fileID: 0} 71 | m_DisabledSprite: {fileID: 0} 72 | m_AnimationTriggers: 73 | m_NormalTrigger: Normal 74 | m_HighlightedTrigger: Highlighted 75 | m_PressedTrigger: Pressed 76 | m_SelectedTrigger: Selected 77 | m_DisabledTrigger: Disabled 78 | m_Interactable: 1 79 | m_TargetGraphic: {fileID: 6300994564907357248} 80 | m_OnClick: 81 | m_PersistentCalls: 82 | m_Calls: [] 83 | --- !u!1 &3245847638180075902 84 | GameObject: 85 | m_ObjectHideFlags: 0 86 | m_CorrespondingSourceObject: {fileID: 0} 87 | m_PrefabInstance: {fileID: 0} 88 | m_PrefabAsset: {fileID: 0} 89 | serializedVersion: 6 90 | m_Component: 91 | - component: {fileID: 6686599077041454343} 92 | - component: {fileID: 572344923113193797} 93 | - component: {fileID: 6300994564907357248} 94 | m_Layer: 5 95 | m_Name: Image 96 | m_TagString: Untagged 97 | m_Icon: {fileID: 0} 98 | m_NavMeshLayer: 0 99 | m_StaticEditorFlags: 0 100 | m_IsActive: 1 101 | --- !u!224 &6686599077041454343 102 | RectTransform: 103 | m_ObjectHideFlags: 0 104 | m_CorrespondingSourceObject: {fileID: 0} 105 | m_PrefabInstance: {fileID: 0} 106 | m_PrefabAsset: {fileID: 0} 107 | m_GameObject: {fileID: 3245847638180075902} 108 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 109 | m_LocalPosition: {x: 0, y: 0, z: 0} 110 | m_LocalScale: {x: 1, y: 1, z: 1} 111 | m_Children: [] 112 | m_Father: {fileID: 9179871002707573841} 113 | m_RootOrder: 0 114 | m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} 115 | m_AnchorMin: {x: 0, y: 0} 116 | m_AnchorMax: {x: 1, y: 1} 117 | m_AnchoredPosition: {x: 0, y: 0} 118 | m_SizeDelta: {x: 0, y: 0} 119 | m_Pivot: {x: 0.5, y: 0.5} 120 | --- !u!222 &572344923113193797 121 | CanvasRenderer: 122 | m_ObjectHideFlags: 0 123 | m_CorrespondingSourceObject: {fileID: 0} 124 | m_PrefabInstance: {fileID: 0} 125 | m_PrefabAsset: {fileID: 0} 126 | m_GameObject: {fileID: 3245847638180075902} 127 | m_CullTransparentMesh: 0 128 | --- !u!114 &6300994564907357248 129 | MonoBehaviour: 130 | m_ObjectHideFlags: 0 131 | m_CorrespondingSourceObject: {fileID: 0} 132 | m_PrefabInstance: {fileID: 0} 133 | m_PrefabAsset: {fileID: 0} 134 | m_GameObject: {fileID: 3245847638180075902} 135 | m_Enabled: 1 136 | m_EditorHideFlags: 0 137 | m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} 138 | m_Name: 139 | m_EditorClassIdentifier: 140 | m_Material: {fileID: 0} 141 | m_Color: {r: 1, g: 1, b: 1, a: 1} 142 | m_RaycastTarget: 1 143 | m_Maskable: 1 144 | m_OnCullStateChanged: 145 | m_PersistentCalls: 146 | m_Calls: [] 147 | m_Sprite: {fileID: 21300000, guid: df864bb51d4bb479d979f9a55dfc90c7, type: 3} 148 | m_Type: 0 149 | m_PreserveAspect: 0 150 | m_FillCenter: 1 151 | m_FillMethod: 4 152 | m_FillAmount: 1 153 | m_FillClockwise: 1 154 | m_FillOrigin: 0 155 | m_UseSpriteMesh: 0 156 | m_PixelsPerUnitMultiplier: 1 157 | -------------------------------------------------------------------------------- /Samples~/Prefabs/HexButton_Horizontal.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ec79681e955294711a65cdffd0aaf109 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Samples~/Prefabs/HexButton_Vertical.prefab: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1001 &1214057738837990626 4 | PrefabInstance: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Modification: 8 | m_TransformParent: {fileID: 0} 9 | m_Modifications: 10 | - target: {fileID: 1414110579747643580, guid: ec79681e955294711a65cdffd0aaf109, 11 | type: 3} 12 | propertyPath: m_Name 13 | value: HexButton_Vertical 14 | objectReference: {fileID: 0} 15 | - target: {fileID: 6300994564907357248, guid: ec79681e955294711a65cdffd0aaf109, 16 | type: 3} 17 | propertyPath: m_Sprite 18 | value: 19 | objectReference: {fileID: 21300000, guid: 11f6b46684a9742c8ad3b50cd0c74c08, 20 | type: 3} 21 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 22 | type: 3} 23 | propertyPath: m_LocalPosition.x 24 | value: 0 25 | objectReference: {fileID: 0} 26 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 27 | type: 3} 28 | propertyPath: m_LocalPosition.y 29 | value: 0 30 | objectReference: {fileID: 0} 31 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 32 | type: 3} 33 | propertyPath: m_LocalPosition.z 34 | value: 0 35 | objectReference: {fileID: 0} 36 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 37 | type: 3} 38 | propertyPath: m_LocalRotation.x 39 | value: 0 40 | objectReference: {fileID: 0} 41 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 42 | type: 3} 43 | propertyPath: m_LocalRotation.y 44 | value: 0 45 | objectReference: {fileID: 0} 46 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 47 | type: 3} 48 | propertyPath: m_LocalRotation.z 49 | value: 0 50 | objectReference: {fileID: 0} 51 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 52 | type: 3} 53 | propertyPath: m_LocalRotation.w 54 | value: 1 55 | objectReference: {fileID: 0} 56 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 57 | type: 3} 58 | propertyPath: m_RootOrder 59 | value: 0 60 | objectReference: {fileID: 0} 61 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 62 | type: 3} 63 | propertyPath: m_LocalEulerAnglesHint.x 64 | value: 0 65 | objectReference: {fileID: 0} 66 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 67 | type: 3} 68 | propertyPath: m_LocalEulerAnglesHint.y 69 | value: 0 70 | objectReference: {fileID: 0} 71 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 72 | type: 3} 73 | propertyPath: m_LocalEulerAnglesHint.z 74 | value: 0 75 | objectReference: {fileID: 0} 76 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 77 | type: 3} 78 | propertyPath: m_AnchoredPosition.x 79 | value: 0 80 | objectReference: {fileID: 0} 81 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 82 | type: 3} 83 | propertyPath: m_AnchoredPosition.y 84 | value: 0 85 | objectReference: {fileID: 0} 86 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 87 | type: 3} 88 | propertyPath: m_SizeDelta.x 89 | value: 86.6 90 | objectReference: {fileID: 0} 91 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 92 | type: 3} 93 | propertyPath: m_SizeDelta.y 94 | value: 100 95 | objectReference: {fileID: 0} 96 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 97 | type: 3} 98 | propertyPath: m_AnchorMin.x 99 | value: 0.5 100 | objectReference: {fileID: 0} 101 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 102 | type: 3} 103 | propertyPath: m_AnchorMin.y 104 | value: 0.5 105 | objectReference: {fileID: 0} 106 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 107 | type: 3} 108 | propertyPath: m_AnchorMax.x 109 | value: 0.5 110 | objectReference: {fileID: 0} 111 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 112 | type: 3} 113 | propertyPath: m_AnchorMax.y 114 | value: 0.5 115 | objectReference: {fileID: 0} 116 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 117 | type: 3} 118 | propertyPath: m_Pivot.x 119 | value: 0.5 120 | objectReference: {fileID: 0} 121 | - target: {fileID: 9179871002707573841, guid: ec79681e955294711a65cdffd0aaf109, 122 | type: 3} 123 | propertyPath: m_Pivot.y 124 | value: 0.5 125 | objectReference: {fileID: 0} 126 | m_RemovedComponents: [] 127 | m_SourcePrefab: {fileID: 100100000, guid: ec79681e955294711a65cdffd0aaf109, type: 3} 128 | -------------------------------------------------------------------------------- /Samples~/Prefabs/HexButton_Vertical.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a02849c0da20443a581920e196b813cd 3 | PrefabImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Samples~/Scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bb7812fb94da940aa9bfdbf6d7544762 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/Scenes/HexLayoutGroupExample.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e8a268a14bb7d4ca58de364047d3c0b7 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Samples~/Sprites.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8edea272d9b59420e892f5486e295cc4 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/Sprites/Hexagon_Horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpewsey/HexagonalUI/c99404ac0f23f91a6d2cd582c3e722f9e9eefb95/Samples~/Sprites/Hexagon_Horizontal.png -------------------------------------------------------------------------------- /Samples~/Sprites/Hexagon_Horizontal.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: df864bb51d4bb479d979f9a55dfc90c7 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: 1 38 | wrapV: 1 39 | wrapW: 1 40 | nPOTScale: 0 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 1 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 1 53 | spriteTessellationDetail: -1 54 | textureType: 8 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | applyGammaDecoding: 0 61 | platformSettings: 62 | - serializedVersion: 3 63 | buildTarget: DefaultTexturePlatform 64 | maxTextureSize: 2048 65 | resizeAlgorithm: 0 66 | textureFormat: -1 67 | textureCompression: 1 68 | compressionQuality: 50 69 | crunchedCompression: 0 70 | allowsAlphaSplitting: 0 71 | overridden: 0 72 | androidETC2FallbackOverride: 0 73 | forceMaximumCompressionQuality_BC6H_BC7: 0 74 | spriteSheet: 75 | serializedVersion: 2 76 | sprites: [] 77 | outline: [] 78 | physicsShape: [] 79 | bones: [] 80 | spriteID: 5e97eb03825dee720800000000000000 81 | internalID: 0 82 | vertices: [] 83 | indices: 84 | edges: [] 85 | weights: [] 86 | secondaryTextures: [] 87 | spritePackingTag: 88 | pSDRemoveMatte: 0 89 | pSDShowRemoveMatteOption: 0 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /Samples~/Sprites/Hexagon_Vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mpewsey/HexagonalUI/c99404ac0f23f91a6d2cd582c3e722f9e9eefb95/Samples~/Sprites/Hexagon_Vertical.png -------------------------------------------------------------------------------- /Samples~/Sprites/Hexagon_Vertical.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 11f6b46684a9742c8ad3b50cd0c74c08 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: 1 38 | wrapV: 1 39 | wrapW: 1 40 | nPOTScale: 0 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 1 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 1 53 | spriteTessellationDetail: -1 54 | textureType: 8 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | applyGammaDecoding: 0 61 | platformSettings: 62 | - serializedVersion: 3 63 | buildTarget: DefaultTexturePlatform 64 | maxTextureSize: 2048 65 | resizeAlgorithm: 0 66 | textureFormat: -1 67 | textureCompression: 1 68 | compressionQuality: 50 69 | crunchedCompression: 0 70 | allowsAlphaSplitting: 0 71 | overridden: 0 72 | androidETC2FallbackOverride: 0 73 | forceMaximumCompressionQuality_BC6H_BC7: 0 74 | spriteSheet: 75 | serializedVersion: 2 76 | sprites: [] 77 | outline: [] 78 | physicsShape: [] 79 | bones: [] 80 | spriteID: 5e97eb03825dee720800000000000000 81 | internalID: 0 82 | vertices: [] 83 | indices: 84 | edges: [] 85 | weights: [] 86 | secondaryTextures: [] 87 | spritePackingTag: 88 | pSDRemoveMatte: 0 89 | pSDShowRemoveMatteOption: 0 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 72e43452e63244da294ffb8b3736e4ec 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f5cb75c7ff4f1405389775555d5b88fa 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Editor/HexLayoutGroupEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace MPewsey.HexagonalUI.Editor 5 | { 6 | /// 7 | /// The HexLayoutGroup custom inspector. 8 | /// 9 | [CustomEditor(typeof(HexLayoutGroup))] 10 | public class HexLayoutGroupEditor : UnityEditor.Editor 11 | { 12 | public override void OnInspectorGUI() 13 | { 14 | serializedObject.Update(); 15 | var constraint = serializedObject.FindProperty("_constraint"); 16 | var flexibleConstraint = constraint.enumValueIndex == (int)HexLayoutGroup.ConstraintType.Flexible; 17 | var prop = serializedObject.GetIterator(); 18 | GUI.enabled = false; 19 | var enterChildren = true; 20 | 21 | while (prop.NextVisible(enterChildren)) 22 | { 23 | if (prop.name != "_constraintCount" || !flexibleConstraint) 24 | EditorGUILayout.PropertyField(prop, true); 25 | 26 | GUI.enabled = true; 27 | enterChildren = false; 28 | } 29 | 30 | serializedObject.ApplyModifiedProperties(); 31 | } 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /Scripts/Editor/HexLayoutGroupEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 26575e6ee72aa484f986c354a310a671 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Editor/MPewsey.HexagonalUI.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MPewsey.HexagonalUI.Editor", 3 | "references": [ 4 | "GUID:f440d987bce314b6eb721572e7cbdd60" 5 | ], 6 | "includePlatforms": [ 7 | "Editor" 8 | ], 9 | "excludePlatforms": [], 10 | "allowUnsafeCode": false, 11 | "overrideReferences": false, 12 | "precompiledReferences": [], 13 | "autoReferenced": true, 14 | "defineConstraints": [], 15 | "versionDefines": [], 16 | "noEngineReferences": false 17 | } -------------------------------------------------------------------------------- /Scripts/Editor/MPewsey.HexagonalUI.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 79ab1ce15d1094ee481d95d1b5a00f0f 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Scripts/Runtime.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 99134e9ea7ab749eab4556cd6db02795 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Scripts/Runtime/HexButton.cs: -------------------------------------------------------------------------------- 1 | /// Copyright (c) Matt Pewsey, All Rights Reserved. 2 | 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | using UnityEngine.UI; 6 | 7 | namespace MPewsey.HexagonalUI 8 | { 9 | /// 10 | /// This component overrides the built in Button component's navigation to work 11 | /// more intuitively with the staggered element stacking of the HexLayoutGroup. 12 | /// This component should be used instead of the built in Button component 13 | /// for buttons that are immediate children of a HexLayoutGroup. 14 | /// 15 | public class HexButton : Button 16 | { 17 | /// 18 | /// A list of sibling selectables populated during a navigation query. 19 | /// 20 | private static List SiblingSelectables { get; set; } = new List(); 21 | 22 | /// 23 | /// Returns the axis for the specified direction. 24 | /// 25 | private static int GetAxis(Vector3 direction) 26 | { 27 | if (Mathf.Abs(direction.x) > Mathf.Abs(direction.y)) 28 | return 0; 29 | return 1; 30 | } 31 | 32 | /// 33 | /// Returns the selectable on navigation up. 34 | /// 35 | public override Selectable FindSelectableOnUp() 36 | { 37 | if (navigation.mode == Navigation.Mode.Explicit) 38 | return navigation.selectOnUp; 39 | if ((navigation.mode & Navigation.Mode.Vertical) != Navigation.Mode.None) 40 | return GetSelectable(transform.rotation * Vector3.up); 41 | return null; 42 | } 43 | 44 | /// 45 | /// Returns the selectable on navigation down. 46 | /// 47 | public override Selectable FindSelectableOnDown() 48 | { 49 | if (navigation.mode == Navigation.Mode.Explicit) 50 | return navigation.selectOnDown; 51 | if ((navigation.mode & Navigation.Mode.Vertical) != Navigation.Mode.None) 52 | return GetSelectable(transform.rotation * Vector3.down); 53 | return null; 54 | } 55 | 56 | /// 57 | /// Returns the selectable on navigation left. 58 | /// 59 | public override Selectable FindSelectableOnLeft() 60 | { 61 | if (navigation.mode == Navigation.Mode.Explicit) 62 | return navigation.selectOnLeft; 63 | if ((navigation.mode & Navigation.Mode.Horizontal) != Navigation.Mode.None) 64 | return GetSelectable(transform.rotation * Vector3.left); 65 | return null; 66 | } 67 | 68 | /// 69 | /// Returns the selectable on navigation right. 70 | /// 71 | public override Selectable FindSelectableOnRight() 72 | { 73 | if (navigation.mode == Navigation.Mode.Explicit) 74 | return navigation.selectOnRight; 75 | if ((navigation.mode & Navigation.Mode.Horizontal) != Navigation.Mode.None) 76 | return GetSelectable(transform.rotation * Vector3.right); 77 | return null; 78 | } 79 | 80 | /// 81 | /// Sets the sibling selectables array with all active selectables. 82 | /// 83 | private void SetSiblingSelectables() 84 | { 85 | SiblingSelectables.Clear(); 86 | var parent = transform.parent; 87 | 88 | for (int i = 0; i < parent.childCount; i++) 89 | { 90 | var child = parent.GetChild(i); 91 | 92 | if (child.gameObject.activeInHierarchy) 93 | { 94 | var selectable = child.GetComponent(); 95 | SiblingSelectables.Add(selectable); 96 | } 97 | } 98 | } 99 | 100 | /// 101 | /// Returns the selectable in the specified direction. 102 | /// 103 | public Selectable GetSelectable(Vector3 direction) 104 | { 105 | var result = FindSelectable(direction); 106 | 107 | if (result == null || transform.parent == null || !IsActive()) 108 | return result; 109 | 110 | var hexLayout = transform.parent.GetComponent(); 111 | var directionAxis = GetAxis(direction); 112 | 113 | if (hexLayout == null || directionAxis != (int)hexLayout.CellOrientation) 114 | return result; 115 | 116 | SetSiblingSelectables(); 117 | var startAxis = (int)hexLayout.StartAxis; 118 | var rows = hexLayout.RowCount(SiblingSelectables.Count); 119 | var columns = hexLayout.ColumnCount(SiblingSelectables.Count); 120 | var index = GetIndex(rows, columns, startAxis); 121 | var (row, column) = (index.x, index.y); 122 | Selectable selectable; 123 | 124 | if (row < 0 || column < 0) 125 | return result; 126 | 127 | if (directionAxis == 0) 128 | { 129 | if (direction.x > 0) 130 | selectable = GetSelectableOnRight(row, column, rows, columns, startAxis); 131 | else 132 | selectable = GetSelectableOnLeft(row, column, rows, columns, startAxis); 133 | } 134 | else 135 | { 136 | if (direction.y > 0) 137 | selectable = GetSelectableOnUp(row, column, rows, columns, startAxis); 138 | else 139 | selectable = GetSelectableOnDown(row, column, rows, columns, startAxis); 140 | } 141 | 142 | SiblingSelectables.Clear(); 143 | return selectable != null ? selectable : result; 144 | } 145 | 146 | /// 147 | /// Returns the next active selectable above the specified row-column index. 148 | /// 149 | private Selectable GetSelectableOnUp(int row, int column, int rows, int columns, int startAxis) 150 | { 151 | for (int i = row - 1; i >= 0; i--) 152 | { 153 | var index = GetFlatIndex(i, column, rows, columns, startAxis); 154 | 155 | if (CanNavigateTo(SiblingSelectables[index])) 156 | return SiblingSelectables[index]; 157 | } 158 | 159 | return null; 160 | } 161 | 162 | /// 163 | /// Returns the next active selectable below the specified row-column index. 164 | /// 165 | private Selectable GetSelectableOnDown(int row, int column, int rows, int columns, int startAxis) 166 | { 167 | for (int i = row + 1; i < rows; i++) 168 | { 169 | var index = GetFlatIndex(i, column, rows, columns, startAxis); 170 | 171 | if (index < SiblingSelectables.Count && CanNavigateTo(SiblingSelectables[index])) 172 | return SiblingSelectables[index]; 173 | } 174 | 175 | return null; 176 | } 177 | 178 | /// 179 | /// Returns the next active selectable to the right of specified row-column index. 180 | /// 181 | private Selectable GetSelectableOnRight(int row, int column, int rows, int columns, int startAxis) 182 | { 183 | for (int i = column + 1; i < columns; i++) 184 | { 185 | var index = GetFlatIndex(row, i, rows, columns, startAxis); 186 | 187 | if (index < SiblingSelectables.Count && CanNavigateTo(SiblingSelectables[index])) 188 | return SiblingSelectables[index]; 189 | } 190 | 191 | return null; 192 | } 193 | 194 | /// 195 | /// Returns the next active selectable to the left of the specified row-column index. 196 | /// 197 | private Selectable GetSelectableOnLeft(int row, int column, int rows, int columns, int startAxis) 198 | { 199 | for (int i = column - 1; i >= 0; i--) 200 | { 201 | var index = GetFlatIndex(row, i, rows, columns, startAxis); 202 | 203 | if (CanNavigateTo(SiblingSelectables[index])) 204 | return SiblingSelectables[index]; 205 | } 206 | 207 | return null; 208 | } 209 | 210 | /// 211 | /// Returns true if the selectable can be navigated to. 212 | /// 213 | private bool CanNavigateTo(Selectable selectable) 214 | { 215 | return selectable != null 216 | && selectable != this 217 | && selectable.IsInteractable() 218 | && selectable.IsActive() 219 | && selectable.navigation.mode != Navigation.Mode.None; 220 | } 221 | 222 | /// 223 | /// Returns the flat index based on the 224 | /// 225 | private static int GetFlatIndex(int row, int column, int rows, int columns, int startAxis) 226 | { 227 | if (startAxis == 0) 228 | return row * columns + column; 229 | 230 | return column * rows + row; 231 | } 232 | 233 | /// 234 | /// Returns the row-column index of the button based on its flat 235 | /// index in the sibling selectables list. 236 | /// 237 | private Vector2Int GetIndex(int rows, int columns, int startAxis) 238 | { 239 | for (int i = 0; i < SiblingSelectables.Count; i++) 240 | { 241 | if (SiblingSelectables[i] == this) 242 | { 243 | if (startAxis == 0) 244 | return new Vector2Int(i / columns, i % columns); 245 | 246 | return new Vector2Int(i % rows, i / rows); 247 | } 248 | } 249 | 250 | return new Vector2Int(-1, -1); 251 | } 252 | } 253 | } 254 | -------------------------------------------------------------------------------- /Scripts/Runtime/HexButton.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8b95c1f04db9249c68fe7f31e9ec5b97 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Runtime/HexLayoutGroup.cs: -------------------------------------------------------------------------------- 1 | /// Copyright (c) Matt Pewsey, All Rights Reserved. 2 | 3 | using UnityEngine; 4 | using UnityEngine.UI; 5 | 6 | namespace MPewsey.HexagonalUI 7 | { 8 | /// 9 | /// Attach this component to a GameObject to apply hexagonal layout 10 | /// to its children. For buttons used as children, use the HexButton 11 | /// component in lieu of the built in Button component for more 12 | /// intuitive input navigation. 13 | /// 14 | [RequireComponent(typeof(RectTransform))] 15 | public class HexLayoutGroup : LayoutGroup 16 | { 17 | [SerializeField] 18 | private float _circumradius = 50.0f; 19 | /// 20 | /// The circumradius of the hexagonal elements. 21 | /// 22 | public float Circumradius 23 | { 24 | get => _circumradius; 25 | set => SetProperty(ref _circumradius, value); 26 | } 27 | 28 | [SerializeField] 29 | private Vector2 _spacing = new Vector2(20.0f, 20.0f); 30 | /// 31 | /// The horizontal and vertical spacing between hexagonal elements. 32 | /// 33 | public Vector2 Spacing 34 | { 35 | get => _spacing; 36 | set => SetProperty(ref _spacing, value); 37 | } 38 | 39 | [SerializeField] 40 | private Axis _startAxis; 41 | /// 42 | /// The start axis for tiling elements. 43 | /// 44 | public Axis StartAxis 45 | { 46 | get => _startAxis; 47 | set => SetProperty(ref _startAxis, value); 48 | } 49 | 50 | [SerializeField] 51 | private Axis _cellOrientation; 52 | /// 53 | /// The orientation of the hexagonal element long axes. 54 | /// 55 | public Axis CellOrientation 56 | { 57 | get => _cellOrientation; 58 | set => SetProperty(ref _cellOrientation, value); 59 | } 60 | 61 | [SerializeField] 62 | private ConstraintType _constraint; 63 | /// 64 | /// The constraint used for paging elements. 65 | /// 66 | public ConstraintType Constraint 67 | { 68 | get => _constraint; 69 | set => SetProperty(ref _constraint, value); 70 | } 71 | 72 | [SerializeField] 73 | private int _constraintCount = 10; 74 | /// 75 | /// The constaint count for non-flexible constraints. 76 | /// 77 | public int ConstraintCount 78 | { 79 | get => _constraintCount; 80 | set => SetProperty(ref _constraintCount, Mathf.Max(value, 1)); 81 | } 82 | 83 | #if UNITY_EDITOR 84 | protected override void OnValidate() 85 | { 86 | base.OnValidate(); 87 | ConstraintCount = Mathf.Max(ConstraintCount, 1); 88 | } 89 | #endif 90 | 91 | /// 92 | /// Calculates the minimum and preferred widths for the object. 93 | /// 94 | public override void CalculateLayoutInputHorizontal() 95 | { 96 | base.CalculateLayoutInputHorizontal(); 97 | var totalMin = Mathf.Max(padding.horizontal + ContentWidth(MinColumnCount()), 0.0f); 98 | var totalPreferred = Mathf.Max(padding.horizontal + ContentWidth(PreferredColumnCount()), 0.0f); 99 | SetLayoutInputForAxis(totalMin, totalPreferred, -1.0f, 0); 100 | } 101 | 102 | /// 103 | /// Calculates the minimum and preferred heights for the object. 104 | /// 105 | public override void CalculateLayoutInputVertical() 106 | { 107 | var totalMin = Mathf.Max(padding.vertical + ContentHeight(MinRowCount()), 0.0f); 108 | var totalPreferred = Mathf.Max(padding.vertical + ContentHeight(PreferredRowCount()), 0.0f); 109 | SetLayoutInputForAxis(totalMin, totalPreferred, -1.0f, 1); 110 | } 111 | 112 | /// 113 | /// Sets the cell sizes for the hexagonal elements. 114 | /// 115 | public override void SetLayoutHorizontal() 116 | { 117 | SetCellSizes(); 118 | } 119 | 120 | /// 121 | /// Sets the positions of the hexagonal elements. 122 | /// 123 | public override void SetLayoutVertical() 124 | { 125 | CalculateLayout(); 126 | } 127 | 128 | /// 129 | /// Returns true if the value is even. 130 | /// 131 | private static bool IsEven(int value) 132 | { 133 | return (value & 1) == 0; 134 | } 135 | 136 | /// 137 | /// Sets the cell sizes for the hexagonal elements. 138 | /// 139 | private void SetCellSizes() 140 | { 141 | var cellSize = CellSize(); 142 | 143 | for (int i = 0; i < rectChildren.Count; i++) 144 | { 145 | var rectChild = rectChildren[i]; 146 | m_Tracker.Add(this, rectChild, DrivenTransformProperties.Anchors | DrivenTransformProperties.AnchoredPosition | DrivenTransformProperties.SizeDelta); 147 | rectChild.anchorMin = Vector2.up; 148 | rectChild.anchorMax = Vector2.up; 149 | rectChild.sizeDelta = cellSize; 150 | } 151 | } 152 | 153 | /// 154 | /// Returns the content height for the specified number of rows. 155 | /// 156 | private float ContentHeight(int rows) 157 | { 158 | if (rows <= 0) 159 | return 0.0f; 160 | 161 | float value; 162 | var cellSize = CellSize(); 163 | 164 | if (CellOrientation == Axis.Horizontal) 165 | value = rows * (cellSize.y + Spacing.y) - Spacing.y + 0.5f * (cellSize.y + Spacing.y); 166 | else 167 | value = rows * (0.75f * cellSize.y + Spacing.y) - Spacing.y + 0.25f * cellSize.y; 168 | 169 | return Mathf.Max(value, 0.0f); 170 | } 171 | 172 | /// 173 | /// Returns the content width for the specified number of columns. 174 | /// 175 | private float ContentWidth(int columns) 176 | { 177 | if (columns <= 0) 178 | return 0.0f; 179 | 180 | float value; 181 | var cellSize = CellSize(); 182 | 183 | if (CellOrientation == Axis.Horizontal) 184 | value = columns * (0.75f * cellSize.x + Spacing.x) - Spacing.x + 0.25f * cellSize.x; 185 | else 186 | value = columns * (cellSize.x + Spacing.x) - Spacing.x + 0.5f * (cellSize.x + Spacing.x); 187 | 188 | return Mathf.Max(value, 0.0f); 189 | } 190 | 191 | /// 192 | /// Sets the positions of the hexagonal elements. 193 | /// 194 | private void CalculateLayout() 195 | { 196 | var rows = RowCount(); 197 | var columns = ColumnCount(); 198 | var cellSize = CellSize(); 199 | var x0 = GetStartOffset(0, ContentWidth(columns)); 200 | var y0 = GetStartOffset(1, ContentHeight(rows)); 201 | 202 | for (int i = 0; i < rectChildren.Count; i++) 203 | { 204 | int row, column; 205 | float x, y; 206 | 207 | if (StartAxis == Axis.Horizontal) 208 | (row, column) = (i / columns, i % columns); 209 | else 210 | (row, column) = (i % rows, i / rows); 211 | 212 | if (CellOrientation == Axis.Horizontal) 213 | { 214 | x = x0 + column * (0.75f * cellSize.x + Spacing.x); 215 | y = y0 + row * (cellSize.y + Spacing.y); 216 | 217 | if (IsEven(column)) 218 | y += 0.5f * (cellSize.y + Spacing.y); 219 | } 220 | else 221 | { 222 | x = x0 + column * (cellSize.x + Spacing.x); 223 | y = y0 + row * (0.75f * cellSize.y + Spacing.y); 224 | 225 | if (IsEven(row)) 226 | x += 0.5f * (cellSize.x + Spacing.x); 227 | } 228 | 229 | SetChildAlongAxis(rectChildren[i], 0, x, cellSize.x); 230 | SetChildAlongAxis(rectChildren[i], 1, y, cellSize.y); 231 | } 232 | } 233 | 234 | /// 235 | /// Returns the row count used for the minimum layout height. 236 | /// 237 | private int MinRowCount() 238 | { 239 | switch (Constraint) 240 | { 241 | case ConstraintType.FixedRow: 242 | return ConstraintCount; 243 | case ConstraintType.FixedColumn: 244 | return Mathf.Max(1, (rectChildren.Count - 1) / ConstraintCount + 1); 245 | default: 246 | return 1; 247 | } 248 | } 249 | 250 | /// 251 | /// Returns the row count used for the preferred layout height. 252 | /// 253 | private int PreferredRowCount() 254 | { 255 | switch (Constraint) 256 | { 257 | case ConstraintType.FixedRow: 258 | return ConstraintCount; 259 | case ConstraintType.FixedColumn: 260 | return Mathf.Max(1, (rectChildren.Count - 1) / ConstraintCount + 1); 261 | default: 262 | return Mathf.CeilToInt(Mathf.Sqrt(rectChildren.Count)); 263 | } 264 | } 265 | 266 | /// 267 | /// Returns the column count used for the minimum layout width. 268 | /// 269 | private int MinColumnCount() 270 | { 271 | switch (Constraint) 272 | { 273 | case ConstraintType.FixedColumn: 274 | return ConstraintCount; 275 | case ConstraintType.FixedRow: 276 | return Mathf.Max(1, (rectChildren.Count - 1) / ConstraintCount + 1); 277 | default: 278 | return 1; 279 | } 280 | } 281 | 282 | /// 283 | /// Returns the column count used for the preferred layout width. 284 | /// 285 | private int PreferredColumnCount() 286 | { 287 | switch (Constraint) 288 | { 289 | case ConstraintType.FixedColumn: 290 | return ConstraintCount; 291 | case ConstraintType.FixedRow: 292 | return Mathf.Max(1, (rectChildren.Count - 1) / ConstraintCount + 1); 293 | default: 294 | return Mathf.CeilToInt(Mathf.Sqrt(rectChildren.Count)); 295 | } 296 | } 297 | 298 | /// 299 | /// Returns the current row count. 300 | /// 301 | private int RowCount() 302 | { 303 | return RowCount(rectChildren.Count); 304 | } 305 | 306 | /// 307 | /// Returns the row count given a total element count. 308 | /// 309 | public int RowCount(int count) 310 | { 311 | var constraint = Mathf.Min(GetConstraintCount(), count); 312 | 313 | if (constraint > 0 && !ConstraintIsRowCount()) 314 | return (count - 1) / constraint + 1; 315 | 316 | return constraint; 317 | } 318 | 319 | /// 320 | /// Returns the current column count. 321 | /// 322 | private int ColumnCount() 323 | { 324 | return ColumnCount(rectChildren.Count); 325 | } 326 | 327 | /// 328 | /// Returns the column count given a total element count. 329 | /// 330 | public int ColumnCount(int count) 331 | { 332 | var constraint = Mathf.Min(GetConstraintCount(), count); 333 | 334 | if (constraint > 0 && ConstraintIsRowCount()) 335 | return (count - 1) / constraint + 1; 336 | 337 | return constraint; 338 | } 339 | 340 | /// 341 | /// Returns the hexagonal element width and height. 342 | /// 343 | public Vector2 CellSize() 344 | { 345 | var longDiagonal = 2.0f * Circumradius; 346 | var shortDiagonal = 0.86602540378f * longDiagonal; 347 | 348 | if (CellOrientation == Axis.Horizontal) 349 | return new Vector2(longDiagonal, shortDiagonal); 350 | 351 | return new Vector2(shortDiagonal, longDiagonal); 352 | } 353 | 354 | /// 355 | /// Returns true if the controlling constraint is the row count. 356 | /// Otherwise, the controlling constraint is the column count. 357 | /// 358 | public bool ConstraintIsRowCount() 359 | { 360 | if (Constraint == ConstraintType.Flexible) 361 | return StartAxis == Axis.Vertical; 362 | 363 | return Constraint == ConstraintType.FixedRow; 364 | } 365 | 366 | /// 367 | /// Returns the controlling constraint count. 368 | /// 369 | public int GetConstraintCount() 370 | { 371 | if (Constraint == ConstraintType.Flexible) 372 | return FlexibleConstraintCount(); 373 | 374 | return ConstraintCount; 375 | } 376 | 377 | /// 378 | /// Returns the constraint count for the flexible constraint. 379 | /// 380 | private int FlexibleConstraintCount() 381 | { 382 | if (StartAxis == Axis.Horizontal) 383 | return FlexibleWidthConstraintCount(); 384 | 385 | return FlexibleHeightConstraintCount(); 386 | } 387 | 388 | /// 389 | /// Returns the constraint count for the flexible width constraint. 390 | /// 391 | private int FlexibleWidthConstraintCount() 392 | { 393 | float value; 394 | var cellSize = CellSize(); 395 | var size = rectTransform.rect.size; 396 | 397 | if (CellOrientation == Axis.Horizontal) 398 | value = (size.x + Spacing.x - 0.25f * cellSize.x - padding.horizontal) / (0.75f * cellSize.x + Spacing.x); 399 | else 400 | value = (size.x + Spacing.x - 0.5f * (cellSize.x + Spacing.x) - padding.horizontal) / (cellSize.x + Spacing.x); 401 | 402 | return Mathf.Max(Mathf.FloorToInt(value), 1); 403 | } 404 | 405 | /// 406 | /// Returns the constraint count for the flexible height constraint. 407 | /// 408 | private int FlexibleHeightConstraintCount() 409 | { 410 | float value; 411 | var cellSize = CellSize(); 412 | var size = rectTransform.rect.size; 413 | 414 | if (CellOrientation == Axis.Horizontal) 415 | value = (size.y + Spacing.y - 0.5f * (cellSize.y + Spacing.y) - padding.vertical) / (cellSize.y + Spacing.y); 416 | else 417 | value = (size.y + Spacing.y - 0.25f * cellSize.y - padding.vertical) / (0.75f * cellSize.y + Spacing.y); 418 | 419 | return Mathf.Max(Mathf.FloorToInt(value), 1); 420 | } 421 | 422 | public enum Axis 423 | { 424 | Horizontal = 0, 425 | Vertical = 1, 426 | } 427 | 428 | public enum ConstraintType 429 | { 430 | Flexible, 431 | FixedRow, 432 | FixedColumn, 433 | } 434 | } 435 | } 436 | -------------------------------------------------------------------------------- /Scripts/Runtime/HexLayoutGroup.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7e777795a64934e3ebb6ed33ccc3c6ab 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Scripts/Runtime/MPewsey.HexagonalUI.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MPewsey.HexagonalUI" 3 | } 4 | -------------------------------------------------------------------------------- /Scripts/Runtime/MPewsey.HexagonalUI.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f440d987bce314b6eb721572e7cbdd60 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.mpewsey.hexagonal-ui", 3 | "author": "Matt Pewsey", 4 | "displayName": "HexagonalUI", 5 | "version": "1.3.1", 6 | "unity": "2018.1", 7 | "keywords": [ 8 | "unity", 9 | "ui", 10 | "hexagonal-grids" 11 | ], 12 | "description": "A hexagonal grid layout group for Unity.", 13 | "samples": [ 14 | { 15 | "displayName": "Samples", 16 | "description": "Samples for usage of the hexagonal layout group.", 17 | "path": "Samples~" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 791e81649db1d41c789836bba91eb26d 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------