Compare commits
No commits in common. "master" and "2025.11.28" have entirely different histories.
master
...
2025.11.28
49 changed files with 181 additions and 1415 deletions
|
|
@ -1,395 +0,0 @@
|
||||||
Attribution 4.0 International
|
|
||||||
|
|
||||||
=======================================================================
|
|
||||||
|
|
||||||
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
|
||||||
does not provide legal services or legal advice. Distribution of
|
|
||||||
Creative Commons public licenses does not create a lawyer-client or
|
|
||||||
other relationship. Creative Commons makes its licenses and related
|
|
||||||
information available on an "as-is" basis. Creative Commons gives no
|
|
||||||
warranties regarding its licenses, any material licensed under their
|
|
||||||
terms and conditions, or any related information. Creative Commons
|
|
||||||
disclaims all liability for damages resulting from their use to the
|
|
||||||
fullest extent possible.
|
|
||||||
|
|
||||||
Using Creative Commons Public Licenses
|
|
||||||
|
|
||||||
Creative Commons public licenses provide a standard set of terms and
|
|
||||||
conditions that creators and other rights holders may use to share
|
|
||||||
original works of authorship and other material subject to copyright
|
|
||||||
and certain other rights specified in the public license below. The
|
|
||||||
following considerations are for informational purposes only, are not
|
|
||||||
exhaustive, and do not form part of our licenses.
|
|
||||||
|
|
||||||
Considerations for licensors: Our public licenses are
|
|
||||||
intended for use by those authorized to give the public
|
|
||||||
permission to use material in ways otherwise restricted by
|
|
||||||
copyright and certain other rights. Our licenses are
|
|
||||||
irrevocable. Licensors should read and understand the terms
|
|
||||||
and conditions of the license they choose before applying it.
|
|
||||||
Licensors should also secure all rights necessary before
|
|
||||||
applying our licenses so that the public can reuse the
|
|
||||||
material as expected. Licensors should clearly mark any
|
|
||||||
material not subject to the license. This includes other CC-
|
|
||||||
licensed material, or material used under an exception or
|
|
||||||
limitation to copyright. More considerations for licensors:
|
|
||||||
wiki.creativecommons.org/Considerations_for_licensors
|
|
||||||
|
|
||||||
Considerations for the public: By using one of our public
|
|
||||||
licenses, a licensor grants the public permission to use the
|
|
||||||
licensed material under specified terms and conditions. If
|
|
||||||
the licensor's permission is not necessary for any reason--for
|
|
||||||
example, because of any applicable exception or limitation to
|
|
||||||
copyright--then that use is not regulated by the license. Our
|
|
||||||
licenses grant only permissions under copyright and certain
|
|
||||||
other rights that a licensor has authority to grant. Use of
|
|
||||||
the licensed material may still be restricted for other
|
|
||||||
reasons, including because others have copyright or other
|
|
||||||
rights in the material. A licensor may make special requests,
|
|
||||||
such as asking that all changes be marked or described.
|
|
||||||
Although not required by our licenses, you are encouraged to
|
|
||||||
respect those requests where reasonable. More considerations
|
|
||||||
for the public:
|
|
||||||
wiki.creativecommons.org/Considerations_for_licensees
|
|
||||||
|
|
||||||
=======================================================================
|
|
||||||
|
|
||||||
Creative Commons Attribution 4.0 International Public License
|
|
||||||
|
|
||||||
By exercising the Licensed Rights (defined below), You accept and agree
|
|
||||||
to be bound by the terms and conditions of this Creative Commons
|
|
||||||
Attribution 4.0 International Public License ("Public License"). To the
|
|
||||||
extent this Public License may be interpreted as a contract, You are
|
|
||||||
granted the Licensed Rights in consideration of Your acceptance of
|
|
||||||
these terms and conditions, and the Licensor grants You such rights in
|
|
||||||
consideration of benefits the Licensor receives from making the
|
|
||||||
Licensed Material available under these terms and conditions.
|
|
||||||
|
|
||||||
|
|
||||||
Section 1 -- Definitions.
|
|
||||||
|
|
||||||
a. Adapted Material means material subject to Copyright and Similar
|
|
||||||
Rights that is derived from or based upon the Licensed Material
|
|
||||||
and in which the Licensed Material is translated, altered,
|
|
||||||
arranged, transformed, or otherwise modified in a manner requiring
|
|
||||||
permission under the Copyright and Similar Rights held by the
|
|
||||||
Licensor. For purposes of this Public License, where the Licensed
|
|
||||||
Material is a musical work, performance, or sound recording,
|
|
||||||
Adapted Material is always produced where the Licensed Material is
|
|
||||||
synched in timed relation with a moving image.
|
|
||||||
|
|
||||||
b. Adapter's License means the license You apply to Your Copyright
|
|
||||||
and Similar Rights in Your contributions to Adapted Material in
|
|
||||||
accordance with the terms and conditions of this Public License.
|
|
||||||
|
|
||||||
c. Copyright and Similar Rights means copyright and/or similar rights
|
|
||||||
closely related to copyright including, without limitation,
|
|
||||||
performance, broadcast, sound recording, and Sui Generis Database
|
|
||||||
Rights, without regard to how the rights are labeled or
|
|
||||||
categorized. For purposes of this Public License, the rights
|
|
||||||
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
|
||||||
Rights.
|
|
||||||
|
|
||||||
d. Effective Technological Measures means those measures that, in the
|
|
||||||
absence of proper authority, may not be circumvented under laws
|
|
||||||
fulfilling obligations under Article 11 of the WIPO Copyright
|
|
||||||
Treaty adopted on December 20, 1996, and/or similar international
|
|
||||||
agreements.
|
|
||||||
|
|
||||||
e. Exceptions and Limitations means fair use, fair dealing, and/or
|
|
||||||
any other exception or limitation to Copyright and Similar Rights
|
|
||||||
that applies to Your use of the Licensed Material.
|
|
||||||
|
|
||||||
f. Licensed Material means the artistic or literary work, database,
|
|
||||||
or other material to which the Licensor applied this Public
|
|
||||||
License.
|
|
||||||
|
|
||||||
g. Licensed Rights means the rights granted to You subject to the
|
|
||||||
terms and conditions of this Public License, which are limited to
|
|
||||||
all Copyright and Similar Rights that apply to Your use of the
|
|
||||||
Licensed Material and that the Licensor has authority to license.
|
|
||||||
|
|
||||||
h. Licensor means the individual(s) or entity(ies) granting rights
|
|
||||||
under this Public License.
|
|
||||||
|
|
||||||
i. Share means to provide material to the public by any means or
|
|
||||||
process that requires permission under the Licensed Rights, such
|
|
||||||
as reproduction, public display, public performance, distribution,
|
|
||||||
dissemination, communication, or importation, and to make material
|
|
||||||
available to the public including in ways that members of the
|
|
||||||
public may access the material from a place and at a time
|
|
||||||
individually chosen by them.
|
|
||||||
|
|
||||||
j. Sui Generis Database Rights means rights other than copyright
|
|
||||||
resulting from Directive 96/9/EC of the European Parliament and of
|
|
||||||
the Council of 11 March 1996 on the legal protection of databases,
|
|
||||||
as amended and/or succeeded, as well as other essentially
|
|
||||||
equivalent rights anywhere in the world.
|
|
||||||
|
|
||||||
k. You means the individual or entity exercising the Licensed Rights
|
|
||||||
under this Public License. Your has a corresponding meaning.
|
|
||||||
|
|
||||||
|
|
||||||
Section 2 -- Scope.
|
|
||||||
|
|
||||||
a. License grant.
|
|
||||||
|
|
||||||
1. Subject to the terms and conditions of this Public License,
|
|
||||||
the Licensor hereby grants You a worldwide, royalty-free,
|
|
||||||
non-sublicensable, non-exclusive, irrevocable license to
|
|
||||||
exercise the Licensed Rights in the Licensed Material to:
|
|
||||||
|
|
||||||
a. reproduce and Share the Licensed Material, in whole or
|
|
||||||
in part; and
|
|
||||||
|
|
||||||
b. produce, reproduce, and Share Adapted Material.
|
|
||||||
|
|
||||||
2. Exceptions and Limitations. For the avoidance of doubt, where
|
|
||||||
Exceptions and Limitations apply to Your use, this Public
|
|
||||||
License does not apply, and You do not need to comply with
|
|
||||||
its terms and conditions.
|
|
||||||
|
|
||||||
3. Term. The term of this Public License is specified in Section
|
|
||||||
6(a).
|
|
||||||
|
|
||||||
4. Media and formats; technical modifications allowed. The
|
|
||||||
Licensor authorizes You to exercise the Licensed Rights in
|
|
||||||
all media and formats whether now known or hereafter created,
|
|
||||||
and to make technical modifications necessary to do so. The
|
|
||||||
Licensor waives and/or agrees not to assert any right or
|
|
||||||
authority to forbid You from making technical modifications
|
|
||||||
necessary to exercise the Licensed Rights, including
|
|
||||||
technical modifications necessary to circumvent Effective
|
|
||||||
Technological Measures. For purposes of this Public License,
|
|
||||||
simply making modifications authorized by this Section 2(a)
|
|
||||||
(4) never produces Adapted Material.
|
|
||||||
|
|
||||||
5. Downstream recipients.
|
|
||||||
|
|
||||||
a. Offer from the Licensor -- Licensed Material. Every
|
|
||||||
recipient of the Licensed Material automatically
|
|
||||||
receives an offer from the Licensor to exercise the
|
|
||||||
Licensed Rights under the terms and conditions of this
|
|
||||||
Public License.
|
|
||||||
|
|
||||||
b. No downstream restrictions. You may not offer or impose
|
|
||||||
any additional or different terms or conditions on, or
|
|
||||||
apply any Effective Technological Measures to, the
|
|
||||||
Licensed Material if doing so restricts exercise of the
|
|
||||||
Licensed Rights by any recipient of the Licensed
|
|
||||||
Material.
|
|
||||||
|
|
||||||
6. No endorsement. Nothing in this Public License constitutes or
|
|
||||||
may be construed as permission to assert or imply that You
|
|
||||||
are, or that Your use of the Licensed Material is, connected
|
|
||||||
with, or sponsored, endorsed, or granted official status by,
|
|
||||||
the Licensor or others designated to receive attribution as
|
|
||||||
provided in Section 3(a)(1)(A)(i).
|
|
||||||
|
|
||||||
b. Other rights.
|
|
||||||
|
|
||||||
1. Moral rights, such as the right of integrity, are not
|
|
||||||
licensed under this Public License, nor are publicity,
|
|
||||||
privacy, and/or other similar personality rights; however, to
|
|
||||||
the extent possible, the Licensor waives and/or agrees not to
|
|
||||||
assert any such rights held by the Licensor to the limited
|
|
||||||
extent necessary to allow You to exercise the Licensed
|
|
||||||
Rights, but not otherwise.
|
|
||||||
|
|
||||||
2. Patent and trademark rights are not licensed under this
|
|
||||||
Public License.
|
|
||||||
|
|
||||||
3. To the extent possible, the Licensor waives any right to
|
|
||||||
collect royalties from You for the exercise of the Licensed
|
|
||||||
Rights, whether directly or through a collecting society
|
|
||||||
under any voluntary or waivable statutory or compulsory
|
|
||||||
licensing scheme. In all other cases the Licensor expressly
|
|
||||||
reserves any right to collect such royalties.
|
|
||||||
|
|
||||||
|
|
||||||
Section 3 -- License Conditions.
|
|
||||||
|
|
||||||
Your exercise of the Licensed Rights is expressly made subject to the
|
|
||||||
following conditions.
|
|
||||||
|
|
||||||
a. Attribution.
|
|
||||||
|
|
||||||
1. If You Share the Licensed Material (including in modified
|
|
||||||
form), You must:
|
|
||||||
|
|
||||||
a. retain the following if it is supplied by the Licensor
|
|
||||||
with the Licensed Material:
|
|
||||||
|
|
||||||
i. identification of the creator(s) of the Licensed
|
|
||||||
Material and any others designated to receive
|
|
||||||
attribution, in any reasonable manner requested by
|
|
||||||
the Licensor (including by pseudonym if
|
|
||||||
designated);
|
|
||||||
|
|
||||||
ii. a copyright notice;
|
|
||||||
|
|
||||||
iii. a notice that refers to this Public License;
|
|
||||||
|
|
||||||
iv. a notice that refers to the disclaimer of
|
|
||||||
warranties;
|
|
||||||
|
|
||||||
v. a URI or hyperlink to the Licensed Material to the
|
|
||||||
extent reasonably practicable;
|
|
||||||
|
|
||||||
b. indicate if You modified the Licensed Material and
|
|
||||||
retain an indication of any previous modifications; and
|
|
||||||
|
|
||||||
c. indicate the Licensed Material is licensed under this
|
|
||||||
Public License, and include the text of, or the URI or
|
|
||||||
hyperlink to, this Public License.
|
|
||||||
|
|
||||||
2. You may satisfy the conditions in Section 3(a)(1) in any
|
|
||||||
reasonable manner based on the medium, means, and context in
|
|
||||||
which You Share the Licensed Material. For example, it may be
|
|
||||||
reasonable to satisfy the conditions by providing a URI or
|
|
||||||
hyperlink to a resource that includes the required
|
|
||||||
information.
|
|
||||||
|
|
||||||
3. If requested by the Licensor, You must remove any of the
|
|
||||||
information required by Section 3(a)(1)(A) to the extent
|
|
||||||
reasonably practicable.
|
|
||||||
|
|
||||||
4. If You Share Adapted Material You produce, the Adapter's
|
|
||||||
License You apply must not prevent recipients of the Adapted
|
|
||||||
Material from complying with this Public License.
|
|
||||||
|
|
||||||
|
|
||||||
Section 4 -- Sui Generis Database Rights.
|
|
||||||
|
|
||||||
Where the Licensed Rights include Sui Generis Database Rights that
|
|
||||||
apply to Your use of the Licensed Material:
|
|
||||||
|
|
||||||
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
|
||||||
to extract, reuse, reproduce, and Share all or a substantial
|
|
||||||
portion of the contents of the database;
|
|
||||||
|
|
||||||
b. if You include all or a substantial portion of the database
|
|
||||||
contents in a database in which You have Sui Generis Database
|
|
||||||
Rights, then the database in which You have Sui Generis Database
|
|
||||||
Rights (but not its individual contents) is Adapted Material; and
|
|
||||||
|
|
||||||
c. You must comply with the conditions in Section 3(a) if You Share
|
|
||||||
all or a substantial portion of the contents of the database.
|
|
||||||
|
|
||||||
For the avoidance of doubt, this Section 4 supplements and does not
|
|
||||||
replace Your obligations under this Public License where the Licensed
|
|
||||||
Rights include other Copyright and Similar Rights.
|
|
||||||
|
|
||||||
|
|
||||||
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
|
||||||
|
|
||||||
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
|
||||||
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
|
||||||
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
|
||||||
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
|
||||||
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
|
||||||
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
|
||||||
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
|
||||||
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
|
||||||
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
|
||||||
|
|
||||||
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
|
||||||
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
|
||||||
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
|
||||||
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
|
||||||
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
|
||||||
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
|
||||||
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
|
||||||
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
|
||||||
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
|
||||||
|
|
||||||
c. The disclaimer of warranties and limitation of liability provided
|
|
||||||
above shall be interpreted in a manner that, to the extent
|
|
||||||
possible, most closely approximates an absolute disclaimer and
|
|
||||||
waiver of all liability.
|
|
||||||
|
|
||||||
|
|
||||||
Section 6 -- Term and Termination.
|
|
||||||
|
|
||||||
a. This Public License applies for the term of the Copyright and
|
|
||||||
Similar Rights licensed here. However, if You fail to comply with
|
|
||||||
this Public License, then Your rights under this Public License
|
|
||||||
terminate automatically.
|
|
||||||
|
|
||||||
b. Where Your right to use the Licensed Material has terminated under
|
|
||||||
Section 6(a), it reinstates:
|
|
||||||
|
|
||||||
1. automatically as of the date the violation is cured, provided
|
|
||||||
it is cured within 30 days of Your discovery of the
|
|
||||||
violation; or
|
|
||||||
|
|
||||||
2. upon express reinstatement by the Licensor.
|
|
||||||
|
|
||||||
For the avoidance of doubt, this Section 6(b) does not affect any
|
|
||||||
right the Licensor may have to seek remedies for Your violations
|
|
||||||
of this Public License.
|
|
||||||
|
|
||||||
c. For the avoidance of doubt, the Licensor may also offer the
|
|
||||||
Licensed Material under separate terms or conditions or stop
|
|
||||||
distributing the Licensed Material at any time; however, doing so
|
|
||||||
will not terminate this Public License.
|
|
||||||
|
|
||||||
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
|
||||||
License.
|
|
||||||
|
|
||||||
|
|
||||||
Section 7 -- Other Terms and Conditions.
|
|
||||||
|
|
||||||
a. The Licensor shall not be bound by any additional or different
|
|
||||||
terms or conditions communicated by You unless expressly agreed.
|
|
||||||
|
|
||||||
b. Any arrangements, understandings, or agreements regarding the
|
|
||||||
Licensed Material not stated herein are separate from and
|
|
||||||
independent of the terms and conditions of this Public License.
|
|
||||||
|
|
||||||
|
|
||||||
Section 8 -- Interpretation.
|
|
||||||
|
|
||||||
a. For the avoidance of doubt, this Public License does not, and
|
|
||||||
shall not be interpreted to, reduce, limit, restrict, or impose
|
|
||||||
conditions on any use of the Licensed Material that could lawfully
|
|
||||||
be made without permission under this Public License.
|
|
||||||
|
|
||||||
b. To the extent possible, if any provision of this Public License is
|
|
||||||
deemed unenforceable, it shall be automatically reformed to the
|
|
||||||
minimum extent necessary to make it enforceable. If the provision
|
|
||||||
cannot be reformed, it shall be severed from this Public License
|
|
||||||
without affecting the enforceability of the remaining terms and
|
|
||||||
conditions.
|
|
||||||
|
|
||||||
c. No term or condition of this Public License will be waived and no
|
|
||||||
failure to comply consented to unless expressly agreed to by the
|
|
||||||
Licensor.
|
|
||||||
|
|
||||||
d. Nothing in this Public License constitutes or may be interpreted
|
|
||||||
as a limitation upon, or waiver of, any privileges and immunities
|
|
||||||
that apply to the Licensor or You, including from the legal
|
|
||||||
processes of any jurisdiction or authority.
|
|
||||||
|
|
||||||
|
|
||||||
=======================================================================
|
|
||||||
|
|
||||||
Creative Commons is not a party to its public
|
|
||||||
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
|
||||||
its public licenses to material it publishes and in those instances
|
|
||||||
will be considered the “Licensor.” The text of the Creative Commons
|
|
||||||
public licenses is dedicated to the public domain under the CC0 Public
|
|
||||||
Domain Dedication. Except for the limited purpose of indicating that
|
|
||||||
material is shared under a Creative Commons public license or as
|
|
||||||
otherwise permitted by the Creative Commons policies published at
|
|
||||||
creativecommons.org/policies, Creative Commons does not authorize the
|
|
||||||
use of the trademark "Creative Commons" or any other trademark or logo
|
|
||||||
of Creative Commons without its prior written consent including,
|
|
||||||
without limitation, in connection with any unauthorized modifications
|
|
||||||
to any of its public licenses or any other arrangements,
|
|
||||||
understandings, or agreements concerning use of licensed material. For
|
|
||||||
the avoidance of doubt, this paragraph does not form part of the
|
|
||||||
public licenses.
|
|
||||||
|
|
||||||
Creative Commons may be contacted at creativecommons.org.
|
|
||||||
113
README.md
113
README.md
|
|
@ -1,9 +1,114 @@
|
||||||
# Visualisation for MARSH
|
# Visualisation for MARSH
|
||||||
|
|
||||||
This is a visualisation module for [Modular Architecture for Reconfigurable Simulation of Helicopters](https://marsh-sim.github.io/).
|
This is a visualisation module for [Modular Architecture for Reconfigurable Simulation of Helicopters](https://marsh-sim.github.io/).
|
||||||
For documentation, see [MARSH Documentation - Visualisation](https://marsh-sim.github.io/nodes/visualisation/)
|
The project is configured to display cockpit instruments with [lidia](https://pypi.org/project/lidia) Python package.
|
||||||
|
|
||||||
## License
|
Named in this order so not everything starts with the same word.
|
||||||
|
|
||||||
Source code available under the terms of [The MIT License](https://opensource.org/license/mit).
|
## Usage
|
||||||
Other assets available under [Creative Commons Attribution 4.0 (CC-BY)](https://creativecommons.org/licenses/by/4.0/).
|
|
||||||
|
The application will attempt to start in VR, but if it fails it will display the default pilot viewpoint looking forward.
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
These can be modified over MAVLink, for example using MARSH Manager.
|
||||||
|
|
||||||
|
Example changes to `NAV_OFS_` parameters to start in given positions:
|
||||||
|
|
||||||
|
- Sidestep, vertical repositioning: all default
|
||||||
|
- Accelerate/decelerate: `HDG` = -90
|
||||||
|
- Hover maneuver: `X` = 50, `Y` = 50
|
||||||
|
- Start of slalom: `HDG` = -90, `X` = -100, `Y` = 300
|
||||||
|
|
||||||
|
#### NAV_OFS_HDG
|
||||||
|
|
||||||
|
Displayed heading relative to default position, in degrees.
|
||||||
|
|
||||||
|
#### NAV_OFS_X
|
||||||
|
|
||||||
|
Starting position offset, forward in default orientation, in meters.
|
||||||
|
|
||||||
|
#### NAV_OFS_X
|
||||||
|
|
||||||
|
Starting position offset, right in default orientation, in meters.
|
||||||
|
|
||||||
|
#### LOCAL_FRAME_LAT
|
||||||
|
|
||||||
|
Latitude of local coordinate frame origin when using messages with global position, in degrees.
|
||||||
|
|
||||||
|
#### LOCAL_FRAME_LON
|
||||||
|
|
||||||
|
Longitude of local coordinate frame origin when using messages with global position, in degrees.
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
The asset files like textures and models are very big, so the project also uses [Git Large File Storage](https://git-lfs.com/).
|
||||||
|
Once installed, it should work correctly with usual `git` commands but you may need to run this if you install it after cloning the repository:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git lfs pull
|
||||||
|
```
|
||||||
|
|
||||||
|
This repository uses [Git Submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules), to get all the code you need to run either:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone --recurse-submodules <address of this repository>
|
||||||
|
# Or at any later point
|
||||||
|
git submodule update --init --recursive
|
||||||
|
```
|
||||||
|
|
||||||
|
Using Godot v4.4.
|
||||||
|
Install SCons with `pipx install scons`.
|
||||||
|
You will need a C++ compiler, you might have one already on Linux, see below for Windows, otherwise in [Godot documentation](https://docs.godotengine.org/en/stable/contributing/development/compiling/index.html).
|
||||||
|
|
||||||
|
For updating MAVLink generator, you additionally `pip install future`.
|
||||||
|
It is recommended to install any packages in a [virtual environment](https://docs.python.org/3/library/venv.html), for example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
python3 -m venv venv
|
||||||
|
source venv/bin/activate
|
||||||
|
pip install future
|
||||||
|
```
|
||||||
|
|
||||||
|
Some files are generated, run the following commands on first setup and when dependencies change:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
godot --dump-extension-api # after updating Godot
|
||||||
|
python update_mavlink.py # after updating MAVLink dialect
|
||||||
|
python update_addons.py # after changing any addon submodules
|
||||||
|
scons compile_commands # after modifying SConstruct
|
||||||
|
cd project/addons/gdcef; python build.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows setup
|
||||||
|
|
||||||
|
The most convenient way of getting a C++ compiler is via the LLVM-MinGW project (by the way, it optimizes the binary more).
|
||||||
|
Download the `llvm-mingw-...-msvcrt-x86_64.zip` from the [Releases page](https://github.com/mstorsjo/llvm-mingw/releases).
|
||||||
|
Unzip the archive to some location you like, and add its `bin` folder to `Path` using the "Edit environment variables for your account" program.
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
To build the GDExtension binary run SCons in the repository root, the default arguments have been added to the file.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scons
|
||||||
|
```
|
||||||
|
|
||||||
|
When building for Windows with MinGW-LLVM, you need to [select this compiler](https://docs.godotengine.org/en/stable/contributing/development/compiling/compiling_for_windows.html#selecting-a-compiler):
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
scons platform=windows use_mingw=yes use_llvm=yes
|
||||||
|
```
|
||||||
|
|
||||||
|
## Roadmap
|
||||||
|
|
||||||
|
- Try to have some acceptable setup for Varjo even without the tracker
|
||||||
|
- Rework the fly area
|
||||||
|
- Make it bigger
|
||||||
|
- Keep it square to avoid assymetric geometry
|
||||||
|
- Don't use the flat plane, just flatten the terrain
|
||||||
|
- Make the terrain mostly green, but add some small patches of different color
|
||||||
|
- Fix z-figthing when looking at the runway from afar
|
||||||
|
- Reduce pixel artifacts
|
||||||
|
- Adjust antialiasing
|
||||||
|
- Ensure there are mipmaps and they're used
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
[tools]
|
|
||||||
clangd = "latest"
|
|
||||||
"pipx:scons" = "latest"
|
|
||||||
|
|
@ -1264,11 +1264,9 @@ surface_material_override/0 = SubResource("StandardMaterial3D_073i7")
|
||||||
|
|
||||||
[node name="Cone80cm" parent="Sidestep/Marques_0ft" instance=ExtResource("2_hj5f7")]
|
[node name="Cone80cm" parent="Sidestep/Marques_0ft" instance=ExtResource("2_hj5f7")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -2.438)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -2.438)
|
||||||
visible = false
|
|
||||||
|
|
||||||
[node name="Cone80cm3" parent="Sidestep/Marques_0ft" instance=ExtResource("2_hj5f7")]
|
[node name="Cone80cm3" parent="Sidestep/Marques_0ft" instance=ExtResource("2_hj5f7")]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 2.438)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 2.438)
|
||||||
visible = false
|
|
||||||
|
|
||||||
[node name="Carre_ext_400ft" type="Node3D" parent="Sidestep"]
|
[node name="Carre_ext_400ft" type="Node3D" parent="Sidestep"]
|
||||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 121.92, 0, 0)
|
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 121.92, 0, 0)
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,15 @@
|
||||||
extends Node3D
|
extends Node3D
|
||||||
|
|
||||||
signal use_fallback(active: bool)
|
signal use_fallback(active: bool)
|
||||||
signal fog_density_changed(new_density: float)
|
|
||||||
|
|
||||||
## Rotation of cyclic stick model for full control deflection, in degrees
|
## Rotation of cyclic stick model for full control deflection, in degrees
|
||||||
@export var range_cyclic: float = 30
|
@export var range_cyclic: float = 30
|
||||||
## Main rotor speed, in revolutions per minute
|
## Main rotor speed, in revolutions per minute
|
||||||
@export var rotor_rpm: float = 500
|
@export var rotor_rpm: float = 500
|
||||||
@export var track_platform: bool = false
|
@export var track_platform: bool = false
|
||||||
@export var fog_values: Array[float] = [0.0, -1.0, -2.0, -3.0, -4.0]
|
|
||||||
|
|
||||||
## Current angle of rotor rotation
|
## Current angle of rotor rotation
|
||||||
var _rotor_azimuth: float = 0
|
var _rotor_azimuth: float = 0
|
||||||
var fog_index: int = 0
|
|
||||||
|
|
||||||
@onready var connector: MarshConnector = $MarshConnector
|
@onready var connector: MarshConnector = $MarshConnector
|
||||||
@onready var skeleton: Skeleton3D = $"Mi-2/Armature/Skeleton3D"
|
@onready var skeleton: Skeleton3D = $"Mi-2/Armature/Skeleton3D"
|
||||||
|
|
@ -28,8 +25,6 @@ var fog_index: int = 0
|
||||||
@onready var bone_cyclic: int = skeleton.find_bone("Cyclic")
|
@onready var bone_cyclic: int = skeleton.find_bone("Cyclic")
|
||||||
@onready var bone_rotor: int = skeleton.find_bone("Rotor")
|
@onready var bone_rotor: int = skeleton.find_bone("Rotor")
|
||||||
|
|
||||||
@onready var instruments: Node = $AttitudeRoot/Instruments
|
|
||||||
|
|
||||||
func _process(delta: float) -> void:
|
func _process(delta: float) -> void:
|
||||||
var target: Transform3D = connector.get_aircraft()
|
var target: Transform3D = connector.get_aircraft()
|
||||||
position = target.origin
|
position = target.origin
|
||||||
|
|
@ -48,11 +43,6 @@ func _process(delta: float) -> void:
|
||||||
var cyc_angles_rad: Vector2 = cyclic * deg_to_rad(range_cyclic)
|
var cyc_angles_rad: Vector2 = cyclic * deg_to_rad(range_cyclic)
|
||||||
var cyc_att := Quaternion.from_euler(Vector3(cyc_angles_rad.y, cyc_angles_rad.x, 0))
|
var cyc_att := Quaternion.from_euler(Vector3(cyc_angles_rad.y, cyc_angles_rad.x, 0))
|
||||||
skeleton.set_bone_pose_rotation(bone_cyclic, cyc_att * cyc_rest)
|
skeleton.set_bone_pose_rotation(bone_cyclic, cyc_att * cyc_rest)
|
||||||
|
|
||||||
# Update the instruments
|
|
||||||
instruments.call("set_controls", connector.get_controls())
|
|
||||||
instruments.call("set_trim", connector.get_trim())
|
|
||||||
instruments.call("update_pfd", connector.get_aircraft(), connector.get_velocity())
|
|
||||||
|
|
||||||
# Spin the rotor only when receiving flight data
|
# Spin the rotor only when receiving flight data
|
||||||
if connector.get_model_connected():
|
if connector.get_model_connected():
|
||||||
|
|
@ -68,14 +58,6 @@ func _process(delta: float) -> void:
|
||||||
xr_origin.transform = tracker_mount.transform * tracker.transform.affine_inverse()
|
xr_origin.transform = tracker_mount.transform * tracker.transform.affine_inverse()
|
||||||
recent_tracking.start()
|
recent_tracking.start()
|
||||||
|
|
||||||
func _input(event):
|
|
||||||
if event.is_action_pressed("fog_cycle"):
|
|
||||||
var step = 1
|
|
||||||
if event is InputEventWithModifiers and event.shift_pressed:
|
|
||||||
step = -1
|
|
||||||
# The index is updated in the signal callback to handle parameter changes
|
|
||||||
connector.fog_density = fog_values[(fog_index + step) % len(fog_values)]
|
|
||||||
|
|
||||||
# Only reset the position when tracking is lost for some time
|
# Only reset the position when tracking is lost for some time
|
||||||
func _on_recent_tracking_timeout() -> void:
|
func _on_recent_tracking_timeout() -> void:
|
||||||
xr_origin.transform = Transform3D.IDENTITY
|
xr_origin.transform = Transform3D.IDENTITY
|
||||||
|
|
@ -83,14 +65,3 @@ func _on_recent_tracking_timeout() -> void:
|
||||||
func _on_vr_setup_failed() -> void:
|
func _on_vr_setup_failed() -> void:
|
||||||
xr_camera.current = false
|
xr_camera.current = false
|
||||||
use_fallback.emit(true)
|
use_fallback.emit(true)
|
||||||
|
|
||||||
func _on_marsh_connector_fog_density_changed(new_density: float) -> void:
|
|
||||||
# Forward to parent
|
|
||||||
fog_density_changed.emit(new_density)
|
|
||||||
|
|
||||||
# Round down to nearest defined value or assign the last one (so it will disable on next cycle)
|
|
||||||
# Example: -1.5 should select -2 and on next cycle it will be -3
|
|
||||||
var new_index = fog_values.find_custom(func (d): return d <= new_density)
|
|
||||||
if new_index == -1:
|
|
||||||
new_index = len(fog_values) - 1
|
|
||||||
fog_index = new_index
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
[ext_resource type="Script" uid="uid://cx30pr7kn4c74" path="res://aircraft/aircraft.gd" id="1_l4uib"]
|
[ext_resource type="Script" uid="uid://cx30pr7kn4c74" path="res://aircraft/aircraft.gd" id="1_l4uib"]
|
||||||
[ext_resource type="PackedScene" uid="uid://cux4tju0ovvly" path="res://assets/mi2/Mi-2.glb" id="1_mrxe8"]
|
[ext_resource type="PackedScene" uid="uid://cux4tju0ovvly" path="res://assets/mi2/Mi-2.glb" id="1_mrxe8"]
|
||||||
[ext_resource type="PackedScene" uid="uid://fmygcraoturj" path="res://reference_axes.tscn" id="3_2bi7g"]
|
[ext_resource type="PackedScene" uid="uid://fmygcraoturj" path="res://reference_axes.tscn" id="3_2bi7g"]
|
||||||
[ext_resource type="PackedScene" uid="uid://cis4s43ubuynp" path="res://instruments/instruments.tscn" id="3_5w717"]
|
[ext_resource type="PackedScene" uid="uid://cis4s43ubuynp" path="res://instruments.tscn" id="3_5w717"]
|
||||||
[ext_resource type="Script" uid="uid://bt32fse84itrp" path="res://aircraft/fallback_input.gd" id="3_gf6ud"]
|
[ext_resource type="Script" uid="uid://bt32fse84itrp" path="res://aircraft/fallback_input.gd" id="3_gf6ud"]
|
||||||
|
|
||||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_mrxe8"]
|
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_mrxe8"]
|
||||||
|
|
@ -66,11 +66,11 @@ fov = 60.0
|
||||||
|
|
||||||
[node name="Instruments" parent="AttitudeRoot" instance=ExtResource("3_5w717")]
|
[node name="Instruments" parent="AttitudeRoot" instance=ExtResource("3_5w717")]
|
||||||
transform = Transform3D(-0.5, -1.27582e-08, 7.43353e-08, 4.33325e-10, 0.4923, 0.0874084, -7.5421e-08, 0.0874084, -0.4923, 0.00724897, -1.1581, 2.40391)
|
transform = Transform3D(-0.5, -1.27582e-08, 7.43353e-08, 4.33325e-10, 0.4923, 0.0874084, -7.5421e-08, 0.0874084, -0.4923, 0.00724897, -1.1581, 2.40391)
|
||||||
|
lidia_hostname = "127.0.0.1"
|
||||||
|
|
||||||
[node name="MarshConnector" type="MarshConnector" parent="."]
|
[node name="MarshConnector" type="MarshConnector" parent="."]
|
||||||
|
|
||||||
[connection signal="use_fallback" from="." to="AttitudeRoot/PilotEyes" method="_on_aircraft_use_fallback"]
|
[connection signal="use_fallback" from="." to="AttitudeRoot/PilotEyes" method="_on_aircraft_use_fallback"]
|
||||||
[connection signal="timeout" from="AttitudeRoot/PilotEyes/PilotFloor/XROrigin3D/RecentTracking" to="." method="_on_recent_tracking_timeout"]
|
[connection signal="timeout" from="AttitudeRoot/PilotEyes/PilotFloor/XROrigin3D/RecentTracking" to="." method="_on_recent_tracking_timeout"]
|
||||||
[connection signal="fog_density_changed" from="MarshConnector" to="." method="_on_marsh_connector_fog_density_changed"]
|
|
||||||
|
|
||||||
[editable path="Mi-2"]
|
[editable path="Mi-2"]
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,9 @@ const CAMERA_X_ROT_MIN := deg_to_rad(-85)
|
||||||
const CAMERA_X_ROT_MAX := deg_to_rad(70)
|
const CAMERA_X_ROT_MAX := deg_to_rad(70)
|
||||||
|
|
||||||
@export var use_mouse: bool = true
|
@export var use_mouse: bool = true
|
||||||
@export var pov_move_speed = 0.05
|
|
||||||
|
|
||||||
var active: bool = false
|
var active: bool = false
|
||||||
var initial_rotation: Vector3
|
var initial_rotation: Vector3
|
||||||
var initial_pov_position: Vector3
|
|
||||||
|
|
||||||
@onready var camera_base = $"."
|
@onready var camera_base = $"."
|
||||||
@onready var camera = $FallbackCamera
|
@onready var camera = $FallbackCamera
|
||||||
|
|
@ -22,7 +20,6 @@ func _ready() -> void:
|
||||||
set_process(false)
|
set_process(false)
|
||||||
set_process_input(false)
|
set_process_input(false)
|
||||||
initial_rotation = camera.rotation
|
initial_rotation = camera.rotation
|
||||||
initial_pov_position = position
|
|
||||||
|
|
||||||
func _on_aircraft_use_fallback(active_in: bool) -> void:
|
func _on_aircraft_use_fallback(active_in: bool) -> void:
|
||||||
if active_in:
|
if active_in:
|
||||||
|
|
@ -54,15 +51,7 @@ func _input(event):
|
||||||
if use_mouse and event is InputEventMouseMotion:
|
if use_mouse and event is InputEventMouseMotion:
|
||||||
var camera_speed_this_frame = CAMERA_MOUSE_ROTATION_SPEED
|
var camera_speed_this_frame = CAMERA_MOUSE_ROTATION_SPEED
|
||||||
rotate_camera(event.relative * camera_speed_this_frame * scale_factor)
|
rotate_camera(event.relative * camera_speed_this_frame * scale_factor)
|
||||||
|
|
||||||
if event.is_action_pressed("pov_reset"):
|
|
||||||
position = initial_pov_position
|
|
||||||
|
|
||||||
func _process(delta: float):
|
|
||||||
var horizontal = Input.get_vector("pov_left", "pov_right", "pov_forward", "pov_back")
|
|
||||||
var vertical = Input.get_axis("pov_down", "pov_up")
|
|
||||||
# Currently PilotEyes has Yaw 180, so horizontal axes need to be inverted
|
|
||||||
position += delta * pov_move_speed * Vector3(-horizontal.x, vertical, -horizontal.y)
|
|
||||||
|
|
||||||
func rotate_camera(move):
|
func rotate_camera(move):
|
||||||
camera_base.rotate_y(-move.x)
|
camera_base.rotate_y(-move.x)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
extends WorldEnvironment
|
|
||||||
|
|
||||||
func _on_fog_density_changed(new_density: float) -> void:
|
|
||||||
if new_density == 0.0 or not is_finite(new_density):
|
|
||||||
environment.fog_enabled = false
|
|
||||||
else:
|
|
||||||
environment.fog_enabled = true
|
|
||||||
environment.fog_density = 10 ** new_density
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
uid://6g3b2ohwbkyv
|
|
||||||
|
|
@ -1,12 +1,33 @@
|
||||||
extends Node
|
extends Node
|
||||||
|
|
||||||
@onready var controls: Node = $SubViewport2/Controls
|
const PFD_PATH: String = "pfd#adi,vsi,alt,ias,rht,rpm,hsi"
|
||||||
@onready var pfd: Node = $SubViewport/PFD
|
const CONTROLS_PATH: String = "controls#collective,cyclic,rudder"
|
||||||
|
|
||||||
# Propagate the calls to child
|
@export var lidia_hostname: String = "localhost"
|
||||||
func set_controls(current: Vector4):
|
@export var lidia_port: int = 5555
|
||||||
controls.set("controls", current)
|
|
||||||
func set_trim(trim: Vector4):
|
func _ready():
|
||||||
controls.set("trim", trim)
|
if !$CEF.initialize({"incognito":true, "locale":"en-US"}):
|
||||||
func update_pfd(aircraft: Transform3D, velocity: Vector3):
|
push_error($CEF.get_error())
|
||||||
pfd.call("update", aircraft, velocity)
|
get_tree().quit()
|
||||||
|
return
|
||||||
|
print("CEF version: " + $CEF.get_full_version())
|
||||||
|
|
||||||
|
# Wait one frame for the texture rect to get its size
|
||||||
|
await get_tree().process_frame
|
||||||
|
|
||||||
|
var browser_pfd = $CEF.create_browser(
|
||||||
|
"http://{}:{}/{}".format([lidia_hostname, lidia_port, PFD_PATH], "{}"),
|
||||||
|
$SubViewport/TextureRect,
|
||||||
|
{ "frame_rate": 90, "javascript": true },
|
||||||
|
)
|
||||||
|
browser_pfd.name = "pfd"
|
||||||
|
browser_pfd.enable_ad_block(false) # Required for lidia static assets
|
||||||
|
|
||||||
|
var browser_ctrl = $CEF.create_browser(
|
||||||
|
"http://{}:{}/{}".format([lidia_hostname, lidia_port, CONTROLS_PATH], "{}"),
|
||||||
|
$SubViewport2/TextureRect,
|
||||||
|
{ "frame_rate": 90, "javascript": true },
|
||||||
|
)
|
||||||
|
browser_ctrl.name = "controls"
|
||||||
|
browser_ctrl.enable_ad_block(false) # Required for lidia static assets
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
[gd_scene load_steps=9 format=3 uid="uid://cis4s43ubuynp"]
|
[gd_scene load_steps=7 format=3 uid="uid://cis4s43ubuynp"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://01bmfj4wthwg" path="res://instruments.gd" id="1_wlkep"]
|
[ext_resource type="Script" uid="uid://01bmfj4wthwg" path="res://instruments.gd" id="1_h5at3"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bgkpwebqksth5" path="res://instruments/controls.tscn" id="2_372d7"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://b26tu6wb2h3ce" path="res://instruments/pfd.tscn" id="2_uhiu3"]
|
|
||||||
|
|
||||||
[sub_resource type="QuadMesh" id="QuadMesh_nowl7"]
|
[sub_resource type="QuadMesh" id="QuadMesh_nowl7"]
|
||||||
|
|
||||||
|
|
@ -21,12 +19,15 @@ resource_local_to_scene = true
|
||||||
albedo_texture = SubResource("ViewportTexture_h5at3")
|
albedo_texture = SubResource("ViewportTexture_h5at3")
|
||||||
|
|
||||||
[node name="Instruments" type="Node3D"]
|
[node name="Instruments" type="Node3D"]
|
||||||
script = ExtResource("1_wlkep")
|
script = ExtResource("1_h5at3")
|
||||||
|
lidia_hostname = "192.168.1.2"
|
||||||
|
|
||||||
[node name="SubViewport" type="SubViewport" parent="."]
|
[node name="SubViewport" type="SubViewport" parent="."]
|
||||||
size = Vector2i(1024, 1024)
|
|
||||||
|
|
||||||
[node name="PFD" parent="SubViewport" instance=ExtResource("2_uhiu3")]
|
[node name="TextureRect" type="TextureRect" parent="SubViewport"]
|
||||||
|
offset_right = 512.0
|
||||||
|
offset_bottom = 512.0
|
||||||
|
expand_mode = 5
|
||||||
|
|
||||||
[node name="Quad" type="MeshInstance3D" parent="."]
|
[node name="Quad" type="MeshInstance3D" parent="."]
|
||||||
transform = Transform3D(0.8, 0, 0, 0, 0.8, 0, 0, 0, 0.8, -0.35, 0, 0)
|
transform = Transform3D(0.8, 0, 0, 0, 0.8, 0, 0, 0, 0.8, -0.35, 0, 0)
|
||||||
|
|
@ -35,7 +36,10 @@ surface_material_override/0 = SubResource("StandardMaterial3D_h5at3")
|
||||||
|
|
||||||
[node name="SubViewport2" type="SubViewport" parent="."]
|
[node name="SubViewport2" type="SubViewport" parent="."]
|
||||||
|
|
||||||
[node name="Controls" parent="SubViewport2" instance=ExtResource("2_372d7")]
|
[node name="TextureRect" type="TextureRect" parent="SubViewport2"]
|
||||||
|
offset_right = 512.0
|
||||||
|
offset_bottom = 512.0
|
||||||
|
expand_mode = 5
|
||||||
|
|
||||||
[node name="Quad2" type="MeshInstance3D" parent="."]
|
[node name="Quad2" type="MeshInstance3D" parent="."]
|
||||||
transform = Transform3D(0.6, 0, 0, 0, 0.6, 0, 0, 0, 0.6, 0.425, 0, 0)
|
transform = Transform3D(0.6, 0, 0, 0, 0.6, 0, 0, 0, 0.6, 0.425, 0, 0)
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
Roboto Mono
|
|
||||||
|
|
||||||
Copyright 2015 Google
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
=====================================================================
|
|
||||||
|
|
||||||
Socket.IO
|
|
||||||
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2014-2022 Guillermo Rauch
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
Binary file not shown.
|
|
@ -1,35 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="font_data_dynamic"
|
|
||||||
type="FontFile"
|
|
||||||
uid="uid://chqgmpsthpbgt"
|
|
||||||
path="res://.godot/imported/RobotoMono-Regular.ttf-48a8b9dfd581c05f54f90e11c9fc9d5f.fontdata"
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://instruments/RobotoMono-Regular.ttf"
|
|
||||||
dest_files=["res://.godot/imported/RobotoMono-Regular.ttf-48a8b9dfd581c05f54f90e11c9fc9d5f.fontdata"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
Rendering=null
|
|
||||||
antialiasing=1
|
|
||||||
generate_mipmaps=false
|
|
||||||
disable_embedded_bitmaps=true
|
|
||||||
multichannel_signed_distance_field=false
|
|
||||||
msdf_pixel_range=8
|
|
||||||
msdf_size=48
|
|
||||||
allow_system_fallback=true
|
|
||||||
force_autohinter=false
|
|
||||||
hinting=1
|
|
||||||
subpixel_positioning=4
|
|
||||||
keep_rounding_remainders=true
|
|
||||||
oversampling=0.0
|
|
||||||
Fallbacks=null
|
|
||||||
fallbacks=[]
|
|
||||||
Compress=null
|
|
||||||
compress=true
|
|
||||||
preload=[]
|
|
||||||
language_support={}
|
|
||||||
script_support={}
|
|
||||||
opentype_features={}
|
|
||||||
BIN
project/instruments/controls-background.png
(Stored with Git LFS)
BIN
project/instruments/controls-background.png
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,34 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="CompressedTexture2D"
|
|
||||||
uid="uid://b0oeokas7mq4q"
|
|
||||||
path="res://.godot/imported/controls-background.png-626db610a70b7b467da1123d55529d5c.ctex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://instruments/controls-background.png"
|
|
||||||
dest_files=["res://.godot/imported/controls-background.png-626db610a70b7b467da1123d55529d5c.ctex"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/high_quality=false
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_compression=1
|
|
||||||
compress/normal_map=0
|
|
||||||
compress/channel_pack=0
|
|
||||||
mipmaps/generate=false
|
|
||||||
mipmaps/limit=-1
|
|
||||||
roughness/mode=0
|
|
||||||
roughness/src_normal=""
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
process/hdr_as_srgb=false
|
|
||||||
process/hdr_clamp_exposure=false
|
|
||||||
process/size_limit=0
|
|
||||||
detect_3d/compress_to=1
|
|
||||||
BIN
project/instruments/controls-ref.png
(Stored with Git LFS)
BIN
project/instruments/controls-ref.png
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,34 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="CompressedTexture2D"
|
|
||||||
uid="uid://c5bcvbphgg1nk"
|
|
||||||
path="res://.godot/imported/controls-ref.png-ed1b9d803223424fa895ad19151b7e9f.ctex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://instruments/controls-ref.png"
|
|
||||||
dest_files=["res://.godot/imported/controls-ref.png-ed1b9d803223424fa895ad19151b7e9f.ctex"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/high_quality=false
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_compression=1
|
|
||||||
compress/normal_map=0
|
|
||||||
compress/channel_pack=0
|
|
||||||
mipmaps/generate=false
|
|
||||||
mipmaps/limit=-1
|
|
||||||
roughness/mode=0
|
|
||||||
roughness/src_normal=""
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
process/hdr_as_srgb=false
|
|
||||||
process/hdr_clamp_exposure=false
|
|
||||||
process/size_limit=0
|
|
||||||
detect_3d/compress_to=1
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
@tool
|
|
||||||
class_name Controls
|
|
||||||
extends Node2D
|
|
||||||
## Recreate the controls page from lidia Python package
|
|
||||||
|
|
||||||
const AXIS_SIZE: float = 326
|
|
||||||
|
|
||||||
@export var controls: Vector4:
|
|
||||||
set(value):
|
|
||||||
controls = value
|
|
||||||
current_cyclic.position.x = AXIS_SIZE / 2.0 * controls.x
|
|
||||||
current_cyclic.position.y = AXIS_SIZE / 2.0 * controls.y
|
|
||||||
current_pedals.position.x = AXIS_SIZE / 2.0 * controls.z
|
|
||||||
current_collective.position.y = -AXIS_SIZE * controls.w
|
|
||||||
|
|
||||||
@export var trim: Vector4:
|
|
||||||
set(value):
|
|
||||||
trim = value
|
|
||||||
trim_lateral.position.x = AXIS_SIZE / 2.0 * trim.x
|
|
||||||
trim_longitudinal.position.y = AXIS_SIZE / 2.0 * trim.y
|
|
||||||
trim_pedals.position.x = AXIS_SIZE / 2.0 * trim.z
|
|
||||||
trim_collective.position.y = -AXIS_SIZE * trim.w
|
|
||||||
|
|
||||||
@onready var trim_longitudinal: Node2D = $CyclicOrigin/TrimLongitudinal
|
|
||||||
@onready var trim_lateral: Node2D = $CyclicOrigin/TrimLateral
|
|
||||||
@onready var current_cyclic: Node2D = $CyclicOrigin/CurrentCyclic
|
|
||||||
@onready var trim_collective: Node2D = $CollectiveOrigin/TrimCollective
|
|
||||||
@onready var current_collective: Node2D = $CollectiveOrigin/CurrentCollective
|
|
||||||
@onready var trim_pedals: Node2D = $PedalsOrigin/TrimPedals
|
|
||||||
@onready var current_pedals: Node2D = $PedalsOrigin/CurrentPedals
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
uid://ds6f8cur05ka0
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
[gd_scene load_steps=7 format=3 uid="uid://bgkpwebqksth5"]
|
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://ds6f8cur05ka0" path="res://instruments/controls.gd" id="1_g7kvs"]
|
|
||||||
[ext_resource type="Texture2D" uid="uid://b0oeokas7mq4q" path="res://instruments/controls-background.png" id="2_wbvwt"]
|
|
||||||
[ext_resource type="Texture2D" uid="uid://c561m3pvc0kop" path="res://instruments/trim-long.png" id="3_37ekc"]
|
|
||||||
[ext_resource type="Texture2D" uid="uid://wdqnlguxmi2a" path="res://instruments/current-dot.png" id="4_4updv"]
|
|
||||||
[ext_resource type="Texture2D" uid="uid://dytpn8rcdimr" path="res://instruments/trim-short.png" id="5_ni3tk"]
|
|
||||||
[ext_resource type="Texture2D" uid="uid://dkda6ju5daocf" path="res://instruments/current-arrow.png" id="6_mfntf"]
|
|
||||||
|
|
||||||
[node name="Controls" type="Node2D"]
|
|
||||||
script = ExtResource("1_g7kvs")
|
|
||||||
|
|
||||||
[node name="Background" type="Sprite2D" parent="."]
|
|
||||||
position = Vector2(256, 256)
|
|
||||||
texture = ExtResource("2_wbvwt")
|
|
||||||
|
|
||||||
[node name="CyclicOrigin" type="Node2D" parent="."]
|
|
||||||
position = Vector2(309, 189)
|
|
||||||
|
|
||||||
[node name="TrimLongitudinal" type="Sprite2D" parent="CyclicOrigin"]
|
|
||||||
position = Vector2(10, 0)
|
|
||||||
texture = ExtResource("3_37ekc")
|
|
||||||
|
|
||||||
[node name="TrimLateral" type="Sprite2D" parent="CyclicOrigin"]
|
|
||||||
position = Vector2(0, 10)
|
|
||||||
rotation = 1.5708
|
|
||||||
texture = ExtResource("3_37ekc")
|
|
||||||
|
|
||||||
[node name="CurrentCyclic" type="Sprite2D" parent="CyclicOrigin"]
|
|
||||||
texture = ExtResource("4_4updv")
|
|
||||||
|
|
||||||
[node name="CollectiveOrigin" type="Node2D" parent="."]
|
|
||||||
position = Vector2(72.5, 352)
|
|
||||||
|
|
||||||
[node name="TrimCollective" type="Sprite2D" parent="CollectiveOrigin"]
|
|
||||||
position = Vector2(-10.5, 0)
|
|
||||||
texture = ExtResource("5_ni3tk")
|
|
||||||
|
|
||||||
[node name="CurrentCollective" type="Sprite2D" parent="CollectiveOrigin"]
|
|
||||||
position = Vector2(20.5, 0)
|
|
||||||
texture = ExtResource("6_mfntf")
|
|
||||||
|
|
||||||
[node name="PedalsOrigin" type="Node2D" parent="."]
|
|
||||||
position = Vector2(309, 425.5)
|
|
||||||
|
|
||||||
[node name="TrimPedals" type="Sprite2D" parent="PedalsOrigin"]
|
|
||||||
position = Vector2(0, 10.5)
|
|
||||||
rotation = -1.5708
|
|
||||||
texture = ExtResource("5_ni3tk")
|
|
||||||
|
|
||||||
[node name="CurrentPedals" type="Sprite2D" parent="PedalsOrigin"]
|
|
||||||
position = Vector2(0, -21.5)
|
|
||||||
rotation = -1.5708
|
|
||||||
texture = ExtResource("6_mfntf")
|
|
||||||
BIN
project/instruments/current-arrow.png
(Stored with Git LFS)
BIN
project/instruments/current-arrow.png
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,34 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="CompressedTexture2D"
|
|
||||||
uid="uid://dkda6ju5daocf"
|
|
||||||
path="res://.godot/imported/current-arrow.png-8e092288abc9ec8d31cbc8f708a9c800.ctex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://instruments/current-arrow.png"
|
|
||||||
dest_files=["res://.godot/imported/current-arrow.png-8e092288abc9ec8d31cbc8f708a9c800.ctex"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/high_quality=false
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_compression=1
|
|
||||||
compress/normal_map=0
|
|
||||||
compress/channel_pack=0
|
|
||||||
mipmaps/generate=false
|
|
||||||
mipmaps/limit=-1
|
|
||||||
roughness/mode=0
|
|
||||||
roughness/src_normal=""
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
process/hdr_as_srgb=false
|
|
||||||
process/hdr_clamp_exposure=false
|
|
||||||
process/size_limit=0
|
|
||||||
detect_3d/compress_to=1
|
|
||||||
BIN
project/instruments/current-dot.png
(Stored with Git LFS)
BIN
project/instruments/current-dot.png
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,34 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="CompressedTexture2D"
|
|
||||||
uid="uid://wdqnlguxmi2a"
|
|
||||||
path="res://.godot/imported/current-dot.png-789da8759af9526ce5f8705121a1077d.ctex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://instruments/current-dot.png"
|
|
||||||
dest_files=["res://.godot/imported/current-dot.png-789da8759af9526ce5f8705121a1077d.ctex"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/high_quality=false
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_compression=1
|
|
||||||
compress/normal_map=0
|
|
||||||
compress/channel_pack=0
|
|
||||||
mipmaps/generate=false
|
|
||||||
mipmaps/limit=-1
|
|
||||||
roughness/mode=0
|
|
||||||
roughness/src_normal=""
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
process/hdr_as_srgb=false
|
|
||||||
process/hdr_clamp_exposure=false
|
|
||||||
process/size_limit=0
|
|
||||||
detect_3d/compress_to=1
|
|
||||||
BIN
project/instruments/heading-ticks.png
(Stored with Git LFS)
BIN
project/instruments/heading-ticks.png
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,34 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="CompressedTexture2D"
|
|
||||||
uid="uid://c36kaqyfalb2v"
|
|
||||||
path="res://.godot/imported/heading-ticks.png-8d0b08e5e3af463192c04d5a2068a1e0.ctex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://instruments/heading-ticks.png"
|
|
||||||
dest_files=["res://.godot/imported/heading-ticks.png-8d0b08e5e3af463192c04d5a2068a1e0.ctex"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/high_quality=false
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_compression=1
|
|
||||||
compress/normal_map=0
|
|
||||||
compress/channel_pack=0
|
|
||||||
mipmaps/generate=false
|
|
||||||
mipmaps/limit=-1
|
|
||||||
roughness/mode=0
|
|
||||||
roughness/src_normal=""
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
process/hdr_as_srgb=false
|
|
||||||
process/hdr_clamp_exposure=false
|
|
||||||
process/size_limit=0
|
|
||||||
detect_3d/compress_to=1
|
|
||||||
BIN
project/instruments/horizon-mask.png
(Stored with Git LFS)
BIN
project/instruments/horizon-mask.png
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,34 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="CompressedTexture2D"
|
|
||||||
uid="uid://c5nbrnus8pcyd"
|
|
||||||
path="res://.godot/imported/horizon-mask.png-03d2bafdd84b9816ae1fe68fc4baf43d.ctex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://instruments/horizon-mask.png"
|
|
||||||
dest_files=["res://.godot/imported/horizon-mask.png-03d2bafdd84b9816ae1fe68fc4baf43d.ctex"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/high_quality=false
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_compression=1
|
|
||||||
compress/normal_map=0
|
|
||||||
compress/channel_pack=0
|
|
||||||
mipmaps/generate=false
|
|
||||||
mipmaps/limit=-1
|
|
||||||
roughness/mode=0
|
|
||||||
roughness/src_normal=""
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
process/hdr_as_srgb=false
|
|
||||||
process/hdr_clamp_exposure=false
|
|
||||||
process/size_limit=0
|
|
||||||
detect_3d/compress_to=1
|
|
||||||
BIN
project/instruments/horizon-overlay.png
(Stored with Git LFS)
BIN
project/instruments/horizon-overlay.png
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,34 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="CompressedTexture2D"
|
|
||||||
uid="uid://b703lu8yhaoav"
|
|
||||||
path="res://.godot/imported/horizon-overlay.png-7e128e1a0dd8183251d6119879899864.ctex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://instruments/horizon-overlay.png"
|
|
||||||
dest_files=["res://.godot/imported/horizon-overlay.png-7e128e1a0dd8183251d6119879899864.ctex"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/high_quality=false
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_compression=1
|
|
||||||
compress/normal_map=0
|
|
||||||
compress/channel_pack=0
|
|
||||||
mipmaps/generate=false
|
|
||||||
mipmaps/limit=-1
|
|
||||||
roughness/mode=0
|
|
||||||
roughness/src_normal=""
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
process/hdr_as_srgb=false
|
|
||||||
process/hdr_clamp_exposure=false
|
|
||||||
process/size_limit=0
|
|
||||||
detect_3d/compress_to=1
|
|
||||||
BIN
project/instruments/horizon.png
(Stored with Git LFS)
BIN
project/instruments/horizon.png
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,34 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="CompressedTexture2D"
|
|
||||||
uid="uid://bxdfrv8bovdai"
|
|
||||||
path="res://.godot/imported/horizon.png-9384af1095d9251c4f8861113a545ccf.ctex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://instruments/horizon.png"
|
|
||||||
dest_files=["res://.godot/imported/horizon.png-9384af1095d9251c4f8861113a545ccf.ctex"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/high_quality=false
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_compression=1
|
|
||||||
compress/normal_map=0
|
|
||||||
compress/channel_pack=0
|
|
||||||
mipmaps/generate=false
|
|
||||||
mipmaps/limit=-1
|
|
||||||
roughness/mode=0
|
|
||||||
roughness/src_normal=""
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
process/hdr_as_srgb=false
|
|
||||||
process/hdr_clamp_exposure=false
|
|
||||||
process/size_limit=0
|
|
||||||
detect_3d/compress_to=1
|
|
||||||
BIN
project/instruments/pfd-background.png
(Stored with Git LFS)
BIN
project/instruments/pfd-background.png
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,34 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="CompressedTexture2D"
|
|
||||||
uid="uid://colp4xsovikmv"
|
|
||||||
path="res://.godot/imported/pfd-background.png-99626101f4d3a30d7dd189ac71adf1c0.ctex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://instruments/pfd-background.png"
|
|
||||||
dest_files=["res://.godot/imported/pfd-background.png-99626101f4d3a30d7dd189ac71adf1c0.ctex"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/high_quality=false
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_compression=1
|
|
||||||
compress/normal_map=0
|
|
||||||
compress/channel_pack=0
|
|
||||||
mipmaps/generate=false
|
|
||||||
mipmaps/limit=-1
|
|
||||||
roughness/mode=0
|
|
||||||
roughness/src_normal=""
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
process/hdr_as_srgb=false
|
|
||||||
process/hdr_clamp_exposure=false
|
|
||||||
process/size_limit=0
|
|
||||||
detect_3d/compress_to=1
|
|
||||||
BIN
project/instruments/pfd-ref.png
(Stored with Git LFS)
BIN
project/instruments/pfd-ref.png
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,34 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="CompressedTexture2D"
|
|
||||||
uid="uid://toojp8r3424r"
|
|
||||||
path="res://.godot/imported/pfd-ref.png-18e0fc5274406321f68279cb4defcf25.ctex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://instruments/pfd-ref.png"
|
|
||||||
dest_files=["res://.godot/imported/pfd-ref.png-18e0fc5274406321f68279cb4defcf25.ctex"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/high_quality=false
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_compression=1
|
|
||||||
compress/normal_map=0
|
|
||||||
compress/channel_pack=0
|
|
||||||
mipmaps/generate=false
|
|
||||||
mipmaps/limit=-1
|
|
||||||
roughness/mode=0
|
|
||||||
roughness/src_normal=""
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
process/hdr_as_srgb=false
|
|
||||||
process/hdr_clamp_exposure=false
|
|
||||||
process/size_limit=0
|
|
||||||
detect_3d/compress_to=1
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
@tool
|
|
||||||
class_name PFD
|
|
||||||
extends Node2D
|
|
||||||
|
|
||||||
@export var euler_attitude_deg: Vector3:
|
|
||||||
set(value):
|
|
||||||
euler_attitude_deg = value
|
|
||||||
horizon_pivot.rotation = deg_to_rad(-value.x)
|
|
||||||
const px_per_deg: float = 6.56
|
|
||||||
horizon_background.position.y = px_per_deg * clamp(value.y, -30, 30)
|
|
||||||
heading_ticks.rotation = deg_to_rad(-value.z)
|
|
||||||
heading_label.text = "%03d" % (int(round(value.z) + 360) % 360)
|
|
||||||
|
|
||||||
@export var airspeed: float:
|
|
||||||
set(value):
|
|
||||||
airspeed = value
|
|
||||||
airspeed_label.text = str(int(round(value)))
|
|
||||||
|
|
||||||
@export var groundspeed: float:
|
|
||||||
set(value):
|
|
||||||
groundspeed = value
|
|
||||||
groundspeed_label.text = str(int(round(value)))
|
|
||||||
|
|
||||||
@export var altitude: float:
|
|
||||||
set(value):
|
|
||||||
altitude = value
|
|
||||||
var step = 1
|
|
||||||
altitude_label.text = str(int(step * round(value / step)))
|
|
||||||
|
|
||||||
@export var climbrate: float = 1000:
|
|
||||||
set(value):
|
|
||||||
climbrate = value
|
|
||||||
climbrate_arrow.scale.y = clamp(value / 1000.0, -1, 1)
|
|
||||||
|
|
||||||
@onready var horizon_pivot: Node2D = $HorizonMask/HorizonOrigin/Pivot
|
|
||||||
@onready var horizon_background: Node2D = $HorizonMask/HorizonOrigin/Pivot/Background
|
|
||||||
@onready var heading_ticks: Node2D = $HeadingOrigin/Ticks
|
|
||||||
@onready var climbrate_arrow: Node2D = $ClimbrateOrigin/Polygon2D
|
|
||||||
@onready var airspeed_label: Label = $Airspeed
|
|
||||||
@onready var groundspeed_label: Label = $Groundspeed
|
|
||||||
@onready var altitude_label: Label = $Altitude
|
|
||||||
@onready var heading_label: Label = $Heading
|
|
||||||
|
|
||||||
func update(aircraft: Transform3D, velocity: Vector3):
|
|
||||||
var godot_euler = aircraft.basis.get_euler()
|
|
||||||
euler_attitude_deg = Vector3(godot_euler.z, -godot_euler.x, -godot_euler.y) * rad_to_deg(1)
|
|
||||||
|
|
||||||
const mps_to_kt = 1.94384
|
|
||||||
var v_local = aircraft.basis.inverse() * velocity
|
|
||||||
airspeed = max(0, v_local.z) * mps_to_kt
|
|
||||||
var v_horizontal = Vector3(velocity.x, 0, velocity.z)
|
|
||||||
groundspeed = v_horizontal.length() * mps_to_kt
|
|
||||||
|
|
||||||
const mps_to_fpm = 196.848
|
|
||||||
climbrate = velocity.y * mps_to_fpm
|
|
||||||
|
|
||||||
const m_to_ft = 3.2808
|
|
||||||
altitude = aircraft.origin.y * m_to_ft
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
uid://368tfiyen071
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
[gd_scene load_steps=9 format=3 uid="uid://b26tu6wb2h3ce"]
|
|
||||||
|
|
||||||
[ext_resource type="Texture2D" uid="uid://colp4xsovikmv" path="res://instruments/pfd-background.png" id="1_inkqg"]
|
|
||||||
[ext_resource type="Script" uid="uid://368tfiyen071" path="res://instruments/pfd.gd" id="1_t02it"]
|
|
||||||
[ext_resource type="Texture2D" uid="uid://c5nbrnus8pcyd" path="res://instruments/horizon-mask.png" id="2_t02it"]
|
|
||||||
[ext_resource type="Texture2D" uid="uid://bxdfrv8bovdai" path="res://instruments/horizon.png" id="3_kwqn1"]
|
|
||||||
[ext_resource type="Texture2D" uid="uid://b703lu8yhaoav" path="res://instruments/horizon-overlay.png" id="4_1vq1p"]
|
|
||||||
[ext_resource type="Texture2D" uid="uid://c36kaqyfalb2v" path="res://instruments/heading-ticks.png" id="5_3w2cf"]
|
|
||||||
[ext_resource type="FontFile" uid="uid://chqgmpsthpbgt" path="res://instruments/RobotoMono-Regular.ttf" id="6_wtx4e"]
|
|
||||||
[ext_resource type="Texture2D" uid="uid://toojp8r3424r" path="res://instruments/pfd-ref.png" id="7_86xjv"]
|
|
||||||
|
|
||||||
[node name="PFD" type="Node2D"]
|
|
||||||
script = ExtResource("1_t02it")
|
|
||||||
|
|
||||||
[node name="Background" type="Sprite2D" parent="."]
|
|
||||||
position = Vector2(512, 512)
|
|
||||||
texture = ExtResource("1_inkqg")
|
|
||||||
|
|
||||||
[node name="HorizonMask" type="Sprite2D" parent="."]
|
|
||||||
clip_children = 1
|
|
||||||
position = Vector2(512, 512)
|
|
||||||
texture = ExtResource("2_t02it")
|
|
||||||
|
|
||||||
[node name="HorizonOrigin" type="Node2D" parent="HorizonMask"]
|
|
||||||
position = Vector2(-82, -244)
|
|
||||||
|
|
||||||
[node name="Pivot" type="Node2D" parent="HorizonMask/HorizonOrigin"]
|
|
||||||
|
|
||||||
[node name="Background" type="Sprite2D" parent="HorizonMask/HorizonOrigin/Pivot"]
|
|
||||||
texture = ExtResource("3_kwqn1")
|
|
||||||
|
|
||||||
[node name="RollArrowContour" type="Polygon2D" parent="HorizonMask/HorizonOrigin/Pivot"]
|
|
||||||
position = Vector2(-430, -267)
|
|
||||||
color = Color(0, 0, 0, 1)
|
|
||||||
polygon = PackedVector2Array(430, 70, 416, 92, 444, 92)
|
|
||||||
|
|
||||||
[node name="RollArrowFill" type="Polygon2D" parent="HorizonMask/HorizonOrigin/Pivot"]
|
|
||||||
position = Vector2(-430, -267)
|
|
||||||
polygon = PackedVector2Array(430, 74, 420, 90, 440, 90)
|
|
||||||
|
|
||||||
[node name="Overlay" type="Sprite2D" parent="HorizonMask/HorizonOrigin"]
|
|
||||||
texture = ExtResource("4_1vq1p")
|
|
||||||
|
|
||||||
[node name="HeadingOrigin" type="Node2D" parent="."]
|
|
||||||
position = Vector2(430, 794)
|
|
||||||
|
|
||||||
[node name="Ticks" type="Sprite2D" parent="HeadingOrigin"]
|
|
||||||
texture = ExtResource("5_3w2cf")
|
|
||||||
|
|
||||||
[node name="ClimbrateOrigin" type="Node2D" parent="."]
|
|
||||||
position = Vector2(711, 268)
|
|
||||||
|
|
||||||
[node name="Polygon2D" type="Polygon2D" parent="ClimbrateOrigin"]
|
|
||||||
polygon = PackedVector2Array(12, 0, -12, 0, -12, -121, 0, -133, 12, -121)
|
|
||||||
|
|
||||||
[node name="Airspeed" type="Label" parent="."]
|
|
||||||
offset_left = 35.0
|
|
||||||
offset_top = 233.0
|
|
||||||
offset_right = 154.0
|
|
||||||
offset_bottom = 298.0
|
|
||||||
theme_override_fonts/font = ExtResource("6_wtx4e")
|
|
||||||
theme_override_font_sizes/font_size = 48
|
|
||||||
text = "0"
|
|
||||||
horizontal_alignment = 2
|
|
||||||
vertical_alignment = 1
|
|
||||||
|
|
||||||
[node name="Groundspeed" type="Label" parent="."]
|
|
||||||
offset_left = 59.0
|
|
||||||
offset_top = 477.0
|
|
||||||
offset_right = 178.0
|
|
||||||
offset_bottom = 542.0
|
|
||||||
theme_override_fonts/font = ExtResource("6_wtx4e")
|
|
||||||
theme_override_font_sizes/font_size = 33
|
|
||||||
text = "0"
|
|
||||||
horizontal_alignment = 2
|
|
||||||
vertical_alignment = 1
|
|
||||||
|
|
||||||
[node name="Altitude" type="Label" parent="."]
|
|
||||||
offset_left = 859.0
|
|
||||||
offset_top = 233.0
|
|
||||||
offset_right = 978.0
|
|
||||||
offset_bottom = 298.0
|
|
||||||
theme_override_fonts/font = ExtResource("6_wtx4e")
|
|
||||||
theme_override_font_sizes/font_size = 48
|
|
||||||
text = "0"
|
|
||||||
horizontal_alignment = 2
|
|
||||||
vertical_alignment = 1
|
|
||||||
|
|
||||||
[node name="Heading" type="Label" parent="."]
|
|
||||||
offset_left = 370.0
|
|
||||||
offset_top = 498.0
|
|
||||||
offset_right = 489.0
|
|
||||||
offset_bottom = 563.0
|
|
||||||
theme_override_fonts/font = ExtResource("6_wtx4e")
|
|
||||||
theme_override_font_sizes/font_size = 33
|
|
||||||
text = "000"
|
|
||||||
horizontal_alignment = 1
|
|
||||||
vertical_alignment = 1
|
|
||||||
|
|
||||||
[node name="Reference" type="Sprite2D" parent="."]
|
|
||||||
visible = false
|
|
||||||
position = Vector2(512, 512)
|
|
||||||
texture = ExtResource("7_86xjv")
|
|
||||||
BIN
project/instruments/trim-long.png
(Stored with Git LFS)
BIN
project/instruments/trim-long.png
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,34 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="CompressedTexture2D"
|
|
||||||
uid="uid://c561m3pvc0kop"
|
|
||||||
path="res://.godot/imported/trim-long.png-0b9b67642209f6a2ae4b2165f3b33d5d.ctex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://instruments/trim-long.png"
|
|
||||||
dest_files=["res://.godot/imported/trim-long.png-0b9b67642209f6a2ae4b2165f3b33d5d.ctex"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/high_quality=false
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_compression=1
|
|
||||||
compress/normal_map=0
|
|
||||||
compress/channel_pack=0
|
|
||||||
mipmaps/generate=false
|
|
||||||
mipmaps/limit=-1
|
|
||||||
roughness/mode=0
|
|
||||||
roughness/src_normal=""
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
process/hdr_as_srgb=false
|
|
||||||
process/hdr_clamp_exposure=false
|
|
||||||
process/size_limit=0
|
|
||||||
detect_3d/compress_to=1
|
|
||||||
BIN
project/instruments/trim-short.png
(Stored with Git LFS)
BIN
project/instruments/trim-short.png
(Stored with Git LFS)
Binary file not shown.
|
|
@ -1,34 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="CompressedTexture2D"
|
|
||||||
uid="uid://dytpn8rcdimr"
|
|
||||||
path="res://.godot/imported/trim-short.png-707c75166ad2d77e18c02dc4882968b1.ctex"
|
|
||||||
metadata={
|
|
||||||
"vram_texture": false
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://instruments/trim-short.png"
|
|
||||||
dest_files=["res://.godot/imported/trim-short.png-707c75166ad2d77e18c02dc4882968b1.ctex"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=0
|
|
||||||
compress/high_quality=false
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_compression=1
|
|
||||||
compress/normal_map=0
|
|
||||||
compress/channel_pack=0
|
|
||||||
mipmaps/generate=false
|
|
||||||
mipmaps/limit=-1
|
|
||||||
roughness/mode=0
|
|
||||||
roughness/src_normal=""
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=false
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
process/hdr_as_srgb=false
|
|
||||||
process/hdr_clamp_exposure=false
|
|
||||||
process/size_limit=0
|
|
||||||
detect_3d/compress_to=1
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
[gd_scene load_steps=8 format=3 uid="uid://crq3o0eu4y8ya"]
|
[gd_scene load_steps=7 format=3 uid="uid://crq3o0eu4y8ya"]
|
||||||
|
|
||||||
[ext_resource type="Script" uid="uid://dfcjdxesyn3l0" path="res://start_vr.gd" id="1_ig7tw"]
|
[ext_resource type="Script" uid="uid://dfcjdxesyn3l0" path="res://start_vr.gd" id="1_ig7tw"]
|
||||||
[ext_resource type="PackedScene" uid="uid://bj1s0g7ixjw71" path="res://aircraft/aircraft.tscn" id="2_0xm2m"]
|
[ext_resource type="PackedScene" uid="uid://bj1s0g7ixjw71" path="res://aircraft/aircraft.tscn" id="2_0xm2m"]
|
||||||
[ext_resource type="Script" uid="uid://6g3b2ohwbkyv" path="res://fog_controller.gd" id="3_1bvp3"]
|
|
||||||
[ext_resource type="PackedScene" uid="uid://bchcr54i3piaw" path="res://ads33-terrain/Cones_scene_terrain.tscn" id="3_h2yge"]
|
[ext_resource type="PackedScene" uid="uid://bchcr54i3piaw" path="res://ads33-terrain/Cones_scene_terrain.tscn" id="3_h2yge"]
|
||||||
|
|
||||||
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_7dm0k"]
|
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_7dm0k"]
|
||||||
|
|
@ -13,10 +12,6 @@ sky_material = SubResource("ProceduralSkyMaterial_7dm0k")
|
||||||
[sub_resource type="Environment" id="Environment_0xm2m"]
|
[sub_resource type="Environment" id="Environment_0xm2m"]
|
||||||
background_mode = 2
|
background_mode = 2
|
||||||
sky = SubResource("Sky_ig7tw")
|
sky = SubResource("Sky_ig7tw")
|
||||||
fog_enabled = true
|
|
||||||
fog_sun_scatter = 0.5
|
|
||||||
fog_density = 0.0
|
|
||||||
fog_depth_end = 80.0
|
|
||||||
|
|
||||||
[node name="Main" type="Node3D"]
|
[node name="Main" type="Node3D"]
|
||||||
|
|
||||||
|
|
@ -26,7 +21,6 @@ fog_depth_end = 80.0
|
||||||
|
|
||||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||||
environment = SubResource("Environment_0xm2m")
|
environment = SubResource("Environment_0xm2m")
|
||||||
script = ExtResource("3_1bvp3")
|
|
||||||
|
|
||||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||||
transform = Transform3D(0.866025, 0.433013, 0.25, 0, -0.5, 0.866025, 0.5, -0.75, -0.433013, -5, 5, -5)
|
transform = Transform3D(0.866025, 0.433013, 0.25, 0, -0.5, 0.866025, 0.5, -0.75, -0.433013, -5, 5, -5)
|
||||||
|
|
@ -35,5 +29,4 @@ shadow_enabled = true
|
||||||
[node name="StartVR" type="Node3D" parent="."]
|
[node name="StartVR" type="Node3D" parent="."]
|
||||||
script = ExtResource("1_ig7tw")
|
script = ExtResource("1_ig7tw")
|
||||||
|
|
||||||
[connection signal="fog_density_changed" from="Aircraft" to="WorldEnvironment" method="_on_fog_density_changed"]
|
|
||||||
[connection signal="setup_failed" from="StartVR" to="Aircraft" method="_on_vr_setup_failed"]
|
[connection signal="setup_failed" from="StartVR" to="Aircraft" method="_on_vr_setup_failed"]
|
||||||
|
|
|
||||||
|
|
@ -25,68 +25,19 @@ window/stretch/mode="viewport"
|
||||||
|
|
||||||
enabled=PackedStringArray()
|
enabled=PackedStringArray()
|
||||||
|
|
||||||
[input]
|
|
||||||
|
|
||||||
pov_up={
|
|
||||||
"deadzone": 0.2,
|
|
||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"location":0,"echo":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
pov_down={
|
|
||||||
"deadzone": 0.2,
|
|
||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":67,"key_label":0,"unicode":99,"location":0,"echo":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
pov_forward={
|
|
||||||
"deadzone": 0.2,
|
|
||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
pov_back={
|
|
||||||
"deadzone": 0.2,
|
|
||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
pov_right={
|
|
||||||
"deadzone": 0.2,
|
|
||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"location":0,"echo":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
pov_left={
|
|
||||||
"deadzone": 0.2,
|
|
||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"location":0,"echo":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
pov_reset={
|
|
||||||
"deadzone": 0.2,
|
|
||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":81,"key_label":0,"unicode":113,"location":0,"echo":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
fog_cycle={
|
|
||||||
"deadzone": 0.2,
|
|
||||||
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":70,"key_label":0,"unicode":102,"location":0,"echo":false,"script":null)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
[physics]
|
[physics]
|
||||||
|
|
||||||
common/enable_object_picking=false
|
common/enable_object_picking=false
|
||||||
|
|
||||||
[rendering]
|
[rendering]
|
||||||
|
|
||||||
textures/canvas_textures/default_texture_filter=2
|
|
||||||
renderer/rendering_method="gl_compatibility"
|
renderer/rendering_method="gl_compatibility"
|
||||||
renderer/rendering_method.mobile="gl_compatibility"
|
renderer/rendering_method.mobile="gl_compatibility"
|
||||||
lights_and_shadows/directional_shadow/size=8192
|
|
||||||
lights_and_shadows/directional_shadow/soft_shadow_filter_quality=3
|
|
||||||
lights_and_shadows/positional_shadow/soft_shadow_filter_quality=3
|
|
||||||
anti_aliasing/quality/msaa_2d=1
|
anti_aliasing/quality/msaa_2d=1
|
||||||
anti_aliasing/quality/msaa_3d=1
|
anti_aliasing/quality/msaa_3d=1
|
||||||
lights_and_shadows/positional_shadow/atlas_size=8192
|
|
||||||
|
|
||||||
[xr]
|
[xr]
|
||||||
|
|
||||||
openxr/enabled=true
|
|
||||||
openxr/reference_space=2
|
openxr/reference_space=2
|
||||||
openxr/foveation_level=3
|
openxr/foveation_level=3
|
||||||
shaders/enabled=true
|
shaders/enabled=true
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
#include "mavlink/all/mavlink.h" // IWYU pragma: keep; always include the mavlink.h file for selected dialect
|
#include "mavlink/all/mavlink.h" // IWYU pragma: keep; always include the mavlink.h file for selected dialect
|
||||||
#include "mavlink/common/mavlink_msg_command_long.h"
|
#include "mavlink/common/mavlink_msg_command_long.h"
|
||||||
#include "mavlink/common/mavlink_msg_manual_control.h"
|
#include "mavlink/common/mavlink_msg_manual_control.h"
|
||||||
#include "mavlink/common/mavlink_msg_manual_setpoint.h"
|
|
||||||
#include "mavlink/common/mavlink_msg_param_request_list.h"
|
#include "mavlink/common/mavlink_msg_param_request_list.h"
|
||||||
#include "mavlink/common/mavlink_msg_param_set.h"
|
#include "mavlink/common/mavlink_msg_param_set.h"
|
||||||
#include "mavlink/common/mavlink_msg_param_value.h"
|
#include "mavlink/common/mavlink_msg_param_value.h"
|
||||||
|
|
@ -27,20 +26,16 @@
|
||||||
#include "mavlink/mavlink_types.h"
|
#include "mavlink/mavlink_types.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
using namespace godot;
|
using namespace godot;
|
||||||
|
|
||||||
void MarshConnector::_bind_methods() {
|
void MarshConnector::_bind_methods() {
|
||||||
// Data access
|
// Data access
|
||||||
ClassDB::bind_method(D_METHOD("get_aircraft"), &MarshConnector::get_aircraft);
|
ClassDB::bind_method(D_METHOD("get_aircraft"), &MarshConnector::get_aircraft);
|
||||||
ClassDB::bind_method(D_METHOD("get_velocity"), &MarshConnector::get_velocity);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_cyclic"), &MarshConnector::get_cyclic);
|
ClassDB::bind_method(D_METHOD("get_cyclic"), &MarshConnector::get_cyclic);
|
||||||
ClassDB::bind_method(D_METHOD("get_collective"),
|
ClassDB::bind_method(D_METHOD("get_collective"),
|
||||||
&MarshConnector::get_collective);
|
&MarshConnector::get_collective);
|
||||||
ClassDB::bind_method(D_METHOD("get_pedals"), &MarshConnector::get_pedals);
|
ClassDB::bind_method(D_METHOD("get_pedals"), &MarshConnector::get_pedals);
|
||||||
ClassDB::bind_method(D_METHOD("get_controls"), &MarshConnector::get_controls);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_trim"), &MarshConnector::get_trim);
|
|
||||||
ClassDB::bind_method(D_METHOD("get_model_connected"),
|
ClassDB::bind_method(D_METHOD("get_model_connected"),
|
||||||
&MarshConnector::get_model_connected);
|
&MarshConnector::get_model_connected);
|
||||||
ClassDB::bind_method(D_METHOD("get_manager_connected"),
|
ClassDB::bind_method(D_METHOD("get_manager_connected"),
|
||||||
|
|
@ -53,15 +48,6 @@ void MarshConnector::_bind_methods() {
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "hostname"), "set_hostname",
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "hostname"), "set_hostname",
|
||||||
"get_hostname");
|
"get_hostname");
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("get_fog_density"),
|
|
||||||
&MarshConnector::get_fog_density);
|
|
||||||
ClassDB::bind_method(D_METHOD("set_fog_density", "p_fog_density"),
|
|
||||||
&MarshConnector::set_fog_density);
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fog_density"), "set_fog_density",
|
|
||||||
"get_fog_density");
|
|
||||||
ADD_SIGNAL(MethodInfo("fog_density_changed",
|
|
||||||
PropertyInfo(Variant::FLOAT, "new_density")));
|
|
||||||
|
|
||||||
// Timer callbacks
|
// Timer callbacks
|
||||||
ClassDB::bind_method(D_METHOD("send_heartbeat"),
|
ClassDB::bind_method(D_METHOD("send_heartbeat"),
|
||||||
&MarshConnector::send_heartbeat);
|
&MarshConnector::send_heartbeat);
|
||||||
|
|
@ -195,9 +181,6 @@ void MarshConnector::receive_data(const PackedByteArray &data) {
|
||||||
case MAVLINK_MSG_ID_MANUAL_CONTROL:
|
case MAVLINK_MSG_ID_MANUAL_CONTROL:
|
||||||
handle_manual_control(message);
|
handle_manual_control(message);
|
||||||
break;
|
break;
|
||||||
case MAVLINK_MSG_ID_MANUAL_SETPOINT:
|
|
||||||
handle_manual_setpoint(message);
|
|
||||||
break;
|
|
||||||
case MAVLINK_MSG_ID_HEARTBEAT:
|
case MAVLINK_MSG_ID_HEARTBEAT:
|
||||||
handle_heartbeat(message);
|
handle_heartbeat(message);
|
||||||
break;
|
break;
|
||||||
|
|
@ -252,13 +235,6 @@ Transform3D MarshConnector::get_aircraft() {
|
||||||
return offset * marsh;
|
return offset * marsh;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector3 MarshConnector::get_velocity() {
|
|
||||||
float heading_rad = parameters[NAV_OFS_HDG] * Math_PI / 180.0;
|
|
||||||
// To rotate clockwise looking from above, that's negative Y in Godot
|
|
||||||
Quaternion heading_offset = Quaternion(Vector3(0, 1, 0), -heading_rad);
|
|
||||||
return heading_offset.xform(last_velocity);
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector2 MarshConnector::get_cyclic() {
|
Vector2 MarshConnector::get_cyclic() {
|
||||||
return Vector2{last_controls.x, last_controls.y};
|
return Vector2{last_controls.x, last_controls.y};
|
||||||
}
|
}
|
||||||
|
|
@ -267,21 +243,6 @@ float MarshConnector::get_collective() { return last_controls.w; }
|
||||||
|
|
||||||
float MarshConnector::get_pedals() { return last_controls.z; }
|
float MarshConnector::get_pedals() { return last_controls.z; }
|
||||||
|
|
||||||
Vector4 MarshConnector::get_controls() { return last_controls; }
|
|
||||||
|
|
||||||
Vector4 MarshConnector::get_trim() { return last_trim; }
|
|
||||||
|
|
||||||
float MarshConnector::get_fog_density() { return parameters[FOG_DENSITY]; }
|
|
||||||
|
|
||||||
void MarshConnector::set_fog_density(float density) {
|
|
||||||
if (density == parameters[FOG_DENSITY])
|
|
||||||
return;
|
|
||||||
|
|
||||||
parameters[FOG_DENSITY] = density;
|
|
||||||
emit_signal("fog_density_changed", density);
|
|
||||||
send_param(FOG_DENSITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MarshConnector::get_manager_connected() { return manager_connected; }
|
bool MarshConnector::get_manager_connected() { return manager_connected; }
|
||||||
|
|
||||||
bool MarshConnector::get_model_connected() { return model_connected; }
|
bool MarshConnector::get_model_connected() { return model_connected; }
|
||||||
|
|
@ -302,10 +263,6 @@ Vector2 MarshConnector::local_meters_from_global_degrees(double latitude,
|
||||||
// Y East is just length along the circle of latitude
|
// Y East is just length along the circle of latitude
|
||||||
double y = (lon - lon0) * (EARTH_RADIUS * cos(lat0));
|
double y = (lon - lon0) * (EARTH_RADIUS * cos(lat0));
|
||||||
|
|
||||||
const double map_size = 3000.0;
|
|
||||||
x = (Math::fract(x / map_size + 0.5) - 0.5) * map_size;
|
|
||||||
y = (Math::fract(y / map_size + 0.5) - 0.5) * map_size;
|
|
||||||
|
|
||||||
return Vector2(x, y);
|
return Vector2(x, y);
|
||||||
}
|
}
|
||||||
void MarshConnector::handle_sim_state(mavlink_message_t message) {
|
void MarshConnector::handle_sim_state(mavlink_message_t message) {
|
||||||
|
|
@ -325,8 +282,6 @@ void MarshConnector::handle_sim_state(mavlink_message_t message) {
|
||||||
local_position.x, local_position.y, sim_state.alt));
|
local_position.x, local_position.y, sim_state.alt));
|
||||||
receive_rotation(godot_rotation_from_mavlink(sim_state.roll, sim_state.pitch,
|
receive_rotation(godot_rotation_from_mavlink(sim_state.roll, sim_state.pitch,
|
||||||
sim_state.yaw));
|
sim_state.yaw));
|
||||||
|
|
||||||
last_velocity = Vector3{-sim_state.ve, -sim_state.vd, sim_state.vn};
|
|
||||||
}
|
}
|
||||||
Vector3 MarshConnector::godot_location_from_mavlink(float north_meters,
|
Vector3 MarshConnector::godot_location_from_mavlink(float north_meters,
|
||||||
float east_meters,
|
float east_meters,
|
||||||
|
|
@ -437,11 +392,7 @@ void MarshConnector::handle_param(mavlink_message_t message) {
|
||||||
|
|
||||||
if (param_value.has_value()) {
|
if (param_value.has_value()) {
|
||||||
// TODO: Verify the value before updating
|
// TODO: Verify the value before updating
|
||||||
if (i == FOG_DENSITY) {
|
parameters[i] = *param_value;
|
||||||
set_fog_density(*param_value);
|
|
||||||
} else {
|
|
||||||
parameters[i] = *param_value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
send_param(Parameter{i});
|
send_param(Parameter{i});
|
||||||
}
|
}
|
||||||
|
|
@ -452,11 +403,10 @@ Error MarshConnector::send_param(Parameter index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
mavlink_param_value_t param_value;
|
mavlink_param_value_t param_value;
|
||||||
|
memset(param_value.param_id, 0, sizeof(param_value.param_id));
|
||||||
CharString nameBuffer = parameter_names[index].ascii();
|
CharString nameBuffer = parameter_names[index].ascii();
|
||||||
const char *name = nameBuffer.get_data();
|
const char *name = nameBuffer.get_data();
|
||||||
|
strcpy_s(param_value.param_id, name);
|
||||||
// strncpy will write nulls after data until reaching target count
|
|
||||||
strncpy(param_value.param_id, name, sizeof(param_value.param_id));
|
|
||||||
param_value.param_value = parameters[index];
|
param_value.param_value = parameters[index];
|
||||||
param_value.param_type = MAV_PARAM_TYPE_REAL32;
|
param_value.param_type = MAV_PARAM_TYPE_REAL32;
|
||||||
param_value.param_count = PARAM_COUNT;
|
param_value.param_count = PARAM_COUNT;
|
||||||
|
|
@ -485,22 +435,6 @@ void MarshConnector::handle_manual_control(mavlink_message_t message) {
|
||||||
last_controls.w = manual_control.z / 1000.0f;
|
last_controls.w = manual_control.z / 1000.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MarshConnector::handle_manual_setpoint(mavlink_message_t message) {
|
|
||||||
if (message.msgid != MAVLINK_MSG_ID_MANUAL_SETPOINT)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mavlink_manual_setpoint_t manual_setpoint;
|
|
||||||
mavlink_msg_manual_setpoint_decode(&message, &manual_setpoint);
|
|
||||||
if (manual_setpoint.mode_switch == MARSH_MANUAL_SETPOINT_MODE_TRIM) {
|
|
||||||
last_trim = Vector4{
|
|
||||||
manual_setpoint.roll,
|
|
||||||
manual_setpoint.pitch,
|
|
||||||
manual_setpoint.yaw,
|
|
||||||
manual_setpoint.thrust,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MarshConnector::handle_heartbeat(mavlink_message_t message) {
|
void MarshConnector::handle_heartbeat(mavlink_message_t message) {
|
||||||
if (message.msgid != MAVLINK_MSG_ID_HEARTBEAT)
|
if (message.msgid != MAVLINK_MSG_ID_HEARTBEAT)
|
||||||
return;
|
return;
|
||||||
|
|
@ -511,16 +445,27 @@ void MarshConnector::handle_heartbeat(mavlink_message_t message) {
|
||||||
if (!manager_connected) {
|
if (!manager_connected) {
|
||||||
print_line("Connected to MARSH Manager");
|
print_line("Connected to MARSH Manager");
|
||||||
|
|
||||||
Error result = subscribe_message(message.sysid, message.compid,
|
// subscribe to messages not sent to visualisation node by default
|
||||||
MAVLINK_MSG_ID_MANUAL_CONTROL);
|
mavlink_command_long_t command;
|
||||||
if (result != OK) {
|
command.target_system = 1;
|
||||||
print_line("Subscribe control send result ", result);
|
command.target_component =
|
||||||
}
|
MAV_COMP_ID_USER1; // HACK: Should get it from received HEARTBEAT
|
||||||
|
command.command = MAV_CMD_SET_MESSAGE_INTERVAL;
|
||||||
|
command.confirmation = 0;
|
||||||
|
command.param1 = static_cast<float>(MAVLINK_MSG_ID_MANUAL_CONTROL);
|
||||||
|
command.param2 = 0; // Default rate
|
||||||
|
command.param3 = 0; // Not used
|
||||||
|
command.param4 = 0;
|
||||||
|
command.param5 = 0;
|
||||||
|
command.param6 = 0;
|
||||||
|
command.param7 = 1; // Address of requestor
|
||||||
|
|
||||||
result = subscribe_message(message.sysid, message.compid,
|
mavlink_message_t message_sent;
|
||||||
MAVLINK_MSG_ID_MANUAL_SETPOINT);
|
mavlink_msg_command_long_encode_chan(
|
||||||
|
system_id, component_id, MAVLINK_COMM_0, &message_sent, &command);
|
||||||
|
Error result = send_message(message_sent);
|
||||||
if (result != OK) {
|
if (result != OK) {
|
||||||
print_line("Subscribe setpoint send result ", result);
|
print_line("Subscribe send result ", result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -529,29 +474,6 @@ void MarshConnector::handle_heartbeat(mavlink_message_t message) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Error MarshConnector::subscribe_message(uint8_t manager_system,
|
|
||||||
uint8_t manager_component,
|
|
||||||
uint32_t msgid) {
|
|
||||||
// subscribe to messages not sent to visualisation node by default
|
|
||||||
mavlink_command_long_t command;
|
|
||||||
command.target_system = manager_system;
|
|
||||||
command.target_component = manager_component;
|
|
||||||
command.command = MAV_CMD_SET_MESSAGE_INTERVAL;
|
|
||||||
command.confirmation = 0;
|
|
||||||
command.param1 = static_cast<float>(msgid);
|
|
||||||
command.param2 = 0; // Default rate
|
|
||||||
command.param3 = 0; // Not used
|
|
||||||
command.param4 = 0;
|
|
||||||
command.param5 = 0;
|
|
||||||
command.param6 = 0;
|
|
||||||
command.param7 = 1; // Address of requester
|
|
||||||
|
|
||||||
mavlink_message_t message_sent;
|
|
||||||
mavlink_msg_command_long_encode_chan(system_id, component_id, MAVLINK_COMM_0,
|
|
||||||
&message_sent, &command);
|
|
||||||
return send_message(message_sent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MarshConnector::manager_timeout() {
|
void MarshConnector::manager_timeout() {
|
||||||
print_line("Lost connection to MARSH Manager");
|
print_line("Lost connection to MARSH Manager");
|
||||||
manager_connected = false;
|
manager_connected = false;
|
||||||
|
|
|
||||||
|
|
@ -39,21 +39,12 @@ public:
|
||||||
|
|
||||||
// Get current state of the aircraft
|
// Get current state of the aircraft
|
||||||
Transform3D get_aircraft();
|
Transform3D get_aircraft();
|
||||||
Vector3 get_velocity();
|
|
||||||
// Get normalized (-1 to 1) cyclic position, where X is right, Y is pitch up
|
// Get normalized (-1 to 1) cyclic position, where X is right, Y is pitch up
|
||||||
Vector2 get_cyclic();
|
Vector2 get_cyclic();
|
||||||
// Get normalized (0 to 1) collective position, positive to climb
|
// Get normalized (0 to 1) collective position, positive to climb
|
||||||
float get_collective();
|
float get_collective();
|
||||||
// Get normalized (-1 to 1) pedals position, positive turn right
|
// Get normalized (-1 to 1) pedals position, positive turn right
|
||||||
float get_pedals();
|
float get_pedals();
|
||||||
// Get normalized position for all controls
|
|
||||||
Vector4 get_controls();
|
|
||||||
// Get normalized trim position
|
|
||||||
Vector4 get_trim();
|
|
||||||
|
|
||||||
// Get current fog density as set in the parameter
|
|
||||||
float get_fog_density();
|
|
||||||
void set_fog_density(float value);
|
|
||||||
|
|
||||||
// Is there a connection to MARSH Manager
|
// Is there a connection to MARSH Manager
|
||||||
bool get_manager_connected();
|
bool get_manager_connected();
|
||||||
|
|
@ -85,7 +76,6 @@ private:
|
||||||
void handle_attitude(mavlink_message_t message);
|
void handle_attitude(mavlink_message_t message);
|
||||||
void handle_param(mavlink_message_t message);
|
void handle_param(mavlink_message_t message);
|
||||||
void handle_manual_control(mavlink_message_t message);
|
void handle_manual_control(mavlink_message_t message);
|
||||||
void handle_manual_setpoint(mavlink_message_t message);
|
|
||||||
void handle_heartbeat(mavlink_message_t message);
|
void handle_heartbeat(mavlink_message_t message);
|
||||||
|
|
||||||
void receive_model_data();
|
void receive_model_data();
|
||||||
|
|
@ -98,7 +88,7 @@ private:
|
||||||
// Not an enum class on purpose, to make use more convenient, it's scoped
|
// Not an enum class on purpose, to make use more convenient, it's scoped
|
||||||
// inside the class namespace anyway
|
// inside the class namespace anyway
|
||||||
enum Parameter : uint16_t {
|
enum Parameter : uint16_t {
|
||||||
FOG_DENSITY,
|
// FOG_DENSITY,
|
||||||
NAV_OFS_HDG,
|
NAV_OFS_HDG,
|
||||||
NAV_OFS_X,
|
NAV_OFS_X,
|
||||||
NAV_OFS_Y,
|
NAV_OFS_Y,
|
||||||
|
|
@ -106,25 +96,21 @@ private:
|
||||||
LOCAL_FRAME_LON,
|
LOCAL_FRAME_LON,
|
||||||
PARAM_COUNT,
|
PARAM_COUNT,
|
||||||
};
|
};
|
||||||
float parameters[PARAM_COUNT] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
|
float parameters[PARAM_COUNT] = {0.0, 0.0, 0.0, 0.0, 0.0};
|
||||||
const String parameter_names[PARAM_COUNT] = {
|
const String parameter_names[PARAM_COUNT] = {
|
||||||
"FOG_DENSITY", "NAV_OFS_HDG", "NAV_OFS_X",
|
// "FOG_DENSITY",
|
||||||
"NAV_OFS_Y", "LOCAL_FRAME_LAT", "LOCAL_FRAME_LON",
|
"NAV_OFS_HDG", "NAV_OFS_X", "NAV_OFS_Y",
|
||||||
|
"LOCAL_FRAME_LAT", "LOCAL_FRAME_LON",
|
||||||
};
|
};
|
||||||
Error send_param(Parameter index);
|
Error send_param(Parameter index);
|
||||||
Error subscribe_message(uint8_t manager_system, uint8_t manager_component,
|
|
||||||
uint32_t msgid);
|
|
||||||
|
|
||||||
uint8_t system_id;
|
uint8_t system_id;
|
||||||
uint8_t component_id;
|
uint8_t component_id;
|
||||||
|
|
||||||
// TODO: Interpolate with some delay
|
// TODO: Interpolate with some delay
|
||||||
// Or not, in practice the simple solution works nicely
|
|
||||||
Vector3 last_location;
|
Vector3 last_location;
|
||||||
Quaternion last_rotation;
|
Quaternion last_rotation;
|
||||||
Vector3 last_velocity;
|
|
||||||
Vector4 last_controls;
|
Vector4 last_controls;
|
||||||
Vector4 last_trim;
|
|
||||||
|
|
||||||
double time_passed;
|
double time_passed;
|
||||||
Timer *heartbeat_timer;
|
Timer *heartbeat_timer;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue