1
0
Fork 0

Merge gitorious.org:fg/fgdata

This commit is contained in:
Hyde Yamakawa 2012-10-02 14:28:13 -04:00
commit f8ed1a8701
84 changed files with 6392 additions and 662 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -0,0 +1,3 @@
Changelog:
1.0.0 initial release

View file

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View file

@ -0,0 +1,156 @@
A YASim Nasal-based engine control system
By Ryan Miller (based on Syd Adams's jet/turboprop models)
==========================================================
Introduction:
-------------
YASim jets and turboprops are not very sophisticated engines. Jets are always on and cannot turn off (except by fuel starvation), and turboprops can be turned on simply by moving the condition lever beyond 0.1%. This Nasal script provides an easy way for casual aircraft modelers to implement a basic jet/turboprop engine control system, and provide a framework for extending the system to meet their aircrafts' needs.
How to use:
-----------
1) Copy the nasal script (generic-yasim-engine.nas) to your aircraft directory and reference it in -set.xml. An example:
<nasal>
<engines>
<file>Aircraft/HelloWorld/Nasal/generic-yasim-engine.nas</file>
</engines>
</nasal>
-------------
FOR JETS ONLY
-------------
2) In another script, call the new() functions for each engine. Use the following syntax:
var engine = <module name>.Jet.new(<number> [, <running> [, <idle throttle> [, <max N1 start> [, <N1 start threshold> [, <spool time> [, <start spool time> [, <shutdown time>]]]]]]])
(Arguments in brackets are optional)
Where:
<module name> the module name you added the script under (in the example, it is "engines")
<number> engine number in FDM
<running> whether or not the engine should be running on startup (boolean 0/1) (default 0)
<idle throttle> throttle setting % on idle; this is intended to be used to simulate thrust/fuel consumption of the engine at idle power, since YASim cannot do this (default 0.01/1%)
<max N1 start> maximum N1 % that can be reached using the starter switch (default 5.21, same value in JSBSim jets)
<N1 start threshold> at this N1 %, the engine can be fully started by turning off the cutoff switch (default 3)
<spool time> engine spool time in N1 %/sec (default 4)
<start spool time> engine start spool time in N1 %/sec (default 2)
<shutdown time> engine shutdown time in N1 %/sec (default 4)
You can then call the following functions in the new object:
engine.init() initializes the engine and creates an update loop; should be called AFTER THE FDM IS INITIALIZED (completely optional; you can call update() whenever you want to update the engine)
engine.update() update the engine
engine.autostart() a simple autostart function; you can use an XML binding like this
<binding>
<command>nasal</command>
<script>engine.autostart();</script>
</binding>
Some examples:
var engine = engines.Jet.new(0, 0, 0.03, 5.21, 3, 5, 1, 6);
setlistener("sim/signals/fdm-initialized", func engine.init(), 0, 0);
- or -
<nasal>
<engines>
<file>Aircraft/HelloWorld/Nasal/generic-yasim-engine.nas</file>
<script>
var engine1 = engines.Jet.new(0, 0, 0.03, 5.21, 3, 5, 1, 6);
var engine2 = engines.Jet.new(1, 0, 0.03, 5.21, 3, 5, 1, 6);
setlistener("sim/signals/fdm-initialized", func
{
engine1.init();
engine2.init();
}, 0, 0);
</script>
</engines>
</nasal>
-------------------
FOR TURBOPROPS ONLY
-------------------
2) In another script, call the new() functions for each engine. Use the following syntax:
var engine = <module name>.Turboprop.new(<number> [, <min condition>]);
Where:
<module name> the module name you added the script under (in the example, it is "engines")
<number> engine number in FDM
<min condition> minimum condition setting for the engine to turn on (default 0.2)
You can then call the following functions in the new object:
engine.init() initializes the engine and creates an update loop; should be called AFTER THE FDM IS INITIALIZED (completely optional; you can call update() whenever you want to update the engine)
engine.update() update the engine
engine.autostart() a simple autostart function; you can use an XML binding like this
<binding>
<command>nasal</command>
<script>engine.autostart();</script>
</binding>
Some examples:
var engine = engines.Turboprop.new(0, 0.4);
setlistener("sim/signals/fdm-initialized", func engine.init(), 0, 0);
- or -
<nasal>
<engines>
<file>Aircraft/HelloWorld/Nasal/generic-yasim-engine.nas</file>
<script>
var engine1 = engines.Jet.new(0, 0.4);
var engine2 = engines.Jet.new(1, 0.4);
setlistener("sim/signals/fdm-initialized", func
{
engine1.init();
engine2.init();
}, 0, 0);
</script>
</engines>
</nasal>
-------------------------
FOR BOTH TYPES OF ENGINES
-------------------------
3) Adapt your FDM, controls, and animations to suit the new control system, refer to the tables below:
+-------------------------------------------------------+
|Jet control system |
+---------------+---------------------------------------+
|Control |Property |
+---------------+---------------------------------------+
|Throttle (user)|/controls/engines/engine/throttle |
|Throttle (FDM) |/controls/engines/engine/throttle-lever|
|Starter |/controls/engines/engine/starter |
|Cutoff |/controls/engines/engine/cutoff |
+---------------+---------------------------------------+
|Output |Property |
+---------------+---------------------------------------+
|N1 |/engines/engine/rpm |
+---------------+---------------------------------------+
+---------------------------------------------------------+
|Turboprop control system |
+----------------+----------------------------------------+
|Control |Property |
+----------------+----------------------------------------+
|Throttle |/controls/engines/engine/throttle |
|Condition (user)|/controls/engines/engine/condition |
|Condition (FDM) |/controls/engines/engine/condition-lever|
|Starter |/controls/engines/engine/starter |
|Cutoff |/controls/engines/engine/cutoff |
+----------------+----------------------------------------+
|Output |Property |
+----------------+----------------------------------------+
|N2/RPM |/engines/engine/n1 |
+----------------+----------------------------------------+

View file

@ -0,0 +1,253 @@
# generic-yasim-engine.nas -- a generic Nasal-based engine control system for YASim
# Version 1.0.0
#
# Copyright (C) 2011 Ryan Miller
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
var UPDATE_PERIOD = 0; # update interval for engine init() functions
# jet engine class
var Jet =
{
# creates a new engine object
new: func(n, running = 0, idle_throttle = 0.01, max_start_n1 = 5.21, start_threshold = 3, spool_time = 4, start_time = 2, shutdown_time = 4)
{
# copy the Jet object
var m = { parents: [Jet] };
# declare object variables
m.number = n;
m.autostart_status = 0;
m.autostart_id = -1;
m.loop_running = 0;
m.started = 0;
m.starting = 0;
m.idle_throttle = idle_throttle;
m.max_start_n1 = max_start_n1;
m.start_threshold = start_threshold;
m.spool_time = spool_time;
m.start_time = start_time;
m.shutdown_time = shutdown_time;
# create references to properties and set default values
m.cutoff = props.globals.getNode("controls/engines/engine[" ~ n ~ "]/cutoff", 1);
m.cutoff.setBoolValue(!running);
m.n1 = props.globals.getNode("engines/engine[" ~ n ~ "]/n1", 1);
m.n1.setDoubleValue(0);
m.out_of_fuel = props.globals.getNode("engines/engine[" ~ n ~ "]/out-of-fuel", 1);
m.out_of_fuel.setBoolValue(0);
m.reverser = props.globals.getNode("controls/engines/engine[" ~ n ~ "]/reverser", 1);
m.reverser.setBoolValue(0);
m.rpm = props.globals.getNode("engines/engine[" ~ n ~ "]/rpm", 1);
m.rpm.setDoubleValue(running ? 100 : 0);
m.running = props.globals.getNode("engines/engine[" ~ n ~ "]/running", 1);
m.running.setBoolValue(running);
m.serviceable = props.globals.getNode("engines/engine[" ~ n ~ "]/serviceable", 1);
m.serviceable.setBoolValue(1);
m.starter = props.globals.getNode("controls/engines/engine[" ~ n ~ "]/starter", 1);
m.starter.setBoolValue(0);
m.throttle = props.globals.getNode("controls/engines/engine[" ~ n ~ "]/throttle", 1);
m.throttle.setDoubleValue(0);
m.throttle_lever = props.globals.getNode("controls/engines/engine[" ~ n ~ "]/throttle-lever", 1);
m.throttle_lever.setDoubleValue(0);
# return our new object
return m;
},
# engine-specific autostart
autostart: func
{
if (me.autostart_status)
{
me.autostart_status = 0;
me.cutoff.setBoolValue(1);
}
else
{
me.autostart_status = 1;
me.starter.setBoolValue(1);
settimer(func
{
me.cutoff.setBoolValue(0);
}, me.max_start_n1 / me.start_time);
}
},
# creates an engine update loop (optional)
init: func
{
if (me.loop_running) return;
me.loop_running = 1;
var loop = func
{
me.update();
settimer(loop, UPDATE_PERIOD);
};
settimer(loop, 0);
},
# updates the engine
update: func
{
if (me.running.getBoolValue() and !me.started)
{
me.running.setBoolValue(0);
}
if (me.cutoff.getBoolValue() or !me.serviceable.getBoolValue() or me.out_of_fuel.getBoolValue())
{
var rpm = me.rpm.getValue();
var time_delta = getprop("sim/time/delta-realtime-sec");
if (me.starter.getBoolValue())
{
rpm += time_delta * me.spool_time;
me.rpm.setValue(rpm >= me.max_start_n1 ? me.max_start_n1 : rpm);
}
else
{
rpm -= time_delta * me.shutdown_time;
me.rpm.setValue(rpm <= 0 ? 0 : rpm);
me.running.setBoolValue(0);
me.throttle_lever.setDoubleValue(0);
me.started = 0;
}
}
elsif (me.starter.getBoolValue())
{
var rpm = me.rpm.getValue();
if (rpm >= me.start_threshold)
{
var time_delta = getprop("sim/time/delta-realtime-sec");
rpm += time_delta * me.spool_time;
me.rpm.setValue(rpm);
if (rpm >= me.n1.getValue())
{
me.running.setBoolValue(1);
me.starter.setBoolValue(0);
me.started = 1;
}
else
{
me.running.setBoolValue(0);
}
}
}
elsif (me.running.getBoolValue())
{
me.throttle_lever.setValue(me.idle_throttle + (1 - me.idle_throttle) * me.throttle.getValue());
me.rpm.setValue(me.n1.getValue());
}
}
};
# turboprop engine class
var turboprop_condition_cutoff = 0.001; # minimum condition value for YASim turboprops to start
var Turboprop =
{
new: func(n, running = 0, min_condition = 0.2)
{
# copy the Turboprop object
var m = { parents: [Turboprop] };
# declare object variables
m.number = n;
m.autostart_status = 0;
m.loop_running = 0;
m.min_condition = min_condition;
# create references to properties and set default values
m.condition = props.globals.getNode("controls/engines/engine[" ~ n ~ "]/condition", 1);
m.condition.setDoubleValue(0);
m.condition_lever = props.globals.getNode("controls/engines/engine[" ~ n ~ "]/condition-lever", 1);
m.condition_lever.setDoubleValue(running ? min_condition : 0);
m.cutoff = props.globals.getNode("controls/engines/engine[" ~ n ~ "]/cutoff", 1);
m.cutoff.setBoolValue(!running);
m.n1 = props.globals.getNode("engines/engine[" ~ n ~ "]/n1", 1);
m.n1.setDoubleValue(running ? 100 : 0);
m.n2 = props.globals.getNode("engines/engine[" ~ n ~ "]/n2", 1);
m.n2.setDoubleValue(0);
m.out_of_fuel = props.globals.getNode("engines/engine[" ~ n ~ "]/out-of-fuel", 1);
m.out_of_fuel.setBoolValue(0);
m.propeller_feather = props.globals.getNode("controls/engines/engine[" ~ n ~ "]/propeller-feather", 1);
m.propeller_feather.setBoolValue(0);
m.starter = props.globals.getNode("controls/engines/engine[" ~ n ~ "]/starter", 1);
m.starter.setBoolValue(0);
# return our new object
return m;
},
# engine-specific autostart
autostart: func
{
if (me.autostart_status)
{
me.autostart_status = 0;
me.cutoff.setBoolValue(1);
me.condition.setValue(0);
}
else
{
me.autostart_status = 1;
me.cutoff.setBoolValue(0);
me.starter.setBoolValue(1);
me.condition.setValue(me.min_condition);
}
},
# creates an engine update loop (optional)
init: func
{
if (me.loop_running) return;
me.loop_running = 1;
var loop = func
{
me.update();
settimer(loop, UPDATE_PERIOD);
};
settimer(loop, 0);
},
# updates the engine
update: func
{
if (me.cutoff.getBoolValue())
{
me.out_of_fuel.setBoolValue(1);
}
if (me.starter.getBoolValue() and me.condition_lever.getValue() < turboprop_condition_cutoff and me.condition.getValue() >= me.min_condition)
{
me.condition_lever.setValue(me._get_condition_value(me.condition.getValue()));
}
elsif (me.condition_lever.getValue() < turboprop_condition_cutoff and me.n2.getValue() < 0.5)
{
if (me.propeller_feather.getBoolValue())
{
me.n1.setValue(0);
}
me.condition_lever.setValue(0);
}
if (me.n2.getValue() >= 0.5)
{
if (me.condition_lever.getValue() >= turboprop_condition_cutoff)
{
me.condition_lever.setValue(me._get_condition_value(me.condition.getValue()));
}
else
{
me.condition_lever.setValue(0);
}
me.n1.setValue(me.n2.getValue());
}
},
_get_condition_value: func(v)
{
if (v >= me.min_condition)
{
return turboprop_condition_cutoff + (v - me.min_condition) / (1 - me.min_condition) * (1 - turboprop_condition_cutoff);
}
return v / me.min_condition * turboprop_condition_cutoff;
}
};

View file

@ -7,21 +7,21 @@
<label>Cessna C172P</label>
<enabled type="bool">true</enabled>
<item>
<label>Select Livery</label>
<name>select-livery</name>
<binding>
<command>nasal</command>
<script>aircraft.livery.dialog.toggle()</script>
</binding>
</item>
<item>
<label>Immatriculation</label>
<name>immatriculation</name>
<binding>
<command>nasal</command>
<script>c172p.immat_dialog.toggle()</script>
</binding>
</item>
<item>
<label>Show/hide yoke</label>
<name>show-hide-yokes</name>
<binding>
<command>property-toggle</command>
<property>sim/model/hide-yoke</property>

View file

@ -43,7 +43,7 @@
<binormal type="int">7</binormal>
</generate>
<technique n="8">
<technique n="7">
<pass>
<program>
<attribute>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<PropertyList>
<name>Aircraft/c172p/Models/Effects/glass</name>
<inherits-from>Effects/model-combined</inherits-from>
<inherits-from>Effects/model-combined-transparent</inherits-from>
<parameters>
<normalmap-enabled type="int">0</normalmap-enabled>
<lightmap-enabled type="int">0</lightmap-enabled>
@ -27,109 +27,8 @@
<rendering-hint>transparent</rendering-hint>
<transparent>true</transparent>
<render-bin>
<bin-number>111</bin-number>
<bin-number>10</bin-number>
<bin-name>DepthSortedBin</bin-name>
</render-bin>
</parameters>
<technique n="7">
<predicate>
<and>
<property>/sim/rendering/rembrandt/enabled</property>
<or>
<less-equal>
<value type="float">2.0</value>
<glversion/>
</less-equal>
<and>
<extension-supported>GL_ARB_shader_objects</extension-supported>
<extension-supported>GL_ARB_shading_language_100</extension-supported>
<extension-supported>GL_ARB_vertex_shader</extension-supported>
<extension-supported>GL_ARB_fragment_shader</extension-supported>
</and>
</or>
<extension-supported>GL_EXT_gpu_shader4</extension-supported>
<extension-supported>GL_ARB_texture_rg</extension-supported>
</and>
</predicate>
<pass>
<lighting>true</lighting>
<depth>
<write-mask type="bool">false</write-mask>
</depth>
<material>
<active>
<use>material/active</use>
</active>
<ambient>
<use>material/ambient</use>
</ambient>
<diffuse>
<use>material/diffuse</use>
</diffuse>
<specular>
<use>material/specular</use>
</specular>
<emissive>
<use>material/emissive</use>
</emissive>
<shininess>
<use>material/shininess</use>
</shininess>
<color-mode>
<use>material/color-mode</use>
</color-mode>
</material>
<blend>
<active>
<use>blend/active</use>
</active>
<source>
<use>blend/source</use>
</source>
<destination>
<use>blend/destination</use>
</destination>
</blend>
<shade-model>
<use>shade-model</use>
</shade-model>
<cull-face>
<use>cull-face</use>
</cull-face>
<render-bin>
<bin-number>111</bin-number>
<bin-name>DepthSortedBin</bin-name>
</render-bin>
<texture-unit>
<active>
<use>texture[0]/active</use>
</active>
<unit>0</unit>
<image>
<use>texture[0]/image</use>
</image>
<filter>
<use>texture[0]/filter</use>
</filter>
<wrap-s>
<use>texture[0]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[0]/wrap-t</use>
</wrap-t>
<!--
<internal-format>
<use>texture[0]/internal-format</use>
</internal-format>
-->
<environment>
<mode>modulate</mode>
</environment>
</texture-unit>
<!-- A two-sided lighting model is set by default near the root
of the scene graph. Perhaps that ought to be set in this
effect?
-->
</pass>
</technique>
</PropertyList>

View file

@ -2095,7 +2095,7 @@
<object-name>navlight_right</object-name>
<object-name>navlight_back</object-name>
<condition>
<property>controls/lighting/nav-lights</property>
<property>systems/electrical/outputs/nav-lights</property>
</condition>
</animation>
@ -2436,7 +2436,7 @@
<condition>
<and>
<property>/sim/rendering/rembrandt/enabled</property>
<property>controls/lighting/landing-lights</property>
<property>systems/electrical/outputs/landing-lights</property>
</and>
</condition>
</animation>
@ -2447,7 +2447,7 @@
<condition>
<and>
<property>/sim/rendering/rembrandt/enabled</property>
<property>controls/lighting/taxi-light</property>
<property>systems/electrical/outputs/taxi-light</property>
</and>
</condition>
</animation>
@ -2460,7 +2460,7 @@
<object-name>landinglight2</object-name>
<condition>
<and>
<property>controls/lighting/landing-lights</property>
<property>systems/electrical/outputs/landing-lights</property>
<not>
<property>/sim/rendering/rembrandt/enabled</property>
</not>
@ -2523,7 +2523,7 @@
<object-name>TaxiLightCone</object-name>
<nopreview/>
<condition>
<property>controls/lighting/taxi-light</property>
<property>systems/electrical/outputs/taxi-light</property>
</condition>
<position>
<x>-0.078</x>
@ -2570,7 +2570,7 @@
<object-name>landinglightcover</object-name>
<condition>
<not>
<property>controls/lighting/landing-lights</property>
<property>systems/electrical/outputs/landing-lights</property>
</not>
</condition>
</animation>

View file

@ -64,14 +64,21 @@ BatteryClass.new = func {
BatteryClass.apply_load = func( amps, dt ) {
var amphrs_used = amps * dt / 3600.0;
var percent_used = amphrs_used / me.amp_hours;
me.charge_percent -= percent_used;
if ( me.charge_percent < 0.0 ) {
me.charge_percent = 0.0;
} elsif ( me.charge_percent > 1.0 ) {
me.charge_percent = 1.0;
var charge_percent = me.charge_percent;
charge_percent -= percent_used;
if ( charge_percent < 0.0 ) {
charge_percent = 0.0;
} elsif ( charge_percent > 1.0 ) {
charge_percent = 1.0;
}
# print( "battery percent = ", me.charge_percent);
return me.amp_hours * me.charge_percent;
if ((charge_percent < 0.1)and(me.charge_percent >= 0.1))
{
print("Warning: Low battery! Enable alternator or apply external power to recharge battery.");
}
me.charge_percent = charge_percent;
setprop("/systems/electrical/battery-charge-percent", charge_percent);
# print( "battery percent = ", charge_percent);
return me.amp_hours * charge_percent;
}
##
@ -207,6 +214,10 @@ update_virtual_bus = func( dt ) {
# switch state
var master_bat = getprop("/controls/engines/engine[0]/master-bat");
var master_alt = getprop("/controls/engines/engine[0]/master-alt");
if (getprop("/controls/electric/external-power"))
{
external_volts = 28;
}
# determine power source
var bus_volts = 0.0;
@ -233,7 +244,7 @@ update_virtual_bus = func( dt ) {
load += 12;
}
setprop("systems/electrical/outputs/starter[0]", starter_volts);
if (starter_volts > 1) {
if (starter_volts > 12) {
setprop("controls/engines/engine[0]/starter",1);
setprop("controls/engines/engine[0]/magnetos",3);
} else {
@ -251,9 +262,6 @@ update_virtual_bus = func( dt ) {
# system loads and ammeter gauge
var ammeter = 0.0;
if ( bus_volts > 1.0 ) {
# normal load
load += 15.0;
# ammeter gauge
if ( power_source == "battery" ) {
ammeter = -load;
@ -271,12 +279,15 @@ update_virtual_bus = func( dt ) {
}
# filter ammeter needle pos
var ammeter_ave = 0.8 * ammeter_ave + 0.2 * ammeter;
ammeter_ave = 0.8 * ammeter_ave + 0.2 * ammeter;
# outputs
setprop("/systems/electrical/amps", ammeter_ave);
setprop("/systems/electrical/volts", bus_volts);
vbus_volts = bus_volts;
if (bus_volts > 12)
vbus_volts = bus_volts;
else
vbus_volts = 0.0;
return load;
}
@ -290,6 +301,7 @@ electrical_bus_1 = func() {
# Cabin Lights Power
if ( getprop("/controls/circuit-breakers/cabin-lights-pwr") ) {
setprop("/systems/electrical/outputs/cabin-lights", bus_volts);
load += bus_volts / 57;
} else {
setprop("/systems/electrical/outputs/cabin-lights", 0.0);
}
@ -300,21 +312,23 @@ electrical_bus_1 = func() {
# Fuel Pump Power
if ( getprop("/controls/engines/engine[0]/fuel-pump") ) {
setprop("/systems/electrical/outputs/fuel-pump", bus_volts);
load += bus_volts / 28;
} else {
setprop("/systems/electrical/outputs/fuel-pump", 0.0);
}
# Landing Light Power
if ( getprop("/controls/switches/landing-light") ) {
setprop("/systems/electrical/outputs/landing-light", bus_volts);
if ( getprop("/controls/lighting/landing-lights") ) {
setprop("/systems/electrical/outputs/landing-lights", bus_volts);
load += bus_volts / 5;
} else {
setprop("/systems/electrical/outputs/landing-light", 0.0 );
setprop("/systems/electrical/outputs/landing-lights", 0.0 );
}
# Beacon Power
if ( getprop("/controls/switches/flashing-beacon" ) ) {
if ( getprop("/controls/lighting/beacon" ) ) {
setprop("/systems/electrical/outputs/beacon", bus_volts);
if ( bus_volts > 1.0 ) { load += 7.5; }
load += bus_volts / 28;
} else {
setprop("/systems/electrical/outputs/beacon", 0.0);
}
@ -335,34 +349,37 @@ electrical_bus_2 = func() {
var bus_volts = vbus_volts;
var load = 0.0;
# Map Lights Power
if ( getprop("/controls/switches/nav-lights" ) ) {
setprop("/systems/electrical/outputs/map-lights", bus_volts);
if ( bus_volts > 1.0 ) { load += 7.0; }
# Nav Lights Power
if ( getprop("/controls/lighting/nav-lights" ) ) {
setprop("/systems/electrical/outputs/nav-lights", bus_volts);
load += bus_volts / 14;
} else {
setprop("/systems/electrical/outputs/map-lights", 0.0);
setprop("/systems/electrical/outputs/nav-lights", 0.0);
}
# Instrument Lights Power
setprop("/systems/electrical/outputs/instrument-lights", bus_volts);
# Strobe Lights Power
if ( getprop("/controls/switches/strobe-lights" ) ) {
setprop("/systems/electrical/outputs/strobe-lights", bus_volts);
if ( getprop("/controls/lighting/strobe" ) ) {
setprop("/systems/electrical/outputs/strobe", bus_volts);
load += bus_volts / 14;
} else {
setprop("/systems/electrical/outputs/strobe-lights", 0.0);
setprop("/systems/electrical/outputs/strobe", 0.0);
}
# Taxi Lights Power
if ( getprop("/controls/switches/taxi-lights" ) ) {
setprop("/systems/electrical/outputs/taxi-lights", bus_volts);
if ( getprop("/controls/lighting/taxi-light" ) ) {
setprop("/systems/electrical/outputs/taxi-light", bus_volts);
load += bus_volts / 10;
} else {
setprop("/systems/electrical/outputs/taxi-lights", 0.0);
setprop("/systems/electrical/outputs/taxi-light", 0.0);
}
# Pitot Heat Power
if ( getprop("/controls/switches/pitot-heat" ) ) {
if ( getprop("/controls/anti-ice/pitot-heat" ) ) {
setprop("/systems/electrical/outputs/pitot-heat", bus_volts);
load += bus_volts / 28;
} else {
setprop("/systems/electrical/outputs/pitot-heat", 0.0);
}
@ -401,6 +418,8 @@ avionics_bus_1 = func() {
bus_volts = ebus1_volts;
}
load += bus_volts / 20.0;
# Turn Coordinator Power
setprop("/systems/electrical/outputs/turn-coordinator", bus_volts);
@ -440,7 +459,8 @@ avionics_bus_2 = func() {
if ( master_av ) {
bus_volts = ebus2_volts;
}
var load = 0.0;
var load = bus_volts / 20.0;
# NavCom 2 Power
setprop("/systems/electrical/outputs/nav[1]", bus_volts);

View file

@ -1,10 +1,10 @@
# strobes ===========================================================
var strobe_switch = props.globals.getNode("controls/lighting/strobe", 1);
var strobe_switch = props.globals.getNode("/systems/electrical/outputs/strobe", 1);
aircraft.light.new("sim/model/c172p/lighting/strobes", [0.015, 1.985], strobe_switch);
# beacons ===========================================================
var beacon_switch = props.globals.getNode("controls/lighting/beacon", 1);
var beacon_switch = props.globals.getNode("/systems/electrical/outputs/beacon", 1);
aircraft.light.new("sim/model/c172p/lighting/beacon-top", [0.10, 0.90], beacon_switch);

View file

@ -0,0 +1,444 @@
<PropertyList>
<checklist>
<title>Before Starting Engine</title>
<item>
<name>Preflight Inspection</name>
<value>COMPLETE</value>
</item>
<item>
<name>Passenger</name>
<value>COMPLETE</value>
</item>
<item>
<name>Seats, Seat Belts, Shoulder Harnesses</name>
<value>ADJUST and LOCK</value>
</item>
<item>
<name>Brakes</name>
<value>TEST and SET (shift-B)</value>
</item>
<item>
<name>Avionics Power Switch</name>
<value>OFF</value>
</item>
<item>
<name>Circuit Breakers</name>
<value>CHECK IN</value>
</item>
<item>
<name>Electrical Equipment, Autopilot</name>
<value>OFF</value>
</item>
<item>
<name>Fuel Selector Valve</name>
<value>BOTH</value>
</item>
</checklist>
<checklist>
<title>Starting Engine</title>
<item>
<name>Prime</name>
<value>As Required - 2-6 strokes</value>
</item>
<item>
<name>Carburetor Heat</name>
<value>COLD</value>
</item>
<item>
<name>Throttle</name>
<value>OPEN 1/8 INCH</value>
</item>
<item>
<name>Mixture</name>
<value>RICH</value>
</item>
<item>
<name>Propellor Area</name>
<value>CLEAR</value>
</item>
<item>
<name>Master Switch</name>
<value>ON</value>
</item>
<item>
<name>Magnetos</name>
<value>BOTH</value>
<value>(press } three times)</value>
</item>
<item>
<name>Ignition Switch</name>
<value>ON</value>
<value>(press s, release when engine starts)</value>
</item>
<item>
<name>Oil Pressure</name>
<value>CHECK</value>
</item>
<item>
<name>Avionics Power Switch</name>
<value>ON</value>
</item>
<item>
<name>Navigation Lights and Flashing Beacon</name>
<value>ON as required</value>
</item>
<item>
<name>Radios</name>
<value>ON</value>
</item>
</checklist>
<checklist>
<title>Before Takeoff</title>
<item>
<name>Parking Brake</name>
<value>SET (shift-B)</value>
</item>
<item>
<name>Seats, Seat Belts, Shoulder Harnesses</name>
<value>CHECK SECURE</value>
</item>
<item>
<name>Cabin Doors</name>
<value>CLOSED and LOCKED</value>
</item>
<item>
<name>Flight Controls</name>
<value>FREE and CORRECT</value>
</item>
<item>
<name>Flight Instruments</name>
<value>CHECK and SET</value>
</item>
<item>
<name>Fuel Quantity</name>
<value>CHECK</value>
</item>
<item>
<name>Mixture</name>
<value>RICH</value>
</item>
<item>
<name>Fuel Selector Valve</name>
<value>RECHECK BOTH</value>
</item>
<item>
<name>Elevator Trim</name>
<value>SET for takeoff</value>
</item>
<item>
<name>Throttle</name>
<value>1700 RPM</value>
</item>
<item>
<name>Magnetos</name>
<value>CHECK RPM DROP</value>
<value>(125 rpm max)</value>
</item>
<item>
<name>Carburetor Heat</name>
<value>CHECK for RPM drop</value>
</item>
<item>
<name>Suction Gauge</name>
<value>CHECK</value>
</item>
<item>
<name>Engine Instruments and Ammeter</name>
<value>CHECK</value>
</item>
<item>
<name>Throttle</name>
<value>1000RPM or LESS</value>
</item>
<item>
<name>Throttle Friction Lock</name>
<value>ADJUST</value>
</item>
<item>
<name>Strobe Lights</name>
<value>AS DESIRED</value>
</item>
<item>
<name>Radios and Avionics</name>
<value>SET</value>
</item>
<item>
<name>Autopilot</name>
<value>OFF</value>
</item>
<item>
<name>Wing Flaps</name>
<value>SET for takeoff</value>
</item>
<item>
<name>Brakes</name>
<value>RELEASE</value>
</item>
</checklist>
<checklist>
<title>Normal Takeoff</title>
<item>
<name>Wing Flaps</name>
<value>0 - 10 degrees</value>
</item>
<item>
<name>Carburetor Heat</name>
<value>COLD</value>
</item>
<item>
<name>Throttle</name>
<value>FULL OPEN</value>
</item>
<item>
<name>Elevator Control</name>
<value>LIFT NOSE WHEEL</value>
<value>(at 55 KIAS)</value>
</item>
</checklist>
<checklist>
<title>Short Field Takeoff</title>
<item>
<name>Wing Flaps</name>
<value>10 degrees</value>
</item>
<item>
<name>Carburetor Heat</name>
<value>COLD</value>
</item>
<item>
<name>Brakes</name>
<value>APPLY</value>
</item>
<item>
<name>Throttle</name>
<value>FULL OPEN</value>
</item>
<item>
<name>Mixture</name>
<value>RICH</value>
<value>(above 3000ft, LEAN to obtain maximum RPM)</value>
</item>
<item>
<name>Brakes</name>
<value>RELEASE</value>
</item>
<item>
<name>Elevator Control</name>
<value>SLIGHTLY TAIL LOW</value>
</item>
<item>
<name>Climb Speed</name>
<value>56 KIAS</value>
</item>
</checklist>
<checklist>
<title>Enroute Climb</title>
<item>
<name>Airspeed</name>
<value>70-85 KIAS</value>
</item>
<item>
<name>Throttle</name>
<value>FULL OPEN</value>
</item>
<item>
<name>Mixture</name>
<value>RICH</value>
<value>(above 3000ft, LEAN to obtain maximum RPM)</value>
</item>
</checklist>
<checklist>
<title>Cruise</title>
<item>
<name>Power</name>
<value>2100-2700 RPM</value>
<value>(no more than 75% recommended)</value>
</item>
<item>
<name>Elevator Trim</name>
<value>ADJUST</value>
</item>
<item>
<name>Mixture</name>
<value>LEAN</value>
</item>
</checklist>
<checklist>
<title>Descent</title>
<item>
<name>Fuel Selector Valve</name>
<value>BOTH</value>
</item>
<item>
<name>Power</name>
<value>AS DESIRED</value>
</item>
<item>
<name>Mixture</name>
<value>ADJUST for smooth operation</value>
<value>(full rich for idle power)</value>
</item>
<item>
<name>Carburetor Heat</name>
<value>FULL HEAT AS REQUIRED</value>
<value>(to prevent carburetor icing)</value>
</item>
</checklist>
<checklist>
<title>Before Landing</title>
<item>
<name>Seats, Seat Belt, Shoulder Harnesses</name>
<value>SECURE</value>
</item>
<item>
<name>Fuel Selector Valve</name>
<value>BOTH</value>
</item>
<item>
<name>Mixture</name>
<value>RICH</value>
</item>
<item>
<name>Carburetor Heat</name>
<value>FULL HEAT</value>
<value>(apply full heat before reducing power)</value>
</item>
<item>
<name>Autopilot</name>
<value>OFF</value>
</item>
</checklist>
<checklist>
<title>Normal Landing</title>
<item>
<name>Airspeed</name>
<value>65-75 KIAS (flaps UP)</value>
</item>
<item>
<name>Wing Flaps</name>
<value>AS DESIRED</value>
<value>(0 - 10 degrees below 110KIAS</value>
<value>10 - 30 degrees below 85KIAS</value>
</item>
<item>
<name>Airspeed</name>
<value>60-70 KIAS (flaps DOWN)</value>
</item>
<item>
<name>Touchdown</name>
<value>MAIN WHEELS FIRST</value>
</item>
<item>
<name>Landing Roll</name>
<value>LOWER NOSE WHEEL GENTLY</value>
</item>
<item>
<name>Braking</name>
<value>MINIMUM REQUIRED</value>
</item>
</checklist>
<checklist>
<title>Short Field Landing</title>
<item>
<name>Airspeed</name>
<value>65-75 KIAS (flaps UP)</value>
</item>
<item>
<name>Wing Flaps</name>
<value>FULL DOWN (30 degrees)</value>
</item>
<item>
<name>Airspeed</name>
<value>61 KIAS (until flare)</value>
</item>
<item>
<name>Power</name>
<value>REDUCE to idle after clearing obstacle</value>
</item>
<item>
<name>Touchdown</name>
<value>MAIN WHEELS FIRST</value>
</item>
<item>
<name>Braking</name>
<value>APPLY HEAVILY</value>
</item>
<item>
<name>Wing Flaps</name>
<value>RETRACT</value>
</item>
</checklist>
<checklist>
<title>Aborted Landing</title>
<item>
<name>Throttle</name>
<value>FULL OPEN</value>
</item>
<item>
<name>Carburetor Heat</name>
<value>COLD</value>
</item>
<item>
<name>Wing Flaps</name>
<value>20 degrees (immediately)</value>
</item>
<item>
<name>Climb Speed</name>
<value>55 KIAS</value>
</item>
<item>
<name>Wing Flaps</name>
<value>10 degrees (until obstacles are cleared)</value>
<value>RETRACT (after reaching safe altitude and 60 KIAS)</value>
</item>
</checklist>
<checklist>
<title>After Landing</title>
<item>
<name>Carburetor Heat</name>
<value>COLD</value>
</item>
<item>
<name>Wing Flaps</name>
<value>UP</value>
</item>
</checklist>
<checklist>
<title>Securing Airplane</title>
<item>
<name>Parking Brake</name>
<value>SET</value>
</item>
<item>
<name>Avionics, Power, Electrical, Autopilot</name>
<value>OFF</value>
</item>
<item>
<name>Mixture</name>
<value>PULLED FULL OUT</value>
</item>
<item>
<name>Ignition Switch</name>
<value>OFF</value>
</item>
<item>
<name>Control Lock</name>
<value>INSTALL</value>
</item>
</checklist>
</PropertyList>

View file

@ -89,7 +89,7 @@
<output>
<name>Landing Light Power</name>
<prop>/systems/electrical/outputs/landing-light</prop>
<prop>/systems/electrical/outputs/landing-lights</prop>
</output>
<output>
@ -115,8 +115,8 @@
</output>
<output>
<name>Map Lights Power</name>
<prop>/systems/electrical/outputs/map-lights</prop>
<name>Nav Lights Power</name>
<prop>/systems/electrical/outputs/nav-lights</prop>
</output>
<output>
@ -126,12 +126,12 @@
<output>
<name>Strobe Lights Power</name>
<prop>/systems/electrical/outputs/strobe-lights</prop>
<prop>/systems/electrical/outputs/strobe</prop>
</output>
<output>
<name>Taxi Lights Power</name>
<prop>/systems/electrical/outputs/taxi-lights</prop>
<prop>/systems/electrical/outputs/taxi-light</prop>
</output>
<output>
@ -324,7 +324,7 @@
<input>Electrical Bus 1</input>
<output>Landing Light Power</output>
<switch>
<prop>/controls/switches/landing-light</prop>
<prop>/controls/lighting/landing-lights</prop>
</switch>
</connector>
@ -332,7 +332,7 @@
<input>Electrical Bus 1</input>
<output>Beacon Power</output>
<switch>
<prop>/controls/switches/flashing-beacon</prop>
<prop>/controls/lighting/beacon</prop>
</switch>
</connector>
@ -366,7 +366,7 @@
<input>Electrical Bus 2</input>
<output>Map Lights Power</output>
<switch>
<prop>/controls/switches/nav-lights</prop>
<prop>/controls/lighting/nav-lights</prop>
</switch>
</connector>
@ -382,7 +382,7 @@
<input>Electrical Bus 2</input>
<output>Strobe Lights Power</output>
<switch>
<prop>/controls/switches/strobe-lights</prop>
<prop>/controls/lighting/strobe</prop>
</switch>
</connector>
@ -390,7 +390,7 @@
<input>Electrical Bus 2</input>
<output>Taxi Lights Power</output>
<switch>
<prop>/controls/switches/taxi-lights</prop>
<prop>/controls/lighting/taxi-light</prop>
</switch>
</connector>
@ -398,7 +398,7 @@
<input>Electrical Bus 2</input>
<output>Pitot Heat Power</output>
<switch>
<prop>/controls/switches/pitot-heat</prop>
<prop>/controls/anti-ice/pitot-heat</prop>
</switch>
</connector>

View file

@ -13,33 +13,11 @@
<desc>Increase/decrease panel lighting</desc>
</key>
<line/>
<line>_________Engine Start Checklist_________</line>
<line>Mixture: Rich</line>
<line>Throttle: Open 1/8"</line>
<line>Parking Brake: Applied (Shift-B)</line>
<line>Prop Area: Clear</line>
<line>Magnetos: Both ( } three times )</line>
<line>Ignition: Start (s)</line>
<line>Throttle: 800-1000rpm</line>
<line/>
<line>_________Pre-Takeoff Checklist_________</line>
<line>Parking Brake: Applied (Shift-B)</line>
<line>Flight Controls: Free and Correct</line>
<line>Elevator Trim: Takeoff</line>
<line>Mixture: Rich</line>
<line>Throttle: 1700rpm</line>
<line>Suction gauge: Check</line>
<line>Engine Instruments: Check</line>
<line>Ammeter: Check</line>
<line>Magnetos: Check (125rpm max drop, 50rpm max diff</line>
<line>Throttle: Closed (check idle)</line>
<line>Throttle: 800-1000rpm</line>
<line>Mixture: As required</line>
<line/>
<line>_________Procedures_________</line>
<line>For checklists, see under Help->Aircraft Checklists</line>
<line/>
<line>Takeoff: no flaps, full throttle, rotate at 55 KIAS</line>
<line>Climbout: no flaps, full throttle, 80 KIAS</line>
<line>Cruise: Throttle 65%, Mixture rich of peak,</line>
<line>Cruise: Throttle 65%, Mixture rich of peak</line>
<line>Landing: full flaps, 65 KIAS</line>
<line/>
<line>_________V Speeds_________</line>

View file

@ -96,6 +96,8 @@ Started October 23 2001 by John Check, fgpanels@rockfish.net
</sound>
<help include="c172-help.xml"/>
<checklists include="c172-checklists.xml"/>
<tutorials include="Tutorials/c172-tutorials.xml"/>

View file

@ -143,6 +143,8 @@ alpha-test - children: active, comparison, reference
Valid values for comparision:
never, less, equal, lequal, greater, notequal, gequal,
always
alpha-to-coverage - true, false
blend - children: active, source, destination, source-rgb,
source-alpha, destination-rgb, destination-alpha

View file

@ -8,8 +8,13 @@ The model-combined effect uses the ubershader to provide any or all of diffuse,
To use this on your aircraft model, you are advised to create a local effect that has the following lines:
1. for automatic Rembrandt support on opaque objects use this:
<name>my-aircraft-effect</name>
<inherits-from>Effects/model-combined</inherits-from>
<inherits-from>Effects/model-combined-deferred</inherits-from>
2. for automatic Rembrandt support on transparent objects (glass) use this:
<name>my-aircraft-glass-effect</name>
<inherits-from>Effects/model-combined-transparent</inherits-from>
The only modeller-adjustable settings are those found in the parameters section and listed here. There are other entries in the parameters section, but those are for internal use only, please don't mess with them.

View file

@ -7,7 +7,7 @@
WARNING: do not remove the Normalmap include at the end-->
<PropertyList>
<name><!--my/effect/name--></name>
<inherits-from>Effects/model-combined</inherits-from>
<inherits-from>Effects/model-combined-deferred</inherits-from>
<parameters>
<!-- Normal Map -->
<normalmap-enabled type="int"> 1 </normalmap-enabled>
@ -77,7 +77,7 @@
<binormal type="int">7</binormal>
</generate>
<technique n="8">
<technique n="7">
<pass>
<program>
<attribute>

View file

@ -7,8 +7,8 @@ Remove unnedeed settings.
WARNING: do not remove the Transparency include at the end-->
<PropertyList>
<name><!--my/effect/name--></name>
<inherits-from>Effects/model-combined</inherits-from>
<name><!--my/effect/name--></name>
<inherits-from>Effects/model-combined-transparent</inherits-from>
<parameters>
<!-- Normal Map -->
<normalmap-enabled type="int"> 0 </normalmap-enabled>
@ -83,5 +83,49 @@ WARNING: do not remove the Transparency include at the end-->
### END TRANSPARENCY INCLUDE ###
############################# -->
</parameters>
<!-- Add normalmap include here if needed -->
<!--WARNING: Do not edit above this line -->
<!-- Add normalmap include here, as follows, if needed.
WARNING: do not enable on untextured objects
-->
<!-- ####################
### NORMALMAP INCLUDE ###
######################### -->
<generate>
<tangent type="int">6</tangent>
<binormal type="int">7</binormal>
</generate>
<technique n="8">
<pass>
<program>
<attribute>
<name>tangent</name>
<index>6</index>
</attribute>
<attribute>
<name>binormal</name>
<index>7</index>
</attribute>
</program>
</pass>
</technique>
<technique n="9">
<pass>
<program>
<attribute>
<name>tangent</name>
<index>6</index>
</attribute>
<attribute>
<name>binormal</name>
<index>7</index>
</attribute>
</program>
</pass>
</technique>
<!-- ########################
### END NORMALMAP INCLUDE ###
############################# -->
</PropertyList>

View file

@ -38,7 +38,8 @@
<!-- Reflection -->
<reflection-enabled type="int"> 1 </reflection-enabled>
<reflect-map-enabled type="int"> 1 </reflect-map-enabled>
<reflection-correction type="float"> 0.10 </reflection-correction>
<!-- <reflect-map-enabled type="int"> 0 </reflect-map-enabled> -->
<reflection-correction type="float"> -0.15 </reflection-correction>
<reflection-dynamic type="int"> 0 </reflection-dynamic>
<reflection-fresnel type="float"> 0.0 </reflection-fresnel>
<reflection-rainbow type="float"> 0.0 </reflection-rainbow>
@ -46,12 +47,12 @@
<texture n= "5" >
<type>cubemap</type>
<images>
<positive-x>Aircraft/Generic/Effects/CubeMaps/fgfs-sky/1.png</positive-x>
<negative-x>Aircraft/Generic/Effects/CubeMaps/fgfs-sky/4.png</negative-x>
<positive-y>Aircraft/Generic/Effects/CubeMaps/fgfs-sky/2.png</positive-y>
<negative-y>Aircraft/Generic/Effects/CubeMaps/fgfs-sky/3.png</negative-y>
<positive-z>Aircraft/Generic/Effects/CubeMaps/fgfs-sky/6.png</positive-z>
<negative-z>Aircraft/Generic/Effects/CubeMaps/fgfs-sky/5.png</negative-z>
<positive-x>Aircraft/Generic/Effects/CubeMaps/buildings/N.png</positive-x>
<negative-x>Aircraft/Generic/Effects/CubeMaps/buildings/S.png</negative-x>
<positive-y>Aircraft/Generic/Effects/CubeMaps/buildings/W.png</positive-y>
<negative-y>Aircraft/Generic/Effects/CubeMaps/buildings/E.png</negative-y>
<positive-z>Aircraft/Generic/Effects/CubeMaps/buildings/U.png</positive-z>
<negative-z>Aircraft/Generic/Effects/CubeMaps/buildings/D.png</negative-z>
</images>
</texture>
<!--Ambient correction -->
@ -147,7 +148,7 @@
</texture-unit>
<program>
<vertex-shader n="0">Shaders/include_fog.vert</vertex-shader>
<vertex-shader n="1">Shaders/default.vert</vertex-shader>
<vertex-shader n="1">Shaders/building-default.vert</vertex-shader>
<fragment-shader n="0">Shaders/include_fog.frag</fragment-shader>
<fragment-shader n="1">Shaders/terrain-nocolor.frag</fragment-shader>
</program>
@ -187,7 +188,7 @@
</internal-format>
</texture-unit>
<program>
<vertex-shader>Shaders/terrain-haze.vert</vertex-shader>
<vertex-shader>Shaders/building-haze.vert</vertex-shader>
<fragment-shader>Shaders/terrain-haze.frag</fragment-shader>
</program>
<uniform>
@ -252,11 +253,37 @@
</pass>
</technique>
<technique n="7">
<pass>
<texture-unit n="4">
<unit>4</unit>
<image>
<use>texture[3]/image</use>
</image>
<filter>
<use>texture[3]/filter</use>
</filter>
<wrap-s>
<use>texture[3]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[3]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[3]/internal-format</use>
</internal-format>
</texture-unit>
<program n="0">
<vertex-shader n="0">Shaders/building-ubershader.vert</vertex-shader>
</program>
</pass>
</technique>
<technique n="8">
<pass>
<texture-unit n="4">
<unit>4</unit>
<image>
<image>
<use>texture[3]/image</use>
</image>
<filter>
@ -272,13 +299,17 @@
<use>texture[3]/internal-format</use>
</internal-format>
</texture-unit>
<program n="0">
<vertex-shader n="1">Shaders/building-ubershader.vert</vertex-shader>
</program>
</pass>
</technique>
<technique n="9">
<pass>
<texture-unit n="4">
<unit>4</unit>
<image>
<image>
<use>texture[3]/image</use>
</image>
<filter>
@ -294,6 +325,171 @@
<use>texture[3]/internal-format</use>
</internal-format>
</texture-unit>
<program n="0">
<vertex-shader n="1">Shaders/building-ubershader.vert</vertex-shader>
</program>
</pass>
</technique>
</technique>
<technique n="10">
<pass>
<program n="0">
<vertex-shader n="0">Shaders/building-deferred-gbuffer.vert</vertex-shader>
</program>
</pass>
</technique>
<technique n="11">
<pass>
<program n="0">
<vertex-shader n="0">Shaders/building-default.vert</vertex-shader>
</program>
</pass>
</technique>
<technique n="12">
<pass>
<lighting>true</lighting>
<material>
<active>
<use>material/active</use>
</active>
<ambient>
<use>material/ambient</use>
</ambient>
<diffuse>
<use>material/diffuse</use>
</diffuse>
<specular>
<use>material/specular</use>
</specular>
<emissive>
<use>material/emissive</use>
</emissive>
<shininess>
<use>material/shininess</use>
</shininess>
<color-mode>off</color-mode>
</material>
<render-bin>
<bin-number>2</bin-number>
<bin-name>RenderBin</bin-name>
</render-bin>
<blend>
<active>
<use>blend/active</use>
</active>
<source>
<use>blend/source</use>
</source>
<destination>
<use>blend/destination</use>
</destination>
</blend>
<shade-model>
<use>shade-model</use>
</shade-model>
<cull-face>
<use>cull-face</use>
</cull-face>
<rendering-hint>
<use>rendering-hint</use>
</rendering-hint>
<texture-unit>
<!-- The texture unit is always active because the shaders expect
that. -->
<unit>0</unit>
<!-- If there is a texture, the type in the derived effect
will be "2d". -->
<type>
<use>texture[0]/type</use>
</type>
<image>
<use>texture[0]/image</use>
</image>
<filter>
<use>texture[0]/filter</use>
</filter>
<wrap-s>
<use>texture[0]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[0]/wrap-t</use>
</wrap-t>
<!--
<internal-format>
<use>texture[0]/internal-format</use>
</internal-format>
-->
</texture-unit>
<vertex-program-two-side>
<use>vertex-program-two-side</use>
</vertex-program-two-side>
<program>
<!-- <vertex-shader n="0">Shaders/include_fog.vert</vertex-shader> -->
<!--fog include-->
<vertex-shader n="1">Shaders/building-default.vert</vertex-shader>
<fragment-shader n="0">Shaders/include_fog.frag</fragment-shader>
<!--fog include-->
<fragment-shader n="1">Shaders/default.frag</fragment-shader>
</program>
<!-- BEGIN fog include -->
<uniform>
<name>visibility</name>
<type>float</type>
<value>
<use>visibility</use>
</value>
</uniform>
<uniform>
<name>avisibility</name>
<type>float</type>
<value>
<use>avisibility</use>
</value>
</uniform>
<uniform>
<name>hazeLayerAltitude</name>
<type>float</type>
<value>
<use>lthickness</use>
</value>
</uniform>
<uniform>
<name>scattering</name>
<type>float</type>
<value>
<use>scattering</use>
</value>
</uniform>
<uniform>
<name>terminator</name>
<type>float</type>
<value>
<use>terminator</use>
</value>
</uniform>
<uniform>
<name>fogType</name>
<type>int</type>
<value>
<use>fogtype</use>
</value>
</uniform>
<!-- END fog include -->
<uniform>
<name>texture</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<uniform>
<name>colorMode</name>
<type>int</type>
<value>
<use>material/color-mode-uniform</use>
</value>
</uniform>
</pass>
</technique>
</PropertyList>

View file

@ -9,9 +9,10 @@ the objects that use it, and replaces it with the default shader.
<name>Effects/model-combined-deferred</name>
<inherits-from>Effects/model-combined</inherits-from>
<technique n="8">
<technique n="7">
<predicate>
<and>
<property>/sim/rendering/shaders/model</property>
<property>/sim/rendering/rembrandt/enabled</property>
<or>
<less-equal>
@ -27,33 +28,587 @@ the objects that use it, and replaces it with the default shader.
</or>
</and>
</predicate>
<pass>
<lighting>false</lighting>
<material>
<ambient>
<use>material/ambient</use>
</ambient>
<diffuse>
<use>material/diffuse</use>
</diffuse>
<specular>
<use>material/specular</use>
</specular>
<emissive>
<use>material/emissive</use>
</emissive>
<shininess>
<use>material/shininess</use>
</shininess>
<color-mode>ambient-and-diffuse</color-mode>
</material>
<cull-face>back</cull-face>
<pass>
<lighting>true</lighting>
<material>
<active>
<use>material/active</use>
</active>
<ambient>
<use>material/ambient</use>
</ambient>
<diffuse>
<use>material/diffuse</use>
</diffuse>
<specular>
<use>material/specular</use>
</specular>
<emissive>
<use>material/emissive</use>
</emissive>
<shininess>
<use>material/shininess</use>
</shininess>
<color-mode>
<use>material/color-mode</use>
</color-mode>
</material>
<blend>
<active>
<use>blend/active</use>
</active>
<source>
<use>blend/source</use>
</source>
<destination>
<use>blend/destination</use>
</destination>
</blend>
<shade-model>
<use>shade-model</use>
</shade-model>
<cull-face>
<use>cull-face</use>
</cull-face>
<rendering-hint>
<use>rendering-hint</use>
</rendering-hint>
<blend>
<use>transparent</use>
</blend>
<alpha-test>
<use>transparent</use>
</alpha-test>
<render-bin>
<bin-number>
<use>render-bin/bin-number</use>
</bin-number>
<bin-name>
<use>render-bin/bin-name</use>
</bin-name>
</render-bin>
<!-- Diffuse texture unit-->
<texture-unit>
<unit>0</unit>
<image>
<use>texture[0]/image</use>
</image>
<filter>
<use>texture[0]/filter</use>
</filter>
<wrap-s>
<use>texture[0]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[0]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[0]/internal-format</use>
</internal-format>
</texture-unit>
<!-- Reflection Noise texture unit-->
<texture-unit>
<unit>1</unit>
<type>noise</type>
</texture-unit>
<!-- NormalMap texture unit-->
<texture-unit>
<unit>2</unit>
<image>
<use>texture[2]/image</use>
</image>
<filter>
<use>texture[2]/filter</use>
</filter>
<wrap-s>
<use>texture[2]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[2]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[2]/internal-format</use>
</internal-format>
</texture-unit>
<!-- LightMap texture unit-->
<texture-unit>
<unit>3</unit>
<image>
<use>texture[3]/image</use>
</image>
<filter>
<use>texture[3]/filter</use>
</filter>
<wrap-s>
<use>texture[3]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[3]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[3]/internal-format</use>
</internal-format>
</texture-unit>
<!-- ReflectMap texture unit-->
<texture-unit>
<unit>4</unit>
<image>
<use>texture[4]/image</use>
</image>
<filter>
<use>texture[4]/filter</use>
</filter>
<wrap-s>
<use>texture[4]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[4]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[4]/internal-format</use>
</internal-format>
</texture-unit>
<!-- Reflection CubeMap texture unit-->
<texture-unit>
<unit>5</unit>
<type>
<use>texture[5]/type</use>
</type>
<!-- use this form for a cube cross -->
<!--<image><use>texture[5]/image</use></image>-->
<!-- END CubeCross -->
<!-- use this form for a 6 image cube map -->
<images>
<use>texture[5]/images</use>
</images>
<!-- END 6 image cube map -->
</texture-unit>
<!-- Reflection fresnel texture unit-->
<texture-unit>
<unit>6</unit>
<image>
<use>texture[6]/image</use>
</image>
<filter>
<use>texture[6]/filter</use>
</filter>
<wrap-s>
<use>texture[6]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[6]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[6]/internal-format</use>
</internal-format>
</texture-unit>
<!-- Reflection rainbow texture unit-->
<texture-unit>
<unit>7</unit>
<image>
<use>texture[7]/image</use>
</image>
<filter>
<use>texture[7]/filter</use>
</filter>
<wrap-s>
<use>texture[7]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[7]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[7]/internal-format</use>
</internal-format>
</texture-unit>
<vertex-program-two-side>
<use>vertex-program-two-side</use>
</vertex-program-two-side>
<program>
<vertex-shader>Shaders/ubershader.vert</vertex-shader>
<fragment-shader>Shaders/ubershader-gbuffer.frag</fragment-shader>
<fragment-shader>Shaders/gbuffer-functions.frag</fragment-shader>
<fragment-shader>Shaders/gbuffer-encode.frag</fragment-shader>
</program>
</pass>
</technique>
<uniform>
<name>BaseTex</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<uniform>
<name>ReflNoiseTex</name>
<type>sampler-3d</type>
<value type="int">1</value>
</uniform>
<uniform>
<name>NormalTex</name>
<type>sampler-2d</type>
<value type="int">2</value>
</uniform>
<uniform>
<name>LightMapTex</name>
<type>sampler-2d</type>
<value type="int">3</value>
</uniform>
<uniform>
<name>ReflMapTex</name>
<type>sampler-2d</type>
<value type="int">4</value>
</uniform>
<uniform>
<name>Environment</name>
<type>sampler-cube</type>
<value type="int">5</value>
</uniform>
<uniform>
<name>ReflFresnelTex</name>
<type>sampler-2d</type>
<value type="int">6</value>
</uniform>
<uniform>
<name>ReflRainbowTex</name>
<type>sampler-2d</type>
<value type="int">7</value>
</uniform>
<!-- NORMAL MAP -->
<!-- normalmap is used-->
<uniform>
<name>nmap_enabled</name>
<type>int</type>
<value>
<use>normalmap-enabled</use>
</value>
</uniform>
<!-- normalmap is .dds-->
<uniform>
<name>nmap_dds</name>
<type>int</type>
<value>
<use>normalmap-dds</use>
</value>
</uniform>
<uniform>
<name>nmap_tile</name>
<type>int</type>
<value>
<use>normalmap-tiling</use>
</value>
</uniform>
<!-- LIGHTMAP -->
<!-- lightmap is used -->
<uniform>
<name>lightmap_enabled</name>
<type>int</type>
<value>
<use>lightmap-enabled</use>
</value>
</uniform>
<!-- lightmap is multichannel -->
<uniform>
<name>lightmap_multi</name>
<type>int</type>
<value>
<use>lightmap-multi</use>
</value>
</uniform>
<uniform>
<name>lightmap_r_factor</name>
<type>float</type>
<value>
<use>lightmap-factor[0]</use>
</value>
</uniform>
<uniform>
<name>lightmap_r_color</name>
<type>float-vec3</type>
<value>
<use>lightmap-color[0]</use>
</value>
</uniform>
<uniform>
<name>lightmap_g_factor</name>
<type>float</type>
<value>
<use>lightmap-factor[1]</use>
</value>
</uniform>
<uniform>
<name>lightmap_g_color</name>
<type>float-vec3</type>
<value>
<use>lightmap-color[1]</use>
</value>
</uniform>
<uniform>
<name>lightmap_b_factor</name>
<type>float</type>
<value>
<use>lightmap-factor[2]</use>
</value>
</uniform>
<uniform>
<name>lightmap_b_color</name>
<type>float-vec3</type>
<value>
<use>lightmap-color[2]</use>
</value>
</uniform>
<uniform>
<name>lightmap_a_factor</name>
<type>float</type>
<value>
<use>lightmap-factor[3]</use>
</value>
</uniform>
<uniform>
<name>lightmap_a_color</name>
<type>float-vec3</type>
<value>
<use>lightmap-color[3]</use>
</value>
</uniform>
<!-- reflection is used -->
<uniform>
<name>refl_enabled</name>
<type>int</type>
<value>
<use>reflection-enabled</use>
</value>
</uniform>
<!-- reflection correction -->
<uniform>
<name>refl_correction</name>
<type>float</type>
<value>
<use>reflection-correction</use>
</value>
</uniform>
<!-- use a reflection map-->
<uniform>
<name>refl_map</name>
<type>int</type>
<value>
<use>reflect-map-enabled</use>
</value>
</uniform>
<!-- reflection is dynamic -->
<uniform>
<name>refl_dynamic</name>
<type>int</type>
<value>
<use>reflection-dynamic</use>
</value>
</uniform>
<!-- set the amount of fringing colour 0.0 - 1.0 -->
<uniform>
<name>refl_rainbow</name>
<type>float</type>
<value>
<use>reflection-rainbow</use>
</value>
</uniform>
<!-- set the amount of fresnel effect colour 0.0 - 1.0 -->
<uniform>
<name>refl_fresnel</name>
<type>float</type>
<value>
<use>reflection-fresnel</use>
</value>
</uniform>
<!-- set the amount of noisiness 0.0 - 1.0 -->
<uniform>
<name>refl_noise</name>
<type>float</type>
<value>
<use>reflection-noise</use>
</value>
</uniform>
<!-- dirt -->
<uniform>
<name>dirt_enabled</name>
<type>int</type>
<value>
<use>dirt-enabled</use>
</value>
</uniform>
<uniform>
<name>dirt_multi</name>
<type>int</type>
<value>
<use>dirt-multi</use>
</value>
</uniform>
<uniform>
<name>dirt_r_color</name>
<type>float-vec3</type>
<value>
<use>dirt-color[0]</use>
</value>
</uniform>
<uniform>
<name>dirt_r_factor</name>
<type>float</type>
<value>
<use>dirt-factor[0]</use>
</value>
</uniform>
<uniform>
<name>dirt_g_color</name>
<type>float-vec3</type>
<value>
<use>dirt-color[1]</use>
</value>
</uniform>
<uniform>
<name>dirt_g_factor</name>
<type>float</type>
<value>
<use>dirt-factor[1]</use>
</value>
</uniform>
<uniform>
<name>dirt_b_color</name>
<type>float-vec3</type>
<value>
<use>dirt-color[2]</use>
</value>
</uniform>
<uniform>
<name>dirt_b_factor</name>
<type>float</type>
<value>
<use>dirt-factor[2]</use>
</value>
</uniform>
<!-- set the amount of ambient light correction 0.0 - 1.0 -->
<uniform>
<name>amb_correction</name>
<type>float</type>
<value>
<use>ambient-correction</use>
</value>
</uniform>
<!-- shader quality -->
<uniform>
<name>shader_qual</name>
<type>int</type>
<value>
<use>shader-quality</use>
</value>
</uniform>
<uniform>
<name>hdg</name>
<type>float</type>
<value>
<use>model-hdg</use>
</value>
</uniform>
<uniform>
<name>pitch</name>
<type>float</type>
<value>
<use>model-pitch</use>
</value>
</uniform>
<uniform>
<name>roll</name>
<type>float</type>
<value>
<use>model-roll</use>
</value>
</uniform>
<!-- BEGIN fog include -->
<uniform>
<name>visibility</name>
<type>float</type>
<value>
<use>visibility</use>
</value>
</uniform>
<uniform>
<name>avisibility</name>
<type>float</type>
<value>
<use>avisibility</use>
</value>
</uniform>
<uniform>
<name>hazeLayerAltitude</name>
<type>float</type>
<value>
<use>lthickness</use>
</value>
</uniform>
<uniform>
<name>scattering</name>
<type>float</type>
<value>
<use>scattering</use>
</value>
</uniform>
<uniform>
<name>terminator</name>
<type>float</type>
<value>
<use>terminator</use>
</value>
</uniform>
<uniform>
<name>fogType</name>
<type>int</type>
<value>
<use>fogtype</use>
</value>
</uniform>
<!-- END fog include -->
<uniform>
<name>rembrandt_enabled</name>
<type>int</type>
<value>
<use>rembrandt</use>
</value>
</uniform>
</pass>
</technique>
</PropertyList>

View file

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Stub effect file for transparent Rembrandt ported model-combined,
to provide glass/transparent surfaces with the ubershader active,
and fallback to plain transparency when the model shader is disabled.
-->
<PropertyList>
<name>Effects/model-combined-transparent</name>
<inherits-from>Effects/model-combined</inherits-from>
<technique n="7">
<predicate>
<and>
<equal>
<property>/sim/rendering/shaders/model</property>
<value type="int">0</value>
</equal>
<property>/sim/rendering/rembrandt/enabled</property>
<or>
<less-equal>
<value type="float">2.0</value>
<glversion/>
</less-equal>
<and>
<extension-supported>GL_ARB_shader_objects</extension-supported>
<extension-supported>GL_ARB_shading_language_100</extension-supported>
<extension-supported>GL_ARB_vertex_shader</extension-supported>
<extension-supported>GL_ARB_fragment_shader</extension-supported>
</and>
</or>
</and>
</predicate>
<pass>
<lighting>true</lighting>
<depth>
<write-mask type="bool">false</write-mask>
</depth>
<material>
<active>
<use>material/active</use>
</active>
<ambient>
<use>material/ambient</use>
</ambient>
<diffuse>
<use>material/diffuse</use>
</diffuse>
<specular>
<use>material/specular</use>
</specular>
<emissive>
<use>material/emissive</use>
</emissive>
<shininess>
<use>material/shininess</use>
</shininess>
<color-mode>
<use>material/color-mode</use>
</color-mode>
</material>
<blend>
<active>
<use>blend/active</use>
</active>
<source>
<use>blend/source</use>
</source>
<destination>
<use>blend/destination</use>
</destination>
</blend>
<shade-model>
<use>shade-model</use>
</shade-model>
<cull-face>
<use>cull-face</use>
</cull-face>
<render-bin>
<bin-number>111</bin-number>
<bin-name>DepthSortedBin</bin-name>
</render-bin>
<texture-unit>
<active>
<use>texture[0]/active</use>
</active>
<unit>0</unit>
<image>
<use>texture[0]/image</use>
</image>
<filter>
<use>texture[0]/filter</use>
</filter>
<wrap-s>
<use>texture[0]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[0]/wrap-t</use>
</wrap-t>
<!--
<internal-format>
<use>texture[0]/internal-format</use>
</internal-format>
-->
<environment>
<mode>modulate</mode>
</environment>
</texture-unit>
<!-- A two-sided lighting model is set by default near the root
of the scene graph. Perhaps that ought to be set in this
effect?
-->
</pass>
</technique>
</PropertyList>

View file

@ -173,6 +173,9 @@ please see Docs/README.model-combined.eff for documentation
</predicate>
<pass>
<lighting>true</lighting>
<depth>
<write-mask type="bool">false</write-mask>
</depth>
<material>
<active>
<use>material/active</use>
@ -223,12 +226,8 @@ please see Docs/README.model-combined.eff for documentation
<use>transparent</use>
</alpha-test>
<render-bin>
<bin-number>
<use>render-bin/bin-number</use>
</bin-number>
<bin-name>
<use>render-bin/bin-name</use>
</bin-name>
<bin-number>111</bin-number>
<bin-name>DepthSortedBin</bin-name>
</render-bin>
<!-- Diffuse texture unit-->
<texture-unit>

View file

@ -33,12 +33,116 @@
<fogstructure><use>/environment/fog-structure</use></fogstructure>
<!-- END fog include -->
</parameters>
<technique n="4">
<predicate>
<and>
<property>/sim/rendering/shaders/skydome</property>
<property>/sim/rendering/random-vegetation</property>
<or>
<less-equal>
<value type="float">2.0</value>
<glversion/>
</less-equal>
<and>
<extension-supported>GL_ARB_shader_objects</extension-supported>
<extension-supported>GL_ARB_shading_language_100</extension-supported>
<extension-supported>GL_ARB_vertex_shader</extension-supported>
<extension-supported>GL_ARB_fragment_shader</extension-supported>
<extension-supported>GL_ARB_multisample</extension-supported>
</and>
</or>
</and>
</predicate>
<pass>
<lighting>true</lighting>
<material>
<ambient type="vec4d">1.0 1.0 1.0 1.0</ambient>
<diffuse type="vec4d">1.0 1.0 1.0 1.0</diffuse>
<color-mode>off</color-mode>
</material>
<texture-unit>
<unit>0</unit>
<type>2d</type>
<image>
<use>texture[0]/image</use>
</image>
<wrap-s>clamp</wrap-s>
<wrap-t>clamp</wrap-t>
</texture-unit>
<alpha-to-coverage>true</alpha-to-coverage>
<program>
<vertex-shader>Shaders/tree-haze.vert</vertex-shader>
<fragment-shader>Shaders/tree-haze.frag</fragment-shader>
</program>
<uniform>
<name>visibility</name>
<type>float</type>
<value><use>visibility</use></value>
</uniform>
<uniform>
<name>avisibility</name>
<type>float</type>
<value><use>avisibility</use></value>
</uniform>
<uniform>
<name>hazeLayerAltitude</name>
<type>float</type>
<value><use>lthickness</use></value>
</uniform>
<uniform>
<name>scattering</name>
<type>float</type>
<value><use>scattering</use></value>
</uniform>
<uniform>
<name>ground_scattering</name>
<type>float</type>
<value><use>ground_scattering</use></value>
</uniform>
<uniform>
<name>terminator</name>
<type>float</type>
<value><use>terminator</use></value>
</uniform>
<uniform>
<name>terrain_alt</name>
<type>float</type>
<value><use>terrain_alt</use></value>
</uniform>
<uniform>
<name>overcast</name>
<type>float</type>
<value><use>overcast</use></value>
</uniform>
<uniform>
<name>eye_alt</name>
<type>float</type>
<value><use>eye_alt</use></value>
</uniform>
<uniform>
<name>texture</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<uniform>
<name>colorMode</name>
<type>int</type>
<value>2</value> <!-- AMBIENT_AND_DIFFUSE -->
</uniform>
<!--<depth>
<function>lequal</function>
<write-mask type="bool">false</write-mask>
</depth>-->
</pass>
</technique>
<technique n="5">
<predicate>
<and>
<property>/sim/rendering/shaders/skydome</property>
<property>/sim/rendering/random-vegetation</property>
<property>/sim/rendering/random-vegetation</property>
<or>
<less-equal>
<value type="float">2.0</value>
@ -138,11 +242,9 @@
<write-mask type="bool">false</write-mask>
</depth>-->
</pass>
</technique>
<technique n="9">
<technique n="8">
<predicate>
<and>
<property>/sim/rendering/rembrandt/enabled</property>
@ -182,6 +284,95 @@
</uniform>
</pass>
</technique>
<technique n="9">
<predicate>
<and>
<property>/sim/rendering/random-vegetation</property>
<extension-supported>GL_ARB_multisample</extension-supported>
<extension-supported>GL_ARB_vertex_shader</extension-supported>
<extension-supported>GL_ARB_fragment_shader</extension-supported>
<less-equal>
<value type="float">1.0</value>
<shader-language/>
</less-equal>
</and>
</predicate>
<pass n="0">
<lighting>true</lighting>
<material>
<ambient type="vec4d">1.0 1.0 1.0 1.0</ambient>
<diffuse type="vec4d">1.0 1.0 1.0 1.0</diffuse>
<color-mode>off</color-mode>
</material>
<alpha-to-coverage>true</alpha-to-coverage>
<texture-unit>
<unit>0</unit>
<type>2d</type>
<image>
<use>texture[0]/image</use>
</image>
<wrap-s>clamp</wrap-s>
<wrap-t>clamp</wrap-t>
</texture-unit>
<program>
<!-- <vertex-shader>Shaders/include_fog.vert</vertex-shader> -->
<vertex-shader>Shaders/tree.vert</vertex-shader>
<fragment-shader n="0">Shaders/include_fog.frag</fragment-shader>
<fragment-shader n="1">Shaders/tree.frag</fragment-shader>
</program>
<uniform>
<name>baseTexture</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<!-- BEGIN fog include -->
<uniform>
<name>visibility</name>
<type>float</type>
<value>
<use>visibility</use>
</value>
</uniform>
<uniform>
<name>avisibility</name>
<type>float</type>
<value>
<use>avisibility</use>
</value>
</uniform>
<uniform>
<name>hazeLayerAltitude</name>
<type>float</type>
<value>
<use>lthickness</use>
</value>
</uniform>
<uniform>
<name>scattering</name>
<type>float</type>
<value>
<use>scattering</use>
</value>
</uniform>
<uniform>
<name>terminator</name>
<type>float</type>
<value>
<use>terminator</use>
</value>
</uniform>
<uniform>
<name>fogType</name>
<type>int</type>
<value>
<use>fogtype</use>
</value>
</uniform>
<!-- END fog include -->
</pass>
</technique>
<technique n="10">
<predicate>
<and>

View file

@ -179,6 +179,7 @@
<!-- TODO: handle variable winds -->
<filter include="layer-heading-offset.xml"/>
<filter include="layer-heading-offset.xml">
<name>MetarController:layer:wind-from-heading-deg_0</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -192,6 +193,7 @@
<output>/environment/config/aloft/entry[0]/wind-from-heading-deg</output>
</filter>
<filter include="layer-heading-offset.xml">
<name>MetarController:layer:wind-from-heading-deg_1</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -205,6 +207,7 @@
<output>/environment/config/aloft/entry[1]/wind-from-heading-deg</output>
</filter>
<filter include="layer-heading-offset.xml">
<name>MetarController:layer:wind-from-heading-deg_2</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -218,6 +221,7 @@
<output>/environment/config/aloft/entry[2]/wind-from-heading-deg</output>
</filter>
<filter include="layer-heading-offset.xml">
<name>MetarController:layer:wind-from-heading-deg_3</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -231,6 +235,7 @@
<output>/environment/config/aloft/entry[3]/wind-from-heading-deg</output>
</filter>
<filter include="layer-heading-offset.xml">
<name>MetarController:layer:wind-from-heading-deg_4</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -246,6 +251,7 @@
<filter include="layer-speed-change.xml"/>
<filter include="layer-speed-change.xml">
<name>MetarController:layer:wind-speed-kt_0</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -259,6 +265,7 @@
<output>/environment/config/aloft/entry[0]/wind-speed-kt</output>
</filter>
<filter include="layer-speed-change.xml">
<name>MetarController:layer:wind-speed-kt_1</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -272,6 +279,7 @@
<output>/environment/config/aloft/entry[1]/wind-speed-kt</output>
</filter>
<filter include="layer-speed-change.xml">
<name>MetarController:layer:wind-speed-kt_2</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -285,6 +293,7 @@
<output>/environment/config/aloft/entry[2]/wind-speed-kt</output>
</filter>
<filter include="layer-speed-change.xml">
<name>MetarController:layer:wind-speed-kt_3</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -298,6 +307,7 @@
<output>/environment/config/aloft/entry[3]/wind-speed-kt</output>
</filter>
<filter include="layer-speed-change.xml">
<name>MetarController:layer:wind-speed-kt_4</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -314,24 +324,28 @@
<!-- Clouds -->
<filter include="clouds-altitude-interpolate.xml"/>
<filter include="clouds-altitude-interpolate.xml">
<name>MetarController:clouds:altitude_interpolate_0</name>
<params>
<from>/environment/metar/clouds/layer[1]/elevation-ft</from>
<to>/environment/clouds/layer[1]/elevation-ft</to>
</params>
</filter>
<filter include="clouds-altitude-interpolate.xml">
<name>MetarController:clouds:altitude_interpolate_1</name>
<params>
<from>/environment/metar/clouds/layer[2]/elevation-ft</from>
<to>/environment/clouds/layer[2]/elevation-ft</to>
</params>
</filter>
<filter include="clouds-altitude-interpolate.xml">
<name>MetarController:clouds:altitude_interpolate_2</name>
<params>
<from>/environment/metar/clouds/layer[3]/elevation-ft</from>
<to>/environment/clouds/layer[3]/elevation-ft</to>
</params>
</filter>
<filter include="clouds-altitude-interpolate.xml">
<name>MetarController:clouds:altitude_interpolate_3</name>
<params>
<from>/environment/metar/clouds/layer[4]/elevation-ft</from>
<to>/environment/clouds/layer[4]/elevation-ft</to>
@ -340,42 +354,50 @@
<filter include="clouds-thickness.xml"/>
<filter include="clouds-thickness.xml">
<name>MetarController:clouds:thickness_0</name>
<input>/environment/metar/clouds/layer[1]/thickness-ft</input>
<output>/environment/clouds/layer[1]/thickness-ft</output>
</filter>
<filter include="clouds-thickness.xml">
<name>MetarController:clouds:thickness_1</name>
<input>/environment/metar/clouds/layer[2]/thickness-ft</input>
<output>/environment/clouds/layer[2]/thickness-ft</output>
</filter>
<filter include="clouds-thickness.xml">
<name>MetarController:clouds:thickness_2</name>
<input>/environment/metar/clouds/layer[3]/thickness-ft</input>
<output>/environment/clouds/layer[3]/thickness-ft</output>
</filter>
<filter include="clouds-thickness.xml">
<name>MetarController:clouds:thickness_3</name>
<input>/environment/metar/clouds/layer[4]/thickness-ft</input>
<output>/environment/clouds/layer[4]/thickness-ft</output>
</filter>
<filter include="clouds-coverage.xml"/>
<filter include="clouds-coverage.xml">
<name>MetarController:clouds:coverage_0</name>
<params>
<from>/environment/metar/clouds/layer[1]/coverage-type</from>
<to>environment/clouds/layer[1]/coverage-type</to>
</params>
</filter>
<filter include="clouds-coverage.xml">
<name>MetarController:clouds:coverage_1</name>
<params>
<from>/environment/metar/clouds/layer[2]/coverage-type</from>
<to>environment/clouds/layer[2]/coverage-type</to>
</params>
</filter>
<filter include="clouds-coverage.xml">
<name>MetarController:clouds:coverage_2</name>
<params>
<from>/environment/metar/clouds/layer[3]/coverage-type</from>
<to>environment/clouds/layer[3]/coverage-type</to>
</params>
</filter>
<filter include="clouds-coverage.xml">
<name>MetarController:clouds:coverage_3</name>
<params>
<from>/environment/metar/clouds/layer[4]/coverage-type</from>
<to>environment/clouds/layer[4]/coverage-type</to>

View file

@ -12,6 +12,7 @@
<PropertyList>
<name>Logitech Attack 3</name>
<name>Logitech Logitech Attack 3</name>
<axis n="0">

View file

@ -20,6 +20,9 @@
Button 13/14 (left hand quadrant buttons): Flaps Up/Down
Buttons 15/16 (middle quadrant buttons): Gear Up/Down
Buttons 17/18 (right quandrant buttons): Spoilers Up/Down
Button 19 (Throttle < 0): Reverse Thrust
Button 20 (Prop < 0): Propellor Beta
Button 21 (Mixture <0) : Cut-off
Buttons 23/24/25 (right hand selector switch): View direction Sensitivity
-->
@ -32,7 +35,7 @@
<name>Pro Flight Cessna Yoke</name>
<axis n="0">
<name>Yoke left/right</name>
<name>Yoke lepft/right</name>
<desc>Aileron</desc>
<binding>
<command>property-scale</command>
@ -379,6 +382,191 @@
</binding>
</mod-up>
</button>
<button n="19"> <!-- Power < 0 -->
<name>Throttle pushed below 0</name>
<desc>Thrust reverser/beta</desc>
<repeatable>false</repeatable>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[0]/reverser</property>
<value>true</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[1]/reverser</property>
<value>true</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[2]/reverser</property>
<value>true</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[3]/reverser</property>
<value>true</value>
</binding>
<binding>
<command>property-assign</command>
<property>/engines/engine[0]/reverse-thrust</property>
<value>1</value>
</binding>
<binding>
<command>property-assign</command>
<property>/engines/engine[1]/reverse-thrust</property>
<value>1</value>
</binding>
<binding>
<command>property-assign</command>
<property>/engines/engine[2]/reverse-thrust</property>
<value>1</value>
</binding>
<binding>
<command>property-assign</command>
<property>/engines/engine[3]/reverse-thrust</property>
<value>1</value>
</binding>
<mod-up>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[0]/reverser</property>
<value>false</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[1]/reverser</property>
<value>false</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[2]/reverser</property>
<value>false</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[3]/reverser</property>
<value>false</value>
</binding>
<binding>
<command>property-assign</command>
<property>/engines/engine[0]/reverse-thrust</property>
<value>0</value>
</binding>
<binding>
<command>property-assign</command>
<property>/engines/engine[1]/reverse-thrust</property>
<value>0</value>
</binding>
<binding>
<command>property-assign</command>
<property>/engines/engine[2]/reverse-thrust</property>
<value>0</value>
</binding>
<binding>
<command>property-assign</command>
<property>/engines/engine[3]/reverse-thrust</property>
<value>0</value>
</binding>
</mod-up>
</button>
<button n="20"> <!-- Propeller < 0 -->
<name>Propeller pushed below 0</name>
<desc>Feather Prop</desc>
<repeatable>false</repeatable>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[0]/propeller-feather</property>
<value>true</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[1]/propeller-feather</property>
<value>true</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[2]/propeller-feather</property>
<value>true</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[3]/propeller-feather</property>
<value>true</value>
</binding>
<mod-up>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[0]/propeller-feather</property>
<value>false</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[1]/propeller-feather</property>
<value>false</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[2]/propeller-feather</property>
<value>false</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[3]/propeller-feather</property>
<value>false</value>
</binding>
</mod-up>
</button>
<button n="21"> <!-- Mixture < 0 -->
<name>Mixture pushed below 0</name>
<desc>Engine cut-off</desc>
<repeatable>false</repeatable>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[0]/cutoff</property>
<value>true</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[1]/cutoff</property>
<value>true</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[2]/cutoff</property>
<value>true</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[3]/cutoff</property>
<value>true</value>
</binding>
<mod-up>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[0]/cutoff</property>
<value>false</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[1]/cutoff</property>
<value>false</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[2]/cutoff</property>
<value>false</value>
</binding>
<binding>
<command>property-assign</command>
<property>/controls/engines/engine[3]/cutoff</property>
<value>false</value>
</binding>
</mod-up>
</button>
<button n="22">
<name>Yoke mode switch left</name>
<desc>Coolie hat sensitivity low</desc>

View file

@ -60,5 +60,10 @@ var PropertyElement = {
return node.getValue();
else
return default;
}
},
getBool: func(key)
{
me._node.getNode(key, 1).getBoolValue();
},
};

View file

@ -218,10 +218,13 @@ var Element = {
{
me.setBool("visible", visible);
},
getVisible: func me.getBool("visible"),
# Hide element (Shortcut for setVisible(0))
hide: func me.setVisible(0),
# Show element (Shortcut for setVisible(1))
show: func me.setVisible(1),
# Toggle element visibility
toggleVisibility: func me.setVisible( !me.getVisible() ),
#
setGeoPosition: func(lat, lon)
{
@ -266,15 +269,18 @@ var Element = {
getBoundingBox: func()
{
var bb = me._node.getNode("bounding-box");
var min_x = bb.getNode("min-x").getValue();
if( min_x != nil )
return [ min_x,
bb.getNode("min-y").getValue(),
bb.getNode("max-x").getValue(),
bb.getNode("max-y").getValue() ];
else
return [0, 0, 0, 0];
if( bb != nil )
{
var min_x = bb.getNode("min-x").getValue();
if( min_x != nil )
return [ min_x,
bb.getNode("min-y").getValue(),
bb.getNode("max-x").getValue(),
bb.getNode("max-y").getValue() ];
}
return [0, 0, 0, 0];
},
# Set transformation center (currently only used for rotation)
setCenter: func()
@ -324,6 +330,7 @@ var Element = {
# Class for a group element on a canvas
#
var Group = {
# public:
new: func(node, id)
{
return { parents: [Group, Element.new(node, id)] };
@ -342,6 +349,17 @@ var Group = {
return factory([me._node, type], id);
},
# Get a vector of all child elements
getChildren: func()
{
var children = [];
foreach(var c; me._node.getChildren())
if( me._isElementNode(c) )
append(children, me._wrapElement(c));
return children;
},
# Get first child with given id (breadth-first search)
#
# @note Use with care as it can take several miliseconds (for me eg. ~2ms).
@ -361,15 +379,11 @@ var Group = {
{
var node_id = node.getNode("id");
if( node_id != nil and node_id.getValue() == id )
# Create element from existing node
return me._element_factories[ node.getName() ](node, nil);
return me._wrapElement(node);
}
foreach(var c; node.getChildren())
# element nodes have type NONE and valid element names (those in the the
# factor list)
if( c.getType() == "NONE"
and me._element_factories[ c.getName() ] != nil )
if( me._isElementNode(c) )
append(stack, c);
}
},
@ -379,6 +393,19 @@ var Group = {
foreach(var type; keys(me._element_factories))
me._node.removeChildren(type, 0);
return me;
},
# private:
_isElementNode: func(el)
{
# element nodes have type NONE and valid element names (those in the factory
# list)
return el.getType() == "NONE"
and me._element_factories[ el.getName() ] != nil;
},
_wrapElement: func(node)
{
# Create element from existing node
return me._element_factories[ node.getName() ](node, nil);
}
};

23
Nasal/canvas/design.txt Normal file
View file

@ -0,0 +1,23 @@
Nothing set in stone yet, we'll document things once the API becomes more stable and once it has been used in several dialogs and instruments
At the moment, this implements the notion of a "LayeredMap", a LayeredMap is a conventional Canvas Map which has support for easily managing "Layers",
which are internally mapped to Canvas Groups. Each Group's "visible" property is managed by the LayeredMap, so that layers can be easily
toggled on/off, i.e. via checkboxes.
Basically, the idea is this, we'll have a MVC (Model/View/Controller) setup, where:
- the Model is mapped to the drawable's meta information (i.e. position)
- the View is mapped to a conventional canvas group
- the Controller is mapped to a bunch of property/timer callbacks to control the Model/View
Model = PositionedSource
View = Canvas
Controller = control properties (zoom, range etc)
LayerElement = callback to create a canvas group
Layer = canvas.Group
Map -> LayeredMap -> GenericMap -> AirportMap

View file

@ -0,0 +1,105 @@
<?xml version="1.0"?>
<!--
generic-canvas.map XML:
- to be used by dialogs and instruments to add a generic map (navaids, fixes, airports etc)
- with each feature put on a separate layer (canvas group)
- each layer being controllable via a boolean property
NOTE: This is still work in progress, and will be significantly refactored in the time to come
Current requirements: (these are subject to change)
Dialogs wanting to use this, MUST:
- set DIALOG_CANVAS in open block
- provide a helper function dialog_property(p) to return a property appended to the dialog root in /sim/gui/dialogs/FOO/
- to set up layer-checkboxes automatically, use canvas.GenericMap.setupGUICheckboxes(DIALOG_CANVAS, gui_group)
For example, add this to your dialogs Nasal/open block in "foo.xml":
var dialog_name = "foo";
var dialog_property = func(p) return "/sim/gui/dialogs/foo/"~p;
var DIALOG_CANVAS = gui.findElementByName(cmdarg(), "airport-selection");
canvas.GenericMap.setupGUICheckboxes(DIALOG_CANVAS, "canvas-control");
TODO: use a single "InitCanvasMapSupport();" helper
In the close block, you'll want to call "map.cleanup_listeners()" at the moment
-->
<PropertyList>
<!--FIXME: move somewhere else, this is GUI specific and not useful for canvas maps shown as instruments! -->
<checkbox-toggle-template>
<name></name>
<label></label>
<property></property>
<binding>
<command>dialog-apply</command>
<object-name></object-name>
</binding>
</checkbox-toggle-template>
<!-- will be procedurally added to the dialog -->
<zoom-template>
<button>
<name>zoomout</name>
<legend>-</legend>
<pref-width>22</pref-width>
<pref-height>22</pref-height>
<binding>
<command>property-adjust</command>
<property></property>
<min>0</min>
<step>-1</step>
</binding>
</button>
<text>
<label>MMMM</label>
<halign>center</halign>
<format>Zoom %d</format>
<property></property>
<live>true</live>
</text>
<button>
<name>zoomin</name>
<legend>+</legend>
<pref-width>22</pref-width>
<pref-height>22</pref-height>
<binding>
<command>property-adjust</command>
<property></property>
<step>1</step>
<max></max> <!-- FIXME: compute dynamically via Nasal size() or just a property-->
</binding>
</button>
<empty><stretch>true</stretch></empty>
</zoom-template>
<nasal>
<load><![CDATA[
var my_canvas = canvas.get(cmdarg());
my_canvas.setColorBackground(0.2, 0.5, 0.2, 0.5); #TODO: support customization in XML
var root = my_canvas.createGroup();
# the top level AirportMap element uses a "GenericMap" now:
#TODO: features should be procedurally enabled via params (WIP)
#TODO: use generic Map and instantiate via XML
var map = canvas.GenericMap.new(parent:root, name:dialog_name) # FIXME: We shouldn't be using AirportMap here:
# we need a high level wrapper that can instantiate
# all sorts of maps, not just AirportMaps
.setTranslation(300, 200) # TODO: move to Map class ctor!
.setupZoom( dialog:DIALOG_CANVAS ) # TODO: make zooming configurable for non GUI use
.pickupFeatures (DIALOG_CANVAS); # set up the features specified in the XML file
# FIXME: resource cleanup (listeners!)
update_info();
]]>
</load>
</nasal>
</PropertyList>

580
Nasal/canvas/map.nas Normal file
View file

@ -0,0 +1,580 @@
###
# map.nas - provide a high level method to create typical maps in FlightGear (airports, navaids, fixes and waypoints) for both, the GUI and instruments
# implements the notion of a "layer" by using canvas groups and adding geo-referenced elements to a layer
# layered maps are linked to boolean properties so that visibility can be easily toggled (GUI checkboxes or cockpit hotspots)
# without having to redraw other layers
#
# GOALS: have a single Nasal/Canvas wrapper for all sort of maps in FlightGear, that can be easily shared and reused for different purposes
#
# DESIGN: ... is slowly evolving, but still very much beta for the time being
#
# API: not yet documented, but see eventually design.txt (will need to add doxygen-strings then)
#
# PERFORMANCE: will be improved, probabaly by moving some features to C++ space and optimizing things there
#
#
# ISSUES: just look for the FIXME and TODO strings - currently, the priority is to create an OOP/MVC design with less specialized code in XML files
#
#
# ROADMAP: Generalize this further, so that:
#
# - it can be easily reused
# - use a MVC approach, where layer-specific data is provided by a Model object
# - other dialogs can use this without tons of custom code (airports.xml, route-manager.xml, map-canvas.xml)
# - generalize this further so that it can be used by instruments
# - implement additional layers (tcas, wxradar, agradar) - especially expose the required data to Nasal
# - implement better GUI support (events) so that zooming/panning via mouse can be supported
# - make the whole thing styleable
#
# - keep track of things getting added here and decide if they should better move to the core canvas module or the C++ code
#
#
# C++ RFEs:
# - overload findNavaidsWithinRange() to support an optional position argument, so that arbitrary navaids can be looked up
# - add Nasal extension function to get scenery vector data (landclass)
# -
# -
#
var DEBUG=0;
if (DEBUG) {
var benchmark = debug.benchmark;
}
else {
var benchmark = func(label, code) code(); # NOP
}
var assert = func(label, expr) expr and die(label);
# Mapping from surface codes to #TODO: make this XML-configurable
var SURFACECOLORS = {
1 : { type: "asphalt", r:0.2, g:0.2, b:0.2 },
2 : { type: "concrete", r:0.3, g:0.3, b:0.3 },
3 : { type: "turf", r:0.2, g:0.5, b:0.2 },
4 : { type: "dirt", r:0.4, g:0.3, b:0.3 },
5 : { type: "gravel", r:0.35, g:0.3, b:0.3 },
# Helipads
6 : { type: "asphalt", r:0.2, g:0.2, b:0.2 },
7 : { type: "concrete", r:0.3, g:0.3, b:0.3 },
8 : { type: "turf", r:0.2, g:0.5, b:0.2 },
9 : { type: "dirt", r:0.4, g:0.3, b:0.3 },
0 : { type: "gravel", r:0.35, g:0.3, b:0.3 },
};
###
# ALL LayeredMap "draws" go through this wrapper, which makes it easy to check what's going on:
var draw_layer = func(layer, callback, lod) {
var name= layer._view.get("id");
# print("Canvas:Draw op triggered"); # just to make sure that we are not adding unnecessary data when checking/unchecking a checkbox
if (DEBUG and name=="taxiways") fgcommand("profiler-start"); #without my patch, this is a no op, so no need to disable
#print("Work items:", size(layer._model._elements));
benchmark("Drawing Layer:"~layer._view.get("id"), func
foreach(var element; layer._model._elements) {
#print(typeof(layer._view));
#debug.dump(layer._view);
callback(layer._view, element, lod); # ISSUE here
});
if (! layer._model.hasData() ) print("Layer was EMPTY:", name);
if (DEBUG and name=="taxiways") fgcommand("profiler-stop");
layer._drawn=1; #TODO: this should be encapsulated
}
# Runway
#
var Runway = {
# Create Runway from hash
#
# @param rwy Hash containing runway data as returned from
# airportinfo().runways[ <runway designator> ]
new: func(rwy)
{
return {
parents: [Runway],
rwy: rwy
};
},
# Get a point on the runway with the given offset
#
# @param pos Position along the center line
# @param off Offset perpendicular to the center line
pointOffCenterline: func(pos, off = 0)
{
var coord = geo.Coord.new();
coord.set_latlon(me.rwy.lat, me.rwy.lon);
coord.apply_course_distance(me.rwy.heading, pos - 0.5 * me.rwy.length);
if( off )
coord.apply_course_distance(me.rwy.heading + 90, off);
return ["N" ~ coord.lat(), "E" ~ coord.lon()];
}
};
var make = func return {parents:arg};
##
# TODO: Create a cache to reuse layers and layer data (i.e. runways)
##
# Todo: wrap parsesvg and return a function that memoizes the created canvas group, so that svg files only need to be parsed once
#
##
# TODO: Implement a real MVC design for "LayeredMaps" that have:
# - a "DataProvider" (i.e. Positioned objects)
# - a View (i.e. a Canvas)
# - a controller (i.e. input/output properties)
#
var MapModel = {}; # navaids, waypoints, fixes etc
MapModel.new = func make(MapModel);
var MapView = {}; # the canvas view, including a layer for each feature
MapView.new = func make(MapView);
var MapController = {}; # the property tree interface to manipulate the model/view via properties
MapController.new = func make(MapController);
var LazyView = {}; # Gets drawables on demand from the model - via property toggle
var DataProvider = {};
DataProvider.new = func make(DataProvider);
###
# for airports, navaids, fixes, waypoints etc
var PositionedProvider = {};
PositionedProvider.new = func make(DataProvider, PositionedProvider);
##
# Drawable
#
## LayerElement (UNUSED ATM):
# for runways, navaids, fixes, waypoints etc
# TODO: we should differentiate between "fairly static" vs. "dynamic" layers - i.e. navaids vs. traffic
var LayerElement = {_drawable:nil};
LayerElement.new = func(drawable) {
var temp = make(LayerElement);
temp._drawable=drawable;
return temp;
}
# a drawable is either a Nasal callback or a scalar, i.e. a path to an SVG file
LayerElement.draw = func(group) {
(typeof(me._drawable)=='func') and drawable(group) or canvas.parsesvg(group,_drawable);
}
# For static targets like Navaids, Fixes - i.e. geographic position doesn't change
var StaticLayerElement = {};
# For moving targets such as aircraft, multiplayer, ai traffic etc
var DynamicLayerElement = {};
var AnimatedLayerElement = {};
# for elements whose appearance may change depending on selected range (i.e. LOD)
var RangeAwareLayerElement = {};
##
# A layer model is just a wrapper for a vector with elements
# either updated via a timer or via a listener
var LayerModel = {_elements:[], _view:, _controller: };
LayerModel.new = func make(LayerModel);
LayerModel.clear = func me._elements = [];
LayerModel.push = func (e) append(me._elements, e);
LayerModel.get = func me._elements;
LayerModel.update = func;
LayerModel.hasData = func size(me. _elements);
LayerModel.setView = func(v) me._view=v;
LayerModel.setController = func(c) me._controller=c;
var LayerController = {};
LayerController.new = func make(LayerController);
##
# use timers to update the model/view (canvas)
var TimeBasedLayerController = {};
LayerController.new = func make(TimeBasedLayerController);
##
# use listeners to update the model/view (canvas)
#
var ListenerBasedLayerController = {};
ListenerBasedLayerController.new = func make(ListenerBasedLayerController);
##
# Uses, both, listeners and timers to update the model/view (canvas)
#
var HybridLayerController = {};
HybridLayerController.new = func make(HybridLayerController);
var ModelEvents = {INIT:, RESET:, UPDATE:};
var ViewEvents = {INIT:, RESET:, UPDATE:};
var ControllerEvents = {INIT:, RESET: , UPDATE:, ZOOM:, PAN:, };
##
# A layer is mapped to a canvas group
# Layers are linked to a single boolean property to toggle them on/off
var Layer = { _model: ,
_view: ,
_controller: ,
_drawn:0,
};
Layer.new = func(group, name, model) {
#print("Setting up new Layer:", name);
var m = make(Layer);
m._model = model.new();
#print("Model name is:", m._model.name);
m._view = group.createChild("group",name);
m.name = name; #FIXME: not needed, there's already _view.get("id")
return m;
}
Layer.hide = func me._view.setVisible(0);
Layer.show = func me._view.setVisible(1);
#TODO: Unify toggle and update methods - and support lazy drawing (make it optional!)
Layer.toggle = func {
# print("Toggling layer");
var checkbox = getprop(me.display_layer);
if(checkbox and !me._drawn) {
# print("Lazy drawing");
me.draw();
}
#var state= me._view.getBool("visible");
#print("Toggle layer visibility ",me.display_layer," checkbox is", checkbox);
#print("Layer id is:", me._view.get("id"));
#print("Drawn is:", me._drawn);
checkbox?me._view.setVisible(1) : me._view.setVisible(0);
}
Layer.reset = func {
me._view.removeAllChildren(); # clear the "real" canvas drawables
me._model.clear(); # the vector is used for lazy rendering
assert("Model not emptied during layer reset!", me._model.hasData() );
me._drawn = 0;
}
#TODO: Unify toggle and update
Layer.update = func {
# print("Layer update: Check if layer is visible, if so, draw");
if (! getprop(me.display_layer)) return; # checkbox for layer not set
if (!me._model.hasData() ) return; # no data available
# print("Trying to draw");
me.draw();
}
Layer.setDraw = func(callback) me.draw = callback;
Layer.setController = func(c) me._controller=c; # TODO: implement
Layer.setModel = func(m) nil; # TODO: implement
##TODO: differentiate between layers with a single object (i.e. aircraft) and multiple objects (airports)
##
# We may need to display some stuff that isn't strictly a geopgraphic feature, but just a chart feature
#
var CartographicLayer = {};
#TODO:
var InteractiveLayer = {};
###
# PositionedLayer
#
# layer of positioned objects (i.e. have lat,lon,alt)
#
var PositionedLayer = {};
PositionedLayer.new = func() {
make( Layer.new() , PositionedLayer );
}
###
# CachedLayer
#
# when re-centering on an airport already loaded, we don't want to reload it
# but change the reference point and load missing airports
var CachedLayer = {};
##
#
var AirportProvider = {};
AirportProvider.new = func make(AirportProvider);
AirportProvider.get = func {
return airportinfo("ksfo");
}
### Data Providers (preparation for MVC version):
# TODO: should use the LayerModel class
#
##
# Manage a bunch of layers
#
var LayerManager = {};
# WXR ?
# TODO: Stub
var MapBehavior = {};
MapBehavior.new = make(MapBehavior);
MapBehavior.zoom = func;
MapBehavior.center = func;
##
# A layered map consists of several layers
# TODO: Support nested LayeredMaps, where a LayeredMap may contain other LayeredMaps
# TODO: use MapBehavior here and move the zoom/refpos methods there, so that map behavior can be easily customized
var LayeredMap = { ranges:[],
zoom_property:nil, listeners:[],
update_property:nil, layers:[],
};
LayeredMap.new = func(parent, name)
return make(LayeredMap, parent.createChild("map",name) );
LayeredMap.listen = func(p,c) { #FIXME: listening should be managed by each m/v/c separately
# print("Setting up LayeredMap-managed listener:", p);
append(me.listeners, setlistener(p, c));
}
LayeredMap.initializeLayers = func {
# print("initializing all layers and updating");
foreach(var l; me.layers)
l.update();
}
LayeredMap.setRefPos = func(lat, lon) {
# print("RefPos set");
me._node.getNode("ref-lat", 1).setDoubleValue(lat);
me._node.getNode("ref-lon", 1).setDoubleValue(lon);
me; # chainable
}
LayeredMap.setHdg = func(hdg) {
me._node.getNode("hdg",1).setDoubleValue(hdg);
me; # chainable
}
LayeredMap.updateZoom = func {
var z = getprop(me.zoom_property) or 0;
var zoom = me.ranges[ size(me.ranges)-1 -z];
# print("Setting zoom range to:", zoom);
benchmark("Zooming map:"~zoom, func
me._node.getNode("range", 1).setDoubleValue(zoom)
);
me; #chainable
}
# this is a huge hack at the moment, we need to encapsulate the setRefPos/setHdg methods, so that they are exposed to XML space
#
LayeredMap.updateState = func {
# center map on airport TODO: should be moved to a method and wrapped with a controller so that behavior can be customizeda
#var apt = me.layers[0]._model._elements[0];
# FIXME:
#me.setRefPos(lat:me._refpos.lat, lon:me._refpos.lon);
me.setHdg(0.0);
me.updateZoom();
}
#
# TODO: this is currently GUI specific and not re-usable for instruments
LayeredMap.setupZoom = func(dialog) {
var dlgroot = dialog.getNode("features/dialog-root").getValue();#FIXME: GUI specific - needs to be re-implemented for instruments
var zoom_property = dlgroot ~"/"~dialog.getNode("features/range-property").getValue(); #FIXME: this doesn't belong here, need to be in ctor instead !!!
ranges=dialog.getNode("features/ranges").getChildren("range");
foreach(var r; ranges)
append(me.ranges, r.getValue() );
# print("Setting up Zoom Ranges:", size(ranges)-1);
me.zoom_property=zoom_property;
me.listen(zoom_property, func me.updateZoom() );
me.updateZoom();
me; #chainable
}
LayeredMap.setZoom = func {} #TODO
LayeredMap.resetLayers = func {
benchmark("Resetting LayeredMap", func
foreach(var l; me.layers) { #TODO: hide all layers, hide map
l.reset();
}
);
}
#FIXME: listener management should be done at the MVC level, for each component - not as part of the LayeredMap!
LayeredMap.cleanup_listeners = func {
print("Cleaning up listeners");
foreach(var l; me.listeners)
removelistener(l);
}
###
# GenericMap: A generic map is a layered map that puts all supported features on a different layer (canvas group) so that
# they can be individually toggled on/off so that unnecessary updates are avoided, there are methods to link layers to boolean properties
# so that they can be easily associated with GUI properties (checkboxes) or cockpit hotspots
# TODO: generalize the XML-parametrization and move it to a helper class
var GenericMap = { };
GenericMap.new = func(parent, name) make(LayeredMap.new(parent:parent, name:name), GenericMap);
GenericMap.setupLayer = func(layer, property) {
var l = MAP_LAYERS[layer].new(me, layer); # Layer.new(me, layer);
l.display_layer = property; #FIXME: use controller object instead here and this overlaps with update_property
#print("Set up layer with toggle property=", property);
l._view.setVisible( getprop(property) ) ;
append(me.layers, l);
return l;
}
# features are layers - so this will do layer setup and then register listeners for each layer
GenericMap.setupFeature = func(layer, property, init ) {
var l=me.setupLayer( layer, property );
me.listen(property, func l.toggle() ); #TODO: should use the controller object here !
l._model._update_property=property; #TODO: move somewhere else - this is the property that is mapped to the CHECKBOX
l._model._view_handle = l; #FIXME: very crude, set a handle to the view(group), so that the model can notify it (for updates)
l._model._map_handle = me; #FIXME: added here so that layers can send update requests to the parent map
#print("Setting up layer init for property:", init);
l._model._input_property = init; # FIXME: init property = input property - needs to be improved!
me.listen(init, func l._model.init() ); #TODO: makes sure that the layer's init method for the MODEL is invoked
me; #chainable
};
# This will read in the config and procedurally instantiate all requested layers and link them to toggle properties
# FIXME: this is currently GUI specific and doesn't yet support instrument use, i.e. needs to be generalized further
GenericMap.pickupFeatures = func(DIALOG_CANVAS) {
var dlgroot = DIALOG_CANVAS.getNode("features/dialog-root").getValue();
# print("Picking up features for:", DIALOG_CANVAS.getPath() );
var layers=DIALOG_CANVAS.getNode("features").getChildren("layer");
foreach(var n; layers) {
var name = n.getNode("name").getValue();
var toggle = n.getNode("property").getValue();
var init = n.getNode("init-property").getValue();
init = dlgroot ~"/"~init;
var property = dlgroot ~"/"~toggle;
# print("Adding layer:",n.getNode("name").getValue() );
me.setupFeature(name, property, init);
}
me;
}
# NOT a method, cmdarg() is no longer meaningful when the canvas nasal block is executed
# so this needs to be called in the dialog's OPEN block instead - TODO: generalize
#FIXME: move somewhere else, this is a GUI helper and should probably be generalized and moved to gui.nas
GenericMap.setupGUI = func (dialog, group) {
var group = gui.findElementByName(cmdarg() , group);
var layers=dialog.getNode("features").getChildren("layer");
var template = dialog.getNode("checkbox-toggle-template");
var dlgroot = dialog.getNode("features/dialog-root").getValue();
var zoom = dlgroot ~"/"~ dialog.getNode("features/range-property").getValue();
var i=0;
foreach(var n; layers) {
var name = n.getNode("name").getValue();
var toggle = dlgroot ~ "/" ~ n.getNode("property").getValue();
var label = n.getNode("description",1).getValue() or name;
var default = n.getNode("default",1).getValue();
default = (default=="enabled")?1:0;
#print("Layer default for", name ," is:", default);
setprop(toggle, default); # set the checkbox to its default setting
var hide_checkbox = n.getNode("hide-checkbox",1).getValue();
hide_checkbox = (hide_checkbox=="true")?1:0;
var checkbox = group.getChild("checkbox",i, 1); #FIXME: compute proper offset dynamically, will currently overwrite other existing checkboxes!
props.copy(template, checkbox);
checkbox.getNode("name").setValue("display-"~name);
checkbox.getNode("label").setValue(label);
checkbox.getNode("property").setValue(toggle);
checkbox.getNode("binding/object-name").setValue("display-"~name);
checkbox.getNode("enabled",1).setValue(!hide_checkbox);
i+=1;
}
#add zoom buttons procedurally:
var template = dialog.getNode("zoom-template");
template.getNode("button[0]/binding[0]/property[0]").setValue(zoom);
template.getNode("text[0]/property[0]").setValue(zoom);
template.getNode("button[1]/binding[0]/property[0]").setValue(zoom);
template.getNode("button[1]/binding[0]/max[0]").setValue( i );
props.copy(template, group);
}
###
# TODO: StylableGenericMap (colors, fonts, symbols)
#
var AirportMap = {};
AirportMap.new = func(parent,name) make(GenericMap.new(parent,name), AirportMap);
#TODO: Use real MVC (DataProvider/PositionedProvider) here
# this is currently "directly" invoked via a listener, needs to be changed
# to use the controller object instead
# TODO: adopt real MVC here
# FIXME: this must currently be explicitly called by the model, we need to use a wrapper to call it automatically instead!
LayerModel.notifyView = func () {
# print("View notified");
me._view_handle.update(); # update the layer/group
me._map_handle.updateState(); # update the map
}
# ID
var SingleAirportProvider = {};
# inputs: position, range
var MultiAirportProvider = {};
#TODO: remove and unify with update()
AirportMap.init = func {
me.resetLayers();
me.updateState();
}
# MultiObjectLayer:
# - Airports
# - Traffic (MP/AI)
# - Navaids
#
# TODO: a "MapLayer" is a full MVC implementation that is owned by a "LayeredMap"
var MAP_LAYERS = {};
var register_layer = func(name, layer) MAP_LAYERS[name]=layer;
var MVC_FOLDER = getprop("/sim/fg-root") ~ "/Nasal/canvas/map/";
var load_modules = func(vec) foreach(var file; vec) io.load_nasal(MVC_FOLDER~file, "canvas");
# TODO: read in the file names dynamically: *.draw, *.model, *.layer
var DRAWABLES = ["navaid.draw", "parking.draw", "runways.draw", "taxiways.draw", "tower.draw"];
load_modules(DRAWABLES);
var MODELS = ["airports.model", "navaids.model",];
load_modules(MODELS);
var LAYERS = ["runways.layer", "taxiways.layer", "parking.layer", "tower.layer", "navaids.layer","test.layer",];
load_modules(LAYERS);
#TODO: Implement!
var CONTROLLERS = [];
load_modules(CONTROLLERS);

View file

View file

@ -0,0 +1,27 @@
var AirportModel = {};
AirportModel.new = func make(AirportModel, LayerModel);
# FIXME: Just testing for now: This really shouldn't be part of the core LayerModel, needs to go to "AirportModel" instead
# FIXME: This will get called ONCE for EACH layer that uses the AirportModel, so VERY inefficient ATM! => should be shared among layers
AirportModel.init = func {
# print("AirportModel initialized!");
# me._map_handle.resetLayers();
me._view_handle.reset();
var id = getprop(me._input_property); # HACK: this needs to be handled via the controller - introduce "input_property"
#print("ID is:", id);
(id == "") and return;
var apt=airportinfo(id); # FIXME: replace with controller call to update the model
#var airports = findAirportsWithinRange(apt.lat, apt.lon, 10); # HACK: expose the range !!
foreach(var a; [ apt ]) #FIXME: move to separate method: "populate"
# print("storing:", a.id) and
me.push(a);
#print("Work items in Model:", me.hasData() );
#print("Model updated!!");
# set RefPos and hdg to apt !!
me._map_handle.setRefPos(apt.lat, apt.lon);
#TODO: Notify view on update - use proper NOTIFICATIONS (INIT; UPDATE etc)
me.notifyView();
}

View file

View file

@ -0,0 +1,15 @@
##
# FIXME: until we have better instancing support for symbols, it would be better to return a functor here
# so that symbols are only parsed once
var NAVAID_CACHE = {};
var draw_navaid = func (group, navaid, lod) {
#var group = group.createChild("group", "navaid");
DEBUG and print("Drawing navaid:", navaid.id);
var symbols = {NDB:"/gui/dialogs/images/ndb_symbol.svg"}; # TODO: add more navaid symbols here
if (symbols[navaid.type] == nil) return print("Missing svg image for navaid:", navaid.type);
var symbol_navaid = group.createChild("group", "navaid");
canvas.parsesvg(symbol_navaid, symbols[navaid.type]);
symbol_navaid.setGeoPosition(navaid.lat, navaid.lon);
}

View file

@ -0,0 +1,9 @@
var NavLayer = {};
NavLayer.new = func(group,name) {
var m=Layer.new(group, name, NavaidModel);
m.setDraw (func draw_layer(layer:m, callback: draw_navaid, lod:0) );
return m;
}
register_layer("navaids", NavLayer);

View file

@ -0,0 +1,11 @@
var NavaidModel = {};
NavaidModel.new = func make(LayerModel, NavaidModel);
NavaidModel.init = func {
me._view_handle.reset();
var navaids = findNavaidsWithinRange(15);
foreach(var n; navaids)
me.push(n);
me.notifyView();
}

View file

@ -0,0 +1,15 @@
var draw_parking = func(group, apt, lod) {
var group = group.createChild("group", "apt-"~apt.id);
foreach(var park; apt.parking())
{
var icon_park =
group.createChild("text", "parking-" ~ park.name)
.setDrawMode( canvas.Text.ALIGNMENT
+ canvas.Text.TEXT )
.setText(park.name)
.setFont("LiberationFonts/LiberationMono-Bold.ttf")
.setGeoPosition(park.lat, park.lon)
.setFontSize(15, 1.3);
}
}

View file

@ -0,0 +1,9 @@
#TODO: use custom Model/DataProvider
var ParkingLayer = {}; # make(Layer);
ParkingLayer.new = func(group, name) {
var m=Layer.new(group, name, AirportModel ); #FIXME: AirportModel can be shared by Taxiways, Runways etc!!
m.setDraw( func draw_layer(layer: m, callback: draw_parking, lod:0 ) );
return m;
}
register_layer("parkings", ParkingLayer);

View file

@ -0,0 +1,113 @@
#TODO: split: draw_single_runway(pos)
var draw_runways = func(group, apt,lod) {
DEBUG and print("Drawing runways for:", apt.id);
# var group = group.createChild("group", "apt-"~apt.id);
# group = group.createChild("group", "runways");
var rws_done = {};
foreach(var rw; keys(apt.runways))
{
var is_heli = substr(rw, 0, 1) == "H";
var rw_dir = is_heli ? nil : int(substr(rw, 0, 2));
var rw_rec = "";
var thresh_rec = 0;
if( rw_dir != nil )
{
rw_rec = sprintf("%02d", math.mod(rw_dir - 18, 36));
if( size(rw) == 3 )
{
var map_rec = {
"R": "L",
"L": "R",
"C": "C"
};
rw_rec ~= map_rec[substr(rw, 2)];
}
if( rws_done[rw_rec] != nil )
continue;
var rw_rec = apt.runways[rw_rec];
if( rw_rec != nil )
thresh_rec = rw_rec.threshold;
}
rws_done[rw] = 1;
rw = apt.runways[rw];
var clr = SURFACECOLORS[rw.surface];
if (clr == nil) { clr = SURFACECOLORS[0]};
var icon_rw =
group.createChild("path", "runway-" ~ rw.id)
.setStrokeLineWidth(0.5)
.setColor(1.0,1.0,1.0)
.setColorFill(clr.r, clr.g, clr.b);
var rwy = Runway.new(rw);
var beg_thr = rwy.pointOffCenterline(rw.threshold);
var beg_thr1 = rwy.pointOffCenterline(rw.threshold, 0.5 * rw.width);
var beg_thr2 = rwy.pointOffCenterline(rw.threshold, -0.5 * rw.width);
var beg1 = rwy.pointOffCenterline(0, 0.5 * rw.width);
var beg2 = rwy.pointOffCenterline(0, -0.5 * rw.width);
var end_thr = rwy.pointOffCenterline(rw.length - thresh_rec);
var end_thr1 = rwy.pointOffCenterline(rw.length - thresh_rec, 0.5 * rw.width);
var end_thr2 = rwy.pointOffCenterline(rw.length - thresh_rec, -0.5 * rw.width);
var end1 = rwy.pointOffCenterline(rw.length, 0.5 * rw.width);
var end2 = rwy.pointOffCenterline(rw.length, -0.5 * rw.width);
icon_rw.setDataGeo
(
[ canvas.Path.VG_MOVE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_CLOSE_PATH ],
[ beg1[0], beg1[1],
beg2[0], beg2[1],
end2[0], end2[1],
end1[0], end1[1] ]
);
if( rw.length / rw.width > 3 and !is_heli )
{
# only runways which are much longer than wide are
# real runways, otherwise it's probably a heliport.
var icon_cl =
group.createChild("path", "centerline")
.setStrokeLineWidth(0.5)
.setColor(1,1,1)
.setStrokeDashArray([15, 10]);
icon_cl.setDataGeo
(
[ canvas.Path.VG_MOVE_TO,
canvas.Path.VG_LINE_TO ],
[ beg_thr[0], beg_thr[1],
end_thr[0], end_thr[1] ]
);
var icon_thr =
group.createChild("path", "threshold")
.setStrokeLineWidth(1.5)
.setColor(1,1,1);
icon_thr.setDataGeo
(
[ canvas.Path.VG_MOVE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_MOVE_TO,
canvas.Path.VG_LINE_TO ],
[ beg_thr1[0], beg_thr1[1],
beg_thr2[0], beg_thr2[1],
end_thr1[0], end_thr1[1],
end_thr2[0], end_thr2[1] ]
);
}
}
}

View file

@ -0,0 +1,10 @@
#TODO: use custom Model/DataProvider
var RunwayLayer = {}; # make(Layer);
RunwayLayer.new = func(group, name) {
# print("Setting up new TestLayer");
var m=Layer.new(group, name, AirportModel ); #FIXME: AirportModel can be shared by Taxiways, Runways etc!!
m.setDraw( func draw_layer(layer: m, callback: draw_runways, lod:0 ) );
return m;
}
register_layer("runways", RunwayLayer);

View file

@ -0,0 +1,40 @@
var draw_taxiways = func(group, apt, lod) { # TODO: the LOD arg isn't stricly needed here,
# the layer is a conventional canvas group, so it can access its map
# parent and just read the "range" property to do LOD handling
group.set("z-index",-100); # HACK: we need to encapsulate this
# var group = group.createChild("group", "apt-"~apt.id); #FIXME: we don't need to use two nested groups for each taxiway - performance?
# group = group.createChild("group", "taxiways");
# print("drawing taxiways for:", apt.id);
# Taxiways drawn first so the runways and parking positions end up on top.
foreach(var taxi; apt.taxiways)
{
var clr = SURFACECOLORS[taxi.surface];
if (clr == nil) { clr = SURFACECOLORS[0]};
var icon_taxi =
group.createChild("path", "taxi")
.setStrokeLineWidth(0)
.setColor(clr.r, clr.g, clr.b)
.setColorFill(clr.r, clr.g, clr.b);
var txi = Runway.new(taxi);
var beg1 = txi.pointOffCenterline(0, 0.5 * taxi.width);
var beg2 = txi.pointOffCenterline(0, -0.5 * taxi.width);
var end1 = txi.pointOffCenterline(taxi.length, 0.5 * taxi.width);
var end2 = txi.pointOffCenterline(taxi.length, -0.5 * taxi.width);
icon_taxi.setDataGeo
(
[ canvas.Path.VG_MOVE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_CLOSE_PATH ],
[ beg1[0], beg1[1],
beg2[0], beg2[1],
end2[0], end2[1],
end1[0], end1[1] ]
);
}
}

View file

@ -0,0 +1,11 @@
#TODO: use custom Model/DataProvider
var TaxiwayLayer = {}; # make(Layer);
TaxiwayLayer.new = func(group, name) {
# print("Setting up new TestLayer");
var m=Layer.new(group, name, AirportModel ); #FIXME: AirportModel can be shared by Taxiways, Runways etc!!
m.setDraw( func draw_layer(layer: m, callback: draw_taxiways, lod:0 ) );
return m;
}
register_layer("taxiways", TaxiwayLayer);

View file

@ -0,0 +1,11 @@
#TODO: use custom Model/DataProvider
var TestLayer = {}; # make(Layer);
TestLayer.new = func(group, name) {
# print("Setting up new TestLayer");
var m=Layer.new(group, name, AirportModel ); #FIXME: AirportModel can be shared by Taxiways, Runways etc!!
m.setDraw( func draw_layer(layer: m, callback: MAP_LAYERS["runways"], lod:0 ) );
return m;
}
register_layer("airport_test", TestLayer);

View file

@ -0,0 +1,19 @@
var draw_tower = func (group, apt,lod) {
var group = group.createChild("group", "tower");
# TODO: move to map_elements.nas (tower, runway, parking etc)
# i.e.: set_element(group, "tower", "style");
var icon_tower =
group.createChild("path", "tower")
.setStrokeLineWidth(1)
.setScale(1.5)
.setColor(0.2,0.2,1.0)
.moveTo(-3, 0)
.vert(-10)
.line(-3, -10)
.horiz(12)
.line(-3, 10)
.vert(10);
icon_tower.setGeoPosition(apt.lat, apt.lon);
}

View file

@ -0,0 +1,8 @@
var TowerLayer = {};
TowerLayer.new = func(group, name) {
var m=Layer.new(group, name, AirportModel ); #FIXME: AirportModel can be shared by Taxiways, Runways etc!!
m.setDraw( func draw_layer(layer: m, callback: draw_tower, lod:0 ) );
return m;
}
register_layer("towers", TowerLayer);

View file

View file

@ -146,6 +146,7 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
# enable/disable menu entries
menuEnable("fuel-and-payload", fdm == "yasim" or fdm == "jsb");
menuEnable("aircraft-checklists", props.globals.getNode("/sim/checklists") != nil);
var isAutopilotMenuEnabled = func {
foreach( var apdp; autopilotDisableProps ) {
if( props.globals.getNode( apdp ) != nil )
@ -158,6 +159,7 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
menuEnable("rendering-buffers", getprop("/sim/rendering/rembrandt/enabled"));
menuEnable("rembrandt-buffers-choice", getprop("/sim/rendering/rembrandt/enabled"));
menuEnable("stereoscopic-options", !getprop("/sim/rendering/rembrandt/enabled"));
menuEnable("sound-config", getprop("/sim/sound/working"));
# frame-per-second display
var fps = props.globals.getNode("/sim/rendering/fps-display", 1);

View file

@ -611,7 +611,7 @@ var readConfig = func(dialog_root="/sim/gui/dialogs/joystick-config") {
if (a != nil) {
# Read properties from bindings
props.copy(a, p.getNode("original_binding", 1));
props.copy(a, btn.getNode("original_binding", 1));
var binding = nil;
foreach (var b; joystick.buttonBindings) {
if ((binding == nil) and (a != nil) and b.match(a)) {

View file

@ -412,9 +412,8 @@ var model = {
me.callsign = {};
foreach (var n; props.globals.getNode("ai/models", 1).getChildren("multiplayer")) {
if (!n.getNode("valid").getValue())
if ((var valid = n.getNode("valid")) == nil or (!valid.getValue()))
continue;
if ((var callsign = n.getNode("callsign")) == nil or !(callsign = callsign.getValue()))
continue;
if (!(callsign = string.trim(callsign)))

View file

@ -0,0 +1,80 @@
// -*-C++-*-
// Shader that uses OpenGL state values to do per-pixel lighting
//
// The only light used is gl_LightSource[0], which is assumed to be
// directional.
//
// Diffuse colors come from the gl_Color, ambient from the material. This is
// equivalent to osg::Material::DIFFUSE.
#version 120
#define MODE_OFF 0
#define MODE_DIFFUSE 1
#define MODE_AMBIENT_AND_DIFFUSE 2
// The constant term of the lighting equation that doesn't depend on
// the surface normal is passed in gl_{Front,Back}Color. The alpha
// component is set to 1 for front, 0 for back in order to work around
// bugs with gl_FrontFacing in the fragment shader.
varying vec4 diffuse_term;
varying vec3 normal;
uniform int colorMode;
////fog "include"////////
//uniform int fogType;
//
//void fog_Func(int type);
/////////////////////////
void main()
{
// Determine the rotation for the building. The Color alpha value provides rotation information
float sr = sin(6.28 * gl_Color.a);
float cr = cos(6.28 * gl_Color.a);
vec3 position = gl_Vertex.xyz;
// Rotation of the building and movement into position
position.xy = vec2(dot(position.xy, vec2(cr, sr)), dot(position.xy, vec2(-sr, cr)));
position = position + gl_Color.xyz;
gl_Position = gl_ModelViewProjectionMatrix * vec4(position,1.0);
//gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
// Rotate the normal.
normal = gl_Normal;
normal.xy = vec2(dot(normal.xy, vec2(cr, sr)), dot(normal.xy, vec2(-sr, cr)));
normal = gl_NormalMatrix * normal;
vec4 ambient_color, diffuse_color;
if (colorMode == MODE_DIFFUSE) {
diffuse_color = vec4(1.0,1.0,1.0,1.0);
ambient_color = gl_FrontMaterial.ambient;
} else if (colorMode == MODE_AMBIENT_AND_DIFFUSE) {
diffuse_color = vec4(1.0,1.0,1.0,1.0);
ambient_color = vec4(1.0,1.0,1.0,1.0);
} else {
diffuse_color = gl_FrontMaterial.diffuse;
ambient_color = gl_FrontMaterial.ambient;
}
diffuse_term = diffuse_color * gl_LightSource[0].diffuse;
vec4 constant_term = gl_FrontMaterial.emission + ambient_color *
(gl_LightModel.ambient + gl_LightSource[0].ambient);
// Super hack: if diffuse material alpha is less than 1, assume a
// transparency animation is at work
if (gl_FrontMaterial.diffuse.a < 1.0)
diffuse_term.a = gl_FrontMaterial.diffuse.a;
else
diffuse_term.a = 1.0;
// Another hack for supporting two-sided lighting without using
// gl_FrontFacing in the fragment shader.
gl_FrontColor.rgb = constant_term.rgb; gl_FrontColor.a = 1.0;
gl_BackColor.rgb = constant_term.rgb; gl_BackColor.a = 0.0;
//fogCoord = abs(ecPosition.z / ecPosition.w);
//fog_Func(fogType);
}

View file

@ -0,0 +1,30 @@
// -*- mode: C; -*-
// Licence: GPL v2
// Author: Frederic Bouvier.
//
varying vec3 ecNormal;
varying float alpha;
void main() {
// Determine the rotation for the building. The Color alpha value provides rotation information
float sr = sin(6.28 * gl_Color.a);
float cr = cos(6.28 * gl_Color.a);
vec3 position = gl_Vertex.xyz;
// Rotation of the building and movement into position
position.xy = vec2(dot(position.xy, vec2(cr, sr)), dot(position.xy, vec2(-sr, cr)));
position = position + gl_Color.xyz;
gl_Position = gl_ModelViewProjectionMatrix * vec4(position,1.0);
// Rotate the normal.
ecNormal = gl_Normal;
ecNormal.xy = vec2(dot(ecNormal.xy, vec2(cr, sr)), dot(ecNormal.xy, vec2(-sr, cr)));
ecNormal = gl_NormalMatrix * ecNormal;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0);
gl_BackColor = vec4(1.0, 1.0, 1.0, 1.0);
alpha = 1.0;
}

254
Shaders/building-haze.vert Normal file
View file

@ -0,0 +1,254 @@
// -*-C++-*-
// Shader that uses OpenGL state values to do per-pixel lighting
//
// The only light used is gl_LightSource[0], which is assumed to be
// directional.
//
// Diffuse colors come from the gl_Color, ambient from the material. This is
// equivalent to osg::Material::DIFFUSE.
// Haze part added by Thorsten Renk, Oct. 2011
#define MODE_OFF 0
#define MODE_DIFFUSE 1
#define MODE_AMBIENT_AND_DIFFUSE 2
// The constant term of the lighting equation that doesn't depend on
// the surface normal is passed in gl_{Front,Back}Color. The alpha
// component is set to 1 for front, 0 for back in order to work around
// bugs with gl_FrontFacing in the fragment shader.
varying vec4 diffuse_term;
varying vec3 normal;
varying vec3 relPos;
//varying float earthShade;
//varying float yprime;
//varying float vertex_alt;
varying float yprime_alt;
varying float mie_angle;
uniform int colorMode;
uniform float hazeLayerAltitude;
uniform float terminator;
uniform float terrain_alt;
uniform float avisibility;
uniform float visibility;
uniform float overcast;
//uniform float scattering;
uniform float ground_scattering;
// This is the value used in the skydome scattering shader - use the same here for consistency?
const float EarthRadius = 5800000.0;
const float terminator_width = 200000.0;
float earthShade;
float light_func (in float x, in float a, in float b, in float c, in float d, in float e)
{
//x = x - 0.5;
// use the asymptotics to shorten computations
if (x < -15.0) {return 0.0;}
return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
}
void main()
{
vec4 light_diffuse;
vec4 light_ambient;
//float yprime_alt;
float yprime;
float lightArg;
float intensity;
float vertex_alt;
float scattering;
// this code is copied from default.vert
//vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex;
// Determine the rotation for the building. The Color alpha value provides rotation information
float sr = sin(6.28 * gl_Color.a);
float cr = cos(6.28 * gl_Color.a);
vec3 position = gl_Vertex.xyz;
// Rotation of the building and movement into position
position.xy = vec2(dot(position.xy, vec2(cr, sr)), dot(position.xy, vec2(-sr, cr)));
position = position + gl_Color.xyz;
gl_Position = gl_ModelViewProjectionMatrix * vec4(position,1.0);
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
// Rotate the normal.
normal = gl_Normal;
normal.xy = vec2(dot(normal.xy, vec2(cr, sr)), dot(normal.xy, vec2(-sr, cr)));
normal = gl_NormalMatrix * normal;
vec4 ambient_color, diffuse_color;
if (colorMode == MODE_DIFFUSE) {
diffuse_color = vec4(1.0,1.0,1.0,1.0);
ambient_color = gl_FrontMaterial.ambient;
} else if (colorMode == MODE_AMBIENT_AND_DIFFUSE) {
diffuse_color = vec4(1.0,1.0,1.0,1.0);
ambient_color = vec4(1.0,1.0,1.0,1.0);
} else {
diffuse_color = gl_FrontMaterial.diffuse;
ambient_color = gl_FrontMaterial.ambient;
}
// here start computations for the haze layer
// we need several geometrical quantities
// first current altitude of eye position in model space
vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
// and relative position to vector
relPos = gl_Vertex.xyz + gl_Color.xyz - ep.xyz;
// unfortunately, we need the distance in the vertex shader, although the more accurate version
// is later computed in the fragment shader again
float dist = length(relPos);
// altitude of the vertex in question, somehow zero leads to artefacts, so ensure it is at least 100m
vertex_alt = max(gl_Vertex.z + gl_Color.z,100.0);
scattering = ground_scattering + (1.0 - ground_scattering) * smoothstep(hazeLayerAltitude -100.0, hazeLayerAltitude + 100.0, vertex_alt);
// branch dependent on daytime
if (terminator < 1000000.0) // the full, sunrise and sunset computation
{
// establish coordinates relative to sun position
vec3 lightFull = (gl_ModelViewMatrixInverse * gl_LightSource[0].position).xyz;
vec3 lightHorizon = normalize(vec3(lightFull.x,lightFull.y, 0.0));
// yprime is the distance of the vertex into sun direction
yprime = -dot(relPos, lightHorizon);
// this gets an altitude correction, higher terrain gets to see the sun earlier
yprime_alt = yprime - sqrt(2.0 * EarthRadius * vertex_alt);
// two times terminator width governs how quickly light fades into shadow
// now the light-dimming factor
earthShade = 0.6 * (1.0 - smoothstep(-terminator_width+ terminator, terminator_width + terminator, yprime_alt)) + 0.4;
// parametrized version of the Flightgear ground lighting function
lightArg = (terminator-yprime_alt)/100000.0;
// directional scattering for low sun
if (lightArg < 10.0)
{mie_angle = (0.5 * dot(normalize(relPos), normalize(lightFull)) ) + 0.5;}
else
{mie_angle = 1.0;}
light_diffuse.b = light_func(lightArg, 1.330e-05, 0.264, 3.827, 1.08e-05, 1.0);
light_diffuse.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
light_diffuse.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
light_diffuse.a = 0.0;
light_diffuse = light_diffuse * scattering;
light_ambient.b = light_func(lightArg, 0.000506, 0.131, -3.315, 0.000457, 0.5);
light_ambient.g = light_func(lightArg, 2.264e-05, 0.134, 0.967, 3.66e-05, 0.4);
light_ambient.r = light_func(lightArg, 0.236, 0.253, 1.073, 0.572, 0.33);
light_ambient.a = 0.0;
// correct ambient light intensity and hue before sunrise
if (earthShade < 0.5)
{
light_ambient = light_ambient * (0.7 + 0.3 * smoothstep(0.2, 0.5, earthShade));
intensity = length(light_ambient.xyz);
light_ambient.xyz = intensity * normalize(mix(light_ambient.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.8,earthShade) ));
intensity = length(light_diffuse.xyz);
light_diffuse.xyz = intensity * normalize(mix(light_diffuse.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.7,earthShade) ));
}
// the haze gets the light at the altitude of the haze top if the vertex in view is below
// but the light at the vertex if the vertex is above
vertex_alt = max(vertex_alt,hazeLayerAltitude);
if (vertex_alt > hazeLayerAltitude)
{
if (dist > 0.8 * avisibility)
{
vertex_alt = mix(vertex_alt, hazeLayerAltitude, smoothstep(0.8*avisibility, avisibility, dist));
yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
}
}
else
{
vertex_alt = hazeLayerAltitude;
yprime_alt = yprime -sqrt(2.0 * EarthRadius * vertex_alt);
}
}
else // the faster, full-day version without lightfields
{
//vertex_alt = max(gl_Vertex.z,100.0);
earthShade = 1.0;
mie_angle = 1.0;
if (terminator > 3000000.0)
{light_diffuse = vec4 (1.0, 1.0, 1.0, 0.0);
light_ambient = vec4 (0.33, 0.4, 0.5, 0.0); }
else
{
lightArg = (terminator/100000.0 - 10.0)/20.0;
light_diffuse.b = 0.78 + lightArg * 0.21;
light_diffuse.g = 0.907 + lightArg * 0.091;
light_diffuse.r = 0.904 + lightArg * 0.092;
light_diffuse.a = 0.0;
light_ambient.b = 0.41 + lightArg * 0.08;
light_ambient.g = 0.333 + lightArg * 0.06;
light_ambient.r = 0.316 + lightArg * 0.016;
light_ambient.a = 0.0;
}
light_diffuse = light_diffuse * scattering;
yprime_alt = -sqrt(2.0 * EarthRadius * hazeLayerAltitude);
}
// default lighting based on texture and material using the light we have just computed
diffuse_term = diffuse_color* light_diffuse;
vec4 constant_term = gl_FrontMaterial.emission + ambient_color *
(gl_LightModel.ambient + light_ambient);
// Super hack: if diffuse material alpha is less than 1, assume a
// transparency animation is at work
if (gl_FrontMaterial.diffuse.a < 1.0)
diffuse_term.a = gl_FrontMaterial.diffuse.a;
else
diffuse_term.a = 1.0;
// Another hack for supporting two-sided lighting without using
// gl_FrontFacing in the fragment shader.
gl_FrontColor.rgb = constant_term.rgb; gl_FrontColor.a = 1.0;
gl_BackColor.rgb = constant_term.rgb; gl_BackColor.a = 0.0;
}

View file

@ -0,0 +1,126 @@
// -*- mode: C; -*-
// Licence: GPL v2
// © Emilian Huminiuc and Vivian Meazza 2011
#version 120
varying vec3 rawpos;
varying vec3 VNormal;
varying vec3 VTangent;
varying vec3 VBinormal;
varying vec3 vViewVec;
varying vec3 reflVec;
varying float alpha;
attribute vec3 tangent;
attribute vec3 binormal;
uniform float pitch;
uniform float roll;
uniform float hdg;
uniform int refl_dynamic;
uniform int nmap_enabled;
uniform int shader_qual;
uniform int rembrandt_enabled;
uniform int color_is_position;
//////Fog Include///////////
// uniform int fogType;
// void fog_Func(int type);
////////////////////////////
void rotationMatrixPR(in float sinRx, in float cosRx, in float sinRy, in float cosRy, out mat4 rotmat)
{
rotmat = mat4( cosRy , sinRx * sinRy , cosRx * sinRy, 0.0,
0.0 , cosRx , -sinRx * cosRx, 0.0,
-sinRy, sinRx * cosRy, cosRx * cosRy , 0.0,
0.0 , 0.0 , 0.0 , 1.0 );
}
void rotationMatrixH(in float sinRz, in float cosRz, out mat4 rotmat)
{
rotmat = mat4( cosRz, -sinRz, 0.0, 0.0,
sinRz, cosRz, 0.0, 0.0,
0.0 , 0.0 , 1.0, 0.0,
0.0 , 0.0 , 0.0, 1.0 );
}
void main(void)
{
float sr = sin(6.28 * gl_Color.a);
float cr = cos(6.28 * gl_Color.a);
rawpos = gl_Vertex.xyz;
// Rotation of the object and movement into position
rawpos.xy = vec2(dot(rawpos.xy, vec2(cr, sr)), dot(rawpos.xy, vec2(-sr, cr)));
rawpos = rawpos + gl_Color.xyz;
vec4 ecPosition = gl_ModelViewMatrix * vec4(rawpos.x, rawpos.y, rawpos.z, 1.0);
//fog_Func(fogType);
// Rotate the normal.
vec3 normal = gl_Normal;
normal.xy = vec2(dot(normal.xy, vec2(cr, sr)), dot(normal.xy, vec2(-sr, cr)));
//normal = gl_NormalMatrix * normal;
VNormal = normalize(gl_NormalMatrix * normal);
if (nmap_enabled > 0 && shader_qual > 2){
VTangent = normalize(gl_NormalMatrix * tangent);
VBinormal = normalize(gl_NormalMatrix * binormal);
} else {
VTangent = vec3(0.0);
VBinormal = vec3 (0.0);
}
vec3 n = normalize(normal);
vec3 t = cross(n, vec3(1.0,0.0,0.0));
vec3 b = cross(n,t);
// Super hack: if diffuse material alpha is less than 1, assume a
// transparency animation is at work
if (gl_FrontMaterial.diffuse.a < 1.0)
alpha = gl_FrontMaterial.diffuse.a;
else
alpha = 1.0;
// Vertex in eye coordinates
vec3 vertVec = ecPosition.xyz;
vViewVec.x = dot(t, vertVec);
vViewVec.y = dot(b, vertVec);
vViewVec.z = dot(n, vertVec);
// calculate the reflection vector
vec4 reflect_eye = vec4(reflect(vertVec, VNormal), 0.0);
vec3 reflVec_stat = normalize(gl_ModelViewMatrixInverse * reflect_eye).xyz;
if (refl_dynamic > 0){
//prepare rotation matrix
mat4 RotMatPR;
mat4 RotMatH;
float _roll = roll;
if (_roll>90.0 || _roll < -90.0)
{
_roll = -_roll;
}
float cosRx = cos(radians(_roll));
float sinRx = sin(radians(_roll));
float cosRy = cos(radians(-pitch));
float sinRy = sin(radians(-pitch));
float cosRz = cos(radians(hdg));
float sinRz = sin(radians(hdg));
rotationMatrixPR(sinRx, cosRx, sinRy, cosRy, RotMatPR);
rotationMatrixH(sinRz, cosRz, RotMatH);
vec3 reflVec_dyn = (RotMatH * (RotMatPR * normalize(gl_ModelViewMatrixInverse * reflect_eye))).xyz;
reflVec = reflVec_dyn;
} else {
reflVec = reflVec_stat;
}
if(rembrandt_enabled < 1){
gl_FrontColor = gl_FrontMaterial.emission + vec4(1.0,1.0,1.0,1.0)
* (gl_LightModel.ambient + gl_LightSource[0].ambient);
} else {
gl_FrontColor = vec4(1.0,1.0,1.0,1.0);
}
gl_Position = gl_ModelViewProjectionMatrix * vec4(rawpos,1.0);
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
}

View file

@ -90,7 +90,7 @@ void main (void)
N = normalize(VNormal);
}
///END bump
vec4 reflection = textureCube(Environment, reflVec * N);
vec4 reflection = textureCube(Environment, reflVec * dot(N,VNormal));
vec3 viewVec = normalize(vViewVec);
float v = abs(dot(viewVec, normalize(VNormal)));// Map a rainbowish color
vec4 fresnel = texture2D(ReflFresnelTex, vec2(v, 0.0));

BIN
Sounds/rattleroll.wav Normal file

Binary file not shown.

View file

@ -123,11 +123,21 @@
<!-- Help menu -->
<help>Hilfe</help> <!-- English: "Help" -->
<help-browser>Hilfe (im Browser)</help-browser> <!-- English: "Help (opens in browser)" -->
<doc-browser>Erweiterte Dokumentation</doc-browser> <!-- English: "Documentation Browser" -->
<aircraft-keys>Flugzeug Hilfe</aircraft-keys> <!-- English: "Aircraft Help" -->
<aircraft-checklists>Flugzeug Checklisten</aircraft-checklists> <!-- English: "Aircraft Checklists" -->
<common-keys>Tastenbelegung (Flugzeugsteuerung)</common-keys> <!-- English: "Common Aircraft Keys" -->
<basic-keys>Tastenbelegung (allgemein)</basic-keys> <!-- English: "Basic Simulator Keys" -->
<joystick-info>Joystick Informationen</joystick-info> <!-- English: "Joystick Information" -->
<tutorial-start>Tutorials</tutorial-start> <!-- English: "Tutorials" -->
<menu-about>Über FlightGear</menu-about> <!-- English: "About" -->
<!-- Aircraft menu (only frequent/common custom menu entries are supported) -->
<select-livery>Lackierung auswählen</select-livery>
<show-hide-yokes>Steuerhorn aus-/einblenden</show-hide-yokes>
<immatriculation>Luftfahrzeugkennzeichen</immatriculation>
<pushback>Flugzeugschlepper</pushback>
<autostart>Autostart</autostart>
<tiller-steering>Bugradsteuerung</tiller-steering>
</PropertyList>

38
Translations/de/sys.xml Normal file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- FlightGear system messages: German language resource -->
<!-- ###
### This file is automatically synchronized with the master (=English language) resource.
### Please do not add comments, change order or restructure the file.
###
### To translate:
### * Replace "???" entries with appropriate translation.
### * Keep untranslated items unmodified (leave the "???"). English original is the
### automatic default.
### * Remove enclosing "<!-_ ... _->" tags for completed translations.
### * Keep the original English text unmodified (the '<!-_ English: "..." -_>)',
### so we know which version of the English original the translation is based upon
### (and we can identify translations which need to be updated, when the original changes).
### * Replace "-_" occurences with a double "-" in all translations (XML does not allow
### consecutive "-" characters in comments).
###
### Last synchronized with English master resource on 2012-September-21 for FlightGear 2.9.0
### -->
<PropertyList>
<splash>
<init>Initialisiere</init> <!-- English: "initializing" -->
<loading-aircraft-list>Lade Flugzeugliste</loading-aircraft-list> <!-- English: "loading aircraft list" -->
<loading-aircraft>Lade Flugzeug</loading-aircraft> <!-- English: "loading aircraft" -->
<loading-nav-dat>Lade Navigationsdaten</loading-nav-dat> <!-- English: "loading navigation data" -->
<init-scenery>Initialisiere Szenerie</init-scenery> <!-- English: "initializing scenery" -->
<creating-subsystems>Erzeuge Subsysteme</creating-subsystems> <!-- English: "creating subsystems" -->
<init-subsystems>Initialisiere Subsysteme</init-subsystems> <!-- English: "initializing subsystems" -->
<binding-subsystems>Binde Subsysteme</binding-subsystems> <!-- English: "binding subsystems" -->
<finishing-subsystems>Finalisiere Subsysteme</finishing-subsystems> <!-- English: "finalizing subsystems" -->
<init-graphics>Initialisiere Grafik</init-graphics> <!-- English: "initializing graphics engine" -->
<loading-scenery>Lade Szenerie</loading-scenery> <!-- English: "loading scenery" -->
</splash>
</PropertyList>

View file

@ -27,9 +27,8 @@
<!-- Location menu -->
<location>Location</location>
<position-on-ground>Position Aircraft On Ground</position-on-ground>
<position-in-air>Position Aircraft In Air</position-in-air>
<goto-airport>Select Airport From List</goto-airport>
<goto-airport>Select Airport</goto-airport>
<random-attitude>Random Attitude</random-attitude>
<tower-position>Tower Position</tower-position>
@ -109,7 +108,9 @@
<!-- Help menu -->
<help>Help</help>
<help-browser>Help (opens in browser)</help-browser>
<doc-browser>Documentation Browser</doc-browser>
<aircraft-keys>Aircraft Help</aircraft-keys>
<aircraft-checklists>Aircraft Checklists</aircraft-checklists>
<common-keys>Common Aircraft Keys</common-keys>
<basic-keys>Basic Simulator Keys</basic-keys>
<joystick-config>Joystick Configuration</joystick-config>
@ -117,4 +118,12 @@
<tutorial-start>Tutorials</tutorial-start>
<menu-about>About</menu-about>
<!-- Aircraft menu (only frequent/common custom menu entries are supported) -->
<select-livery>Select livery</select-livery>
<show-hide-yokes>Show/hide yokes</show-hide-yokes>
<immatriculation>Immatriculation</immatriculation>
<pushback>Pushback</pushback>
<autostart>Autostart</autostart>
<tiller-steering>Tiller Steering</tiller-steering>
</PropertyList>

21
Translations/en/sys.xml Normal file
View file

@ -0,0 +1,21 @@
<?xml version="1.0"?>
<!-- FlightGear system messages: English (=default) language resource -->
<PropertyList>
<splash>
<init>initializing</init>
<loading-aircraft-list>loading aircraft list</loading-aircraft-list>
<loading-aircraft>loading aircraft</loading-aircraft>
<loading-nav-dat>loading navigation data</loading-nav-dat>
<init-scenery>initializing scenery</init-scenery>
<creating-subsystems>creating subsystems</creating-subsystems>
<init-subsystems>initializing subsystems</init-subsystems>
<binding-subsystems>binding subsystems</binding-subsystems>
<finishing-subsystems>finalizing subsystems</finishing-subsystems>
<init-graphics>initializing graphics engine</init-graphics>
<loading-scenery>loading scenery</loading-scenery>
</splash>
</PropertyList>

38
Translations/es/sys.xml Normal file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- FlightGear system messages: Spanish language resource -->
<!-- ###
### This file is automatically synchronized with the master (=English language) resource.
### Please do not add comments, change order or restructure the file.
###
### To translate:
### * Replace "???" entries with appropriate translation.
### * Keep untranslated items unmodified (leave the "???"). English original is the
### automatic default.
### * Remove enclosing "<!-_ ... _->" tags for completed translations.
### * Keep the original English text unmodified (the '<!-_ English: "..." -_>)',
### so we know which version of the English original the translation is based upon
### (and we can identify translations which need to be updated, when the original changes).
### * Replace "-_" occurences with a double "-" in all translations (XML does not allow
### consecutive "-" characters in comments).
###
### Last synchronized with English master resource on 2012-September-21 for FlightGear 2.9.0
### -->
<PropertyList>
<splash>
<!-- <init>???</init> --> <!-- English: "initializing" -->
<!-- <loading-aircraft-list>???</loading-aircraft-list> --> <!-- English: "loading aircraft list" -->
<!-- <loading-aircraft>???</loading-aircraft> --> <!-- English: "loading aircraft" -->
<!-- <loading-nav-dat>???</loading-nav-dat> --> <!-- English: "loading navigation data" -->
<!-- <init-scenery>???</init-scenery> --> <!-- English: "initializing scenery" -->
<!-- <creating-subsystems>???</creating-subsystems> --> <!-- English: "creating subsystems" -->
<!-- <init-subsystems>???</init-subsystems> --> <!-- English: "initializing subsystems" -->
<!-- <binding-subsystems>???</binding-subsystems> --> <!-- English: "binding subsystems" -->
<!-- <finishing-subsystems>???</finishing-subsystems> --> <!-- English: "finalizing subsystems" -->
<!-- <init-graphics>???</init-graphics> --> <!-- English: "initializing graphics engine" -->
<!-- <loading-scenery>???</loading-scenery> --> <!-- English: "loading scenery" -->
</splash>
</PropertyList>

38
Translations/fr/sys.xml Normal file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- FlightGear system messages: French language resource -->
<!-- ###
### This file is automatically synchronized with the master (=English language) resource.
### Please do not add comments, change order or restructure the file.
###
### To translate:
### * Replace "???" entries with appropriate translation.
### * Keep untranslated items unmodified (leave the "???"). English original is the
### automatic default.
### * Remove enclosing "<!-_ ... _->" tags for completed translations.
### * Keep the original English text unmodified (the '<!-_ English: "..." -_>)',
### so we know which version of the English original the translation is based upon
### (and we can identify translations which need to be updated, when the original changes).
### * Replace "-_" occurences with a double "-" in all translations (XML does not allow
### consecutive "-" characters in comments).
###
### Last synchronized with English master resource on 2012-September-21 for FlightGear 2.9.0
### -->
<PropertyList>
<splash>
<init>Réinitialiser</init> <!-- English: "initializing" -->
<!-- <loading-aircraft-list>???</loading-aircraft-list> --> <!-- English: "loading aircraft list" -->
<!-- <loading-aircraft>???</loading-aircraft> --> <!-- English: "loading aircraft" -->
<!-- <loading-nav-dat>???</loading-nav-dat> --> <!-- English: "loading navigation data" -->
<!-- <init-scenery>???</init-scenery> --> <!-- English: "initializing scenery" -->
<!-- <creating-subsystems>???</creating-subsystems> --> <!-- English: "creating subsystems" -->
<!-- <init-subsystems>???</init-subsystems> --> <!-- English: "initializing subsystems" -->
<!-- <binding-subsystems>???</binding-subsystems> --> <!-- English: "binding subsystems" -->
<!-- <finishing-subsystems>???</finishing-subsystems> --> <!-- English: "finalizing subsystems" -->
<!-- <init-graphics>???</init-graphics> --> <!-- English: "initializing graphics engine" -->
<!-- <loading-scenery>???</loading-scenery> --> <!-- English: "loading scenery" -->
</splash>
</PropertyList>

38
Translations/it/sys.xml Normal file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- FlightGear system messages: Italian language resource -->
<!-- ###
### This file is automatically synchronized with the master (=English language) resource.
### Please do not add comments, change order or restructure the file.
###
### To translate:
### * Replace "???" entries with appropriate translation.
### * Keep untranslated items unmodified (leave the "???"). English original is the
### automatic default.
### * Remove enclosing "<!-_ ... _->" tags for completed translations.
### * Keep the original English text unmodified (the '<!-_ English: "..." -_>)',
### so we know which version of the English original the translation is based upon
### (and we can identify translations which need to be updated, when the original changes).
### * Replace "-_" occurences with a double "-" in all translations (XML does not allow
### consecutive "-" characters in comments).
###
### Last synchronized with English master resource on 2012-September-21 for FlightGear 2.9.0
### -->
<PropertyList>
<splash>
<!-- <init>???</init> --> <!-- English: "initializing" -->
<!-- <loading-aircraft-list>???</loading-aircraft-list> --> <!-- English: "loading aircraft list" -->
<!-- <loading-aircraft>???</loading-aircraft> --> <!-- English: "loading aircraft" -->
<!-- <loading-nav-dat>???</loading-nav-dat> --> <!-- English: "loading navigation data" -->
<!-- <init-scenery>???</init-scenery> --> <!-- English: "initializing scenery" -->
<!-- <creating-subsystems>???</creating-subsystems> --> <!-- English: "creating subsystems" -->
<!-- <init-subsystems>???</init-subsystems> --> <!-- English: "initializing subsystems" -->
<!-- <binding-subsystems>???</binding-subsystems> --> <!-- English: "binding subsystems" -->
<!-- <finishing-subsystems>???</finishing-subsystems> --> <!-- English: "finalizing subsystems" -->
<!-- <init-graphics>???</init-graphics> --> <!-- English: "initializing graphics engine" -->
<!-- <loading-scenery>???</loading-scenery> --> <!-- English: "loading scenery" -->
</splash>
</PropertyList>

View file

@ -15,6 +15,7 @@
<strings>
<options>Translations/en/options.xml</options>
<menu>Translations/en/menu.xml</menu>
<sys>Translations/en/sys.xml</sys>
</strings>
</locale>
@ -27,6 +28,7 @@
<strings>
<options>Translations/es/options.xml</options>
<menu>Translations/es/menu.xml</menu>
<sys>Translations/es/sys.xml</sys>
</strings>
</locale>
@ -39,6 +41,7 @@
<strings>
<options>Translations/de/options.xml</options>
<menu>Translations/de/menu.xml</menu>
<sys>Translations/de/sys.xml</sys>
</strings>
</locale>
@ -52,6 +55,7 @@
<strings>
<options>Translations/fr/options.xml</options>
<menu>Translations/fr/menu.xml</menu>
<sys>Translations/fr/sys.xml</sys>
</strings>
</locale>
@ -64,6 +68,7 @@
<strings>
<options>Translations/it/options.xml</options>
<menu>Translations/it/menu.xml</menu>
<sys>Translations/it/sys.xml</sys>
</strings>
</locale>
@ -75,6 +80,7 @@
<strings>
<options>Translations/nl/options.xml</options>
<menu>Translations/nl/menu.xml</menu>
<sys>Translations/nl/sys.xml</sys>
</strings>
</locale>
@ -85,6 +91,7 @@
<strings>
<options>Translations/pl/options.xml</options>
<menu>Translations/pl/menu.xml</menu>
<sys>Translations/pl/sys.xml</sys>
</strings>
</locale>
@ -104,6 +111,7 @@
<strings>
<options>Translations/cs/options.xml</options>
<menu>Translations/cs/menu.xml</menu>
<sys>Translations/cs/sys.xml</sys>
</strings>
</locale>
@ -113,6 +121,7 @@
<strings>
<options>Translations/da/options.xml</options>
<menu>Translations/da/menu.xml</menu>
<sys>Translations/da/sys.xml</sys>
</strings>
</locale>

41
Translations/nl/sys.xml Normal file
View file

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- FlightGear system messages: Dutch language resource -->
<!-- ###
### This file is automatically synchronized with the master (=English language) resource.
### Please do not add comments, change order or restructure the file.
###
### To translate:
### * Replace "???" entries with appropriate translation.
### * Keep untranslated items unmodified (leave the "???"). English original is the
### automatic default.
### * Remove enclosing "<!-_ ... _->" tags for completed translations.
### * Keep the original English text unmodified (the '<!-_ English: "..." -_>)',
### so we know which version of the English original the translation is based upon
### (and we can identify translations which need to be updated, when the original changes).
### * Replace "-_" occurences with a double "-" in all translations (XML does not allow
### consecutive "-" characters in comments).
###
### Last synchronized with English master resource on 2012-September-21 for FlightGear 2.9.0
### -->
<PropertyList>
<splash>
<!-- I know, this isn't really Dutch. Just a stub until Gijs has time to work on this new file :). -->
<init>initialisere</init> <!-- English: "initializing" -->
<!-- <loading-aircraft-list>???</loading-aircraft-list> --> <!-- English: "loading aircraft list" -->
<loading-aircraft>vliegtuig laden</loading-aircraft> <!-- English: "loading aircraft" -->
<!-- <loading-nav-dat>???</loading-nav-dat> --> <!-- English: "loading navigation data" -->
<!-- <init-scenery>???</init-scenery> --> <!-- English: "initializing scenery" -->
<!-- <creating-subsystems>???</creating-subsystems> --> <!-- English: "creating subsystems" -->
<init-subsystems>initialisere subsysteme</init-subsystems> <!-- English: "initializing subsystems" -->
<!-- <binding-subsystems>???</binding-subsystems> --> <!-- English: "binding subsystems" -->
<!-- <finishing-subsystems>???</finishing-subsystems> --> <!-- English: "finalizing subsystems" -->
<init-graphics>initialisere grafiek</init-graphics> <!-- English: "initializing graphics engine" -->
<loading-scenery>scenerie laden</loading-scenery> <!-- English: "loading scenery" -->
</splash>
</PropertyList>

38
Translations/pl/sys.xml Normal file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- FlightGear system messages: Polish language resource -->
<!-- ###
### This file is automatically synchronized with the master (=English language) resource.
### Please do not add comments, change order or restructure the file.
###
### To translate:
### * Replace "???" entries with appropriate translation.
### * Keep untranslated items unmodified (leave the "???"). English original is the
### automatic default.
### * Remove enclosing "<!-_ ... _->" tags for completed translations.
### * Keep the original English text unmodified (the '<!-_ English: "..." -_>)',
### so we know which version of the English original the translation is based upon
### (and we can identify translations which need to be updated, when the original changes).
### * Replace "-_" occurences with a double "-" in all translations (XML does not allow
### consecutive "-" characters in comments).
###
### Last synchronized with English master resource on 2012-September-21 for FlightGear 2.9.0
### -->
<PropertyList>
<splash>
<!-- <init>???</init> --> <!-- English: "initializing" -->
<!-- <loading-aircraft-list>???</loading-aircraft-list> --> <!-- English: "loading aircraft list" -->
<!-- <loading-aircraft>???</loading-aircraft> --> <!-- English: "loading aircraft" -->
<!-- <loading-nav-dat>???</loading-nav-dat> --> <!-- English: "loading navigation data" -->
<!-- <init-scenery>???</init-scenery> --> <!-- English: "initializing scenery" -->
<!-- <creating-subsystems>???</creating-subsystems> --> <!-- English: "creating subsystems" -->
<!-- <init-subsystems>???</init-subsystems> --> <!-- English: "initializing subsystems" -->
<!-- <binding-subsystems>???</binding-subsystems> --> <!-- English: "binding subsystems" -->
<!-- <finishing-subsystems>???</finishing-subsystems> --> <!-- English: "finalizing subsystems" -->
<!-- <init-graphics>???</init-graphics> --> <!-- English: "initializing graphics engine" -->
<!-- <loading-scenery>???</loading-scenery> --> <!-- English: "loading scenery" -->
</splash>
</PropertyList>

38
Translations/pt/sys.xml Normal file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- FlightGear system messages: Portuguese language resource -->
<!-- ###
### This file is automatically synchronized with the master (=English language) resource.
### Please do not add comments, change order or restructure the file.
###
### To translate:
### * Replace "???" entries with appropriate translation.
### * Keep untranslated items unmodified (leave the "???"). English original is the
### automatic default.
### * Remove enclosing "<!-_ ... _->" tags for completed translations.
### * Keep the original English text unmodified (the '<!-_ English: "..." -_>)',
### so we know which version of the English original the translation is based upon
### (and we can identify translations which need to be updated, when the original changes).
### * Replace "-_" occurences with a double "-" in all translations (XML does not allow
### consecutive "-" characters in comments).
###
### Last synchronized with English master resource on 2012-September-21 for FlightGear 2.9.0
### -->
<PropertyList>
<splash>
<!-- <init>???</init> --> <!-- English: "initializing" -->
<!-- <loading-aircraft-list>???</loading-aircraft-list> --> <!-- English: "loading aircraft list" -->
<!-- <loading-aircraft>???</loading-aircraft> --> <!-- English: "loading aircraft" -->
<!-- <loading-nav-dat>???</loading-nav-dat> --> <!-- English: "loading navigation data" -->
<!-- <init-scenery>???</init-scenery> --> <!-- English: "initializing scenery" -->
<!-- <creating-subsystems>???</creating-subsystems> --> <!-- English: "creating subsystems" -->
<!-- <init-subsystems>???</init-subsystems> --> <!-- English: "initializing subsystems" -->
<!-- <binding-subsystems>???</binding-subsystems> --> <!-- English: "binding subsystems" -->
<!-- <finishing-subsystems>???</finishing-subsystems> --> <!-- English: "finalizing subsystems" -->
<!-- <init-graphics>???</init-graphics> --> <!-- English: "initializing graphics engine" -->
<!-- <loading-scenery>???</loading-scenery> --> <!-- English: "loading scenery" -->
</splash>
</PropertyList>

View file

@ -113,6 +113,9 @@
<empty>
<stretch>true</stretch>
</empty>
<hrule/>
<text>
<halign>center</halign>
@ -166,7 +169,67 @@
<format>Revision: %s</format>
<property>/sim/version/revision</property>
</text>
</group>
<empty>
<stretch>true</stretch>
</empty>
<hrule/>
<text>
<halign>center</halign>
<label>Graphics/OpenGL Information</label>
</text>
<group>
<layout>vbox</layout>
<border>10</border>
<halign>center</halign>
<default-padding>2</default-padding>
<text>
<halign>left</halign>
<label>MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM</label>
<format>OpenGL Vendor: %s</format>
<property>/sim/rendering/gl-vendor</property>
</text>
<text>
<halign>left</halign>
<label>MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM</label>
<format>OpenGL Renderer: %s</format>
<property>/sim/rendering/gl-renderer</property>
</text>
<text>
<halign>left</halign>
<label>MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM</label>
<format>OpenGL Version: %s</format>
<property>/sim/rendering/gl-version</property>
</text>
<text>
<halign>left</halign>
<label>MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM</label>
<format>GLSL Version: %s</format>
<property>/sim/rendering/gl-shading-language-version</property>
</text>
<text>
<halign>left</halign>
<label>MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM</label>
<format>Max Texture Size: %s</format>
<property>/sim/rendering/max-texture-size</property>
</text>
<text>
<halign>left</halign>
<label>MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM</label>
<format>Depth Buffer Bits: %s</format>
<property>/sim/rendering/depth-buffer-bits</property>
</text>
</group>
</group>
@ -188,6 +251,35 @@
</binding>
</button>
<button>
<legend>Take screen shot</legend>
<equal>true</equal>
<default>false</default>
<binding>
<command>nasal</command>
<script>fgcommand("screen-capture");</script>
</binding>
</button>
<button>
<legend>Copy to Clipboard</legend>
<equal>true</equal>
<default>false</default>
<binding>
<command>nasal</command>
<script><![CDATA[
var properties = ["gl-vendor","gl-version","gl-renderer", "gl-shading-language-version"];
var data = "";
var path = "/sim/rendering/";
foreach(var p; properties)
data ~= p ~":"~getprop(path~p) ~"\n";
clipboard.setText(data);
gui.popupTip("Copied version information to clipboard!");
]]></script>
</binding>
</button>
<empty><stretch>true</stretch></empty>
</group>

View file

@ -24,27 +24,151 @@
<binding>
<command>dialog-close</command>
</binding>
<binding>
<command>property-toggle</command>
<property>/sim/gui/dialogs/airports/signals/dialog-close</property>
</binding>
</button>
</group>
<hrule/>
<nasal>
<open>
var id = "";
var node = props.globals.getNode("/sim/gui/dialogs/airports", 1);
if (node.getNode("list") == nil)
node.getNode("list", 1).setValue("");
<!-- Generalize all this, turn into helpers and load defaults via XML -->
<open><![CDATA[
## "prologue" currently required by the canvas-generic-map
var dialog_name ="airports"; #TODO: use substr() and cmdarg() to get this dynamically
var dialog_property = func(p) return "/sim/gui/dialogs/airports/"~p; #TODO: generalize using cmdarg
var DIALOG_CANVAS = gui.findElementByName(cmdarg(), "airport-selection");
canvas.GenericMap.setupGUI(DIALOG_CANVAS, "canvas-control"); #TODO: this is not a method!
## end of canvas-generic-map prologue
node = node.getNode("list");
setprop("/sim/gui/dialogs/airports/selected-airport/rwy", "");
setprop("/sim/gui/dialogs/airports/selected-airport/parkpos", "");
setprop("/sim/gui/dialogs/airports/mode", "search");
setprop("/sim/gui/dialogs/airports/list", "");
if (getprop("/sim/gui/dialogs/airports/display-taxiways") == "") {
setprop("/sim/gui/dialogs/airports/display-taxiways", "1");
}
if (getprop("/sim/gui/dialogs/airports/display-parking") == "") {
setprop("/sim/gui/dialogs/airports/display-parking", "0");
}
if (getprop("/sim/gui/dialogs/airports/display-tower") == "") {
setprop("/sim/gui/dialogs/airports/display-tower", "1");
}
# Start with the closest airport
var airport_id = airportinfo().id;
# Retrieve METAR
fgcommand("request-metar", var n = props.Node.new({ "path": "/sim/gui/dialogs/airports/selected-airport/metar",
"station": airport_id}));
var dlg = props.globals.getNode("/sim/gui/dialogs/airports", 1);
var avail_runways = dlg.getNode("available-runways", 1);
var avail_parking = dlg.getNode("available-parking", 1);
if (dlg.getNode("list") == nil)
dlg.getNode("list", 1).setValue("");
var airportlist = dlg.getNode("list");
var mode = {
runway: dlg.getNode("use_runway", 1),
bestrunway: dlg.getNode("use_best_runway", 1),
parkpos: dlg.getNode("use_parkpos", 1)
};
var set_radio = func(m) {
foreach (k; keys(mode)) {
mode[k].setBoolValue(m == k);
}
}
var initialized = 0;
foreach (k; keys(mode)) {
if (mode[k].getType() == "NONE" or initialized) {
mode[k].setBoolValue(0);
} else {
initialized += mode[k].getBoolValue();
}
}
if (!initialized) {
set_radio("bestrunway");
}
var update_info = func {
var info = airportinfo(airport_id);
setprop("/sim/gui/dialogs/airports/selected-airport/id", airport_id);
setprop("/sim/gui/dialogs/airports/selected-airport/name", info.name ~ " (" ~ airport_id ~ ")");
setprop("/sim/gui/dialogs/airports/selected-airport/location", sprintf("%.3f / %.3f", info.lat, info.lon));
setprop("/sim/gui/dialogs/airports/selected-airport/lon", info.lon);
setprop("/sim/gui/dialogs/airports/selected-airport/elevation-ft", 3.28 * info.elevation);
setprop("/sim/gui/dialogs/airports/selected-airport/rwy", "");
setprop("/sim/gui/dialogs/airports/selected-airport/parkpos", "");
if (info.has_metar) {
# Retrieve an updated METAR, and indicate that we've not got one currently.
setprop("/sim/gui/dialogs/airports/selected-airport/metar/station-id", airport_id);
setprop("/sim/gui/dialogs/airports/selected-airport/metar/time-to-live", 0);
setprop("/sim/gui/dialogs/airports/selected-airport/metar/data", "Retrieving METAR, please wait.");
} else {
# This airport has no METAR. Ratehr than cancelling the retrieve-metar command, simply set the TTL
# to a very long time so it won't over-ride our message.
setprop("/sim/gui/dialogs/airports/selected-airport/metar/data", "No METAR available from this airport");
setprop("/sim/gui/dialogs/airports/selected-airport/metar/time-to-live", 9999);
}
var longest_runway = 0;
var runway_string = "";
var runways = info.runways;
avail_runways.removeChildren("value");
avail_parking.removeChildren("value");
var runway_keys = sort(keys(runways), string.icmp);
var i = 0;
foreach(var rwy; runway_keys) {
runway_string = runway_string ~ rwy ~ " ";
longest_runway = math.max(longest_runway, runways[rwy].length * 3.28);
avail_runways.getNode("value[" ~ i ~ "]", 1).setValue(rwy);
i += 1;
}
i = 0;
foreach (var park; info.parking()) {
avail_parking.getNode("value[" ~ i ~ "]", 1).setValue(park.name);
i += 1;
}
setprop("/sim/gui/dialogs/airports/selected-airport/longest-runway", longest_runway);
var airport_pos = geo.Coord.new();
airport_pos.set_latlon(info.lat, info.lon);
var pos = geo.aircraft_position();
var dst = pos.distance_to(airport_pos) / 1852.0;
var crs = pos.course_to(airport_pos);
setprop("/sim/gui/dialogs/airports/selected-airport/distance-nm", dst);
setprop("/sim/gui/dialogs/airports/selected-airport/course-deg", crs);
gui.dialog_update("airports", "runway-list");
gui.dialog_update("airports", "parking-list");
}
var listbox = func {
id = pop(split(" ", node.getValue()));
id = substr(id, 1, size(id) - 2); # strip parentheses
airport_id = pop(split(" ", airportlist.getValue()));
airport_id = substr(airport_id, 1, size(airport_id) - 2); # strip parentheses
update_info();
}
var apply = func {
setprop("/sim/presets/airport-id", id);
setprop("/sim/presets/airport-id", airport_id);
setprop("/sim/presets/longitude-deg", -9999);
setprop("/sim/presets/latitude-deg", -9999);
setprop("/sim/presets/altitude-ft", -9999);
@ -53,79 +177,518 @@
setprop("/sim/presets/offset-azimuth-deg", 0);
setprop("/sim/presets/glideslope-deg", 0);
setprop("/sim/presets/heading-deg", 0);
setprop("/sim/presets/runway", "");
setprop("/sim/presets/parkpos", "");
}
if (mode["bestrunway"].getBoolValue()) {
setprop("/sim/presets/runway", "");
setprop("/sim/presets/parkpos", "");
} else if (mode["runway"].getBoolValue()) {
setprop("/sim/presets/runway", getprop("/sim/gui/dialogs/airports/selected-airport/rwy"));
setprop("/sim/presets/parkpos", "");
} else {
setprop("/sim/presets/runway", "");
setprop("/sim/presets/parkpos", getprop("/sim/gui/dialogs/airports/selected-airport/parkpos"));
}
}
update_info();
]]>
</open>
<close>
fgcommand("clear-metar", var n = props.Node.new({ "path": "/sim/gui/dialogs/airports/selected-airport/metar",
"station": airport_id}));
# map.cleanup_listeners(); #TODO: We should be setting a signal when closing the dialog, so that cleanup code can be invoked automatically
</close>
</nasal>
<airport-list>
<name>airport-list</name>
<pref-width>440</pref-width>
<pref-height>360</pref-height>
<halign>fill</halign>
<valign>fill</valign>
<stretch>true</stretch>
<property>/sim/gui/dialogs/airports/list</property>
<binding>
<command>dialog-apply</command>
<object-name>airport-list</object-name>
</binding>
<binding>
<command>nasal</command>
<script>listbox()</script>
</binding>
</airport-list>
<group>
<layout>hbox</layout>
<default-padding>4</default-padding>
<group>
<layout>vbox</layout>
<text>
<label>Airport:</label>
<pref-width>60</pref-width>
</text>
<group>
<layout>hbox</layout>
<default-padding>4</default-padding>
<input>
<name>input</name>
<pref-width>280</pref-width>
<halign>fill</halign>
<stretch>true</stretch>
<property>/sim/gui/dialogs/airports/list</property>
<binding>
<command>dialog-apply</command>
<object-name>input</object-name>
</binding>
<binding>
<command>dialog-update</command>
<object-name>airport-list</object-name>
</binding>
</input>
<text>
<label>Airport:</label>
</text>
<button>
<legend>Search</legend>
<binding>
<command>dialog-apply</command>
<object-name>input</object-name>
</binding>
<binding>
<command>dialog-update</command>
<object-name>airport-list</object-name>
</binding>
</button>
<input>
<name>input</name>
<pref-width>200</pref-width>
<halign>fill</halign>
<stretch>true</stretch>
<property>/sim/gui/dialogs/airports/list</property>
<binding>
<command>dialog-apply</command>
<object-name>input</object-name>
</binding>
<binding>
<command>dialog-update</command>
<object-name>airport-list</object-name>
</binding>
</input>
<button>
<legend>Clear</legend>
<binding>
<command>property-assign</command>
<property>/sim/gui/dialogs/airports/mode</property>
<value>search</value>
</binding>
<binding>
<command>property-assign</command>
<property>/sim/gui/dialogs/airports/list</property>
<value></value>
</binding>
<binding>
<command>dialog-update</command>
<object-name>input</object-name>
</binding>
<binding>
<command>dialog-update</command>
<object-name>airport-list</object-name>
</binding>
</button>
<button>
<legend>Search</legend>
<default>true</default>
<binding>
<command>property-assign</command>
<property>/sim/gui/dialogs/airports/mode</property>
<value>search</value>
</binding>
<binding>
<command>dialog-apply</command>
<object-name>input</object-name>
</binding>
<binding>
<command>dialog-update</command>
<object-name>airport-list</object-name>
</binding>
</button>
<button>
<legend>Within 100nm</legend>
<binding>
<command>property-assign</command>
<property>/sim/gui/dialogs/airports/mode</property>
<value>100nm</value>
</binding>
<binding>
<command>nasal</command>
<script>
var airports = findAirportsWithinRange(100);
var list = dlg.getNode("close-airports", 1);
list.removeChildren("value");
forindex (var idx; airports) {
list.getNode("value["~ idx ~ "]", 1).setValue(airports[idx].name ~ " (" ~ airports[idx].id ~ ")");
}
</script>
</binding>
<binding>
<command>dialog-update</command>
<object-name>close-airport-list</object-name>
</binding>
</button>
</group>
<group>
<layout>table</layout>
<default-padding>0</default-padding>
<list>
<row>0</row><col>0</col>
<visible>
<equals>
<property>/sim/gui/dialogs/airports/mode</property>
<value>100nm</value>
</equals>
</visible>
<name>close-airport-list</name>
<pref-width>300</pref-width>
<pref-height>260</pref-height>
<halign>fill</halign>
<valign>fill</valign>
<stretch>true</stretch>
<property>/sim/gui/dialogs/airports/list</property>
<properties>/sim/gui/dialogs/airports/close-airports</properties>
<binding>
<command>dialog-apply</command>
<object-name>close-airport-list</object-name>
</binding>
<binding>
<command>nasal</command>
<script>listbox()</script>
</binding>
</list>
<airport-list>
<row>0</row><col>0</col>
<visible>
<equals>
<property>/sim/gui/dialogs/airports/mode</property>
<value>search</value>
</equals>
</visible>
<name>airport-list</name>
<pref-width>300</pref-width>
<pref-height>260</pref-height>
<halign>fill</halign>
<valign>fill</valign>
<stretch>true</stretch>
<property>/sim/gui/dialogs/airports/list</property>
<binding>
<command>dialog-apply</command>
<object-name>airport-list</object-name>
</binding>
<binding>
<command>nasal</command>
<script>listbox()</script>
</binding>
</airport-list>
</group>
<hrule/>
<group>
<layout>table</layout>
<text>
<row>0</row>
<col>0</col>
<width>100</width>
<halign>right</halign>
<label>Airport:</label>
</text>
<text>
<row>0</row>
<col>1</col>
<colspan>3</colspan>
<halign>left</halign>
<live>true</live>
<property>/sim/gui/dialogs/airports/selected-airport/name</property>
</text>
<text>
<row>1</row>
<col>0</col>
<halign>right</halign>
<label>Lat / Lon:</label>
</text>
<text>
<row>1</row>
<col>1</col>
<halign>left</halign>
<live>true</live>
<property>/sim/gui/dialogs/airports/selected-airport/location</property>
</text>
<text>
<row>1</row>
<col>2</col>
<halign>right</halign>
<label>Elevation:</label>
</text>
<text>
<row>1</row>
<col>3</col>
<halign>left</halign>
<live>true</live>
<format>%.0f ft</format>
<property>/sim/gui/dialogs/airports/selected-airport/elevation-ft</property>
</text>
<text>
<row>2</row>
<col>0</col>
<halign>right</halign>
<label>Longest runway:</label>
</text>
<text>
<row>2</row>
<col>1</col>
<halign>left</halign>
<live>true</live>
<format>%.0f ft</format>
<property>/sim/gui/dialogs/airports/selected-airport/longest-runway</property>
</text>
<text>
<row>3</row>
<col>0</col>
<halign>right</halign>
<label>Distance:</label>
</text>
<text>
<row>3</row>
<col>1</col>
<halign>left</halign>
<live>true</live>
<format>%.1f nm</format>
<property>/sim/gui/dialogs/airports/selected-airport/distance-nm</property>
</text>
<text>
<row>3</row>
<col>2</col>
<halign>right</halign>
<label>Course:</label>
</text>
<text>
<row>3</row>
<col>3</col>
<halign>left</halign>
<live>true</live>
<format>%.0f deg</format>
<property>/sim/gui/dialogs/airports/selected-airport/course-deg</property>
</text>
<text>
<row>4</row>
<col>0</col>
<colspan>3</colspan>
<halign>left</halign>
<live>true</live>
<label>METAR:</label>
</text>
<textbox>
<name>metar</name>
<row>5</row>
<col>0</col>
<colspan>4</colspan>
<halign>fill</halign>
<stretch>true</stretch>
<pref-width>300</pref-width>
<pref-height>60</pref-height>
<slider>0</slider>
<editable>false</editable>
<wrap>true</wrap>
<live>true</live>
<property>/sim/gui/dialogs/airports/selected-airport/metar/data</property>
</textbox>
</group>
<hrule/>
<group>
<layout>table</layout>
<halign>center</halign>
<radio>
<row>2</row><col>0</col>
<property>/sim/gui/dialogs/airports/use_best_runway</property>
<live>true</live>
<binding>
<command>nasal</command>
<script>set_radio("bestrunway")</script>
</binding>
</radio>
<text>
<row>2</row><col>1</col>
<halign>right</halign>
<label>Best runway</label>
<enable>
<property>/sim/gui/dialogs/airports/use_best_runway</property>
</enable>
</text>
<text>
<row>2</row><col>2</col>
<halign>right</halign>
<label>(based on wind)</label>
<enable>
<property>/sim/gui/dialogs/airports/use_best_runway</property>
</enable>
</text>
<radio>
<row>3</row><col>0</col>
<property>/sim/gui/dialogs/airports/use_runway</property>
<live>true</live>
<binding>
<command>nasal</command>
<script>set_radio("runway")</script>
</binding>
</radio>
<text>
<row>3</row><col>1</col>
<halign>right</halign>
<label>Runway:</label>
<enable>
<property>/sim/gui/dialogs/airports/use_runway</property>
</enable>
</text>
<combo>
<name>runway-list</name>
<row>3</row><col>2</col>
<pref-width>85</pref-width>
<enable>
<property>/sim/gui/dialogs/airports/use_runway</property>
</enable>
<property>/sim/gui/dialogs/airports/selected-airport/rwy</property>
<editable>false</editable>
<properties>sim/gui/dialogs/airports/available-runways</properties>
<binding>
<command>dialog-apply</command>
<object-name>runway-list</object-name>
</binding>
</combo>
<radio>
<row>4</row><col>0</col>
<property>/sim/gui/dialogs/airports/use_parkpos</property>
<live>true</live>
<binding>
<command>nasal</command>
<script>set_radio("parkpos")</script>
</binding>
</radio>
<text>
<row>4</row><col>1</col>
<halign>right</halign>
<label>Parking:</label>
<enable>
<property>/sim/gui/dialogs/airports/use_parkpos</property>
</enable>
</text>
<combo>
<name>parking-list</name>
<row>4</row><col>2</col>
<pref-width>85</pref-width>
<enable>
<property>/sim/gui/dialogs/airports/use_parkpos</property>
</enable>
<property>/sim/gui/dialogs/airports/selected-airport/parkpos</property>
<editable>false</editable>
<properties>sim/gui/dialogs/airports/available-parking</properties>
<binding>
<command>dialog-apply</command>
<object-name>parking-list</object-name>
</binding>
</combo>
</group>
</group>
<vrule/>
<group>
<layout>vbox</layout>
<!-- Instantiate a generic canvas map and parametrize it via inclusion -->
<!-- TODO: use params and aliasing -->
<canvas include="/Nasal/canvas/generic-canvas-map.xml">
<name>airport-selection</name>
<valign>fill</valign>
<halign>fill</halign>
<stretch>true</stretch>
<pref-width>600</pref-width>
<pref-height>400</pref-height>
<view n="0">600</view>
<view n="1">400</view>
<features>
<!-- TODO: use params and aliases to make this shorter -->
<!-- TODO: support styling, i.e. image sets/fonts and colors to be used -->
<!-- this will set up individual "layers" and map them to boolean "toggle" properties -->
<!-- providing an optional "description" tag here allows us to create all checkboxes procedurally -->
<dialog-root>/sim/gui/dialogs/airports</dialog-root>
<range-property>zoom</range-property>
<!-- These are the ranges available for the map: var ranges = [0.1, 0.25, 0.5, 1, 2.5, 5] -->
<ranges>
<range>0.1</range>
<range>0.25</range>
<range>0.5</range>
<range>1</range>
<range>2.5</range>
<range>5</range>
</ranges>
<!-- available layers and their toggle property (appended to dialog-root specified above) -->
<layer>
<name>runways</name> <!-- the name of the layer -->
<init-property>selected-airport/id</init-property> <!-- the init/input property that re-inits the layer MODEL -->
<property>display-runways</property> <!-- the property switch that toggles the layer on/off (show/hide) -->
<description>Show Runways</description> <!-- the checkbox label for the property -->
<default>enabled</default> <!-- default state -->
<hide-checkbox>true</hide-checkbox> <!-- if the checkbox should be shown or hidden -->
</layer>
<layer>
<name>taxiways</name>
<init-property>selected-airport/id</init-property>
<property>display-taxiways</property>
<description>Show Taxiways</description>
<default>disabled</default>
</layer>
<layer>
<name>parkings</name>
<init-property>selected-airport/id</init-property>
<property>display-parking</property>
<description>Show Parking</description>
<default>disabled</default>
</layer>
<layer>
<name>towers</name>
<init-property>selected-airport/id</init-property>
<property>display-tower</property>
<description>Show Tower</description>
<default>enabled</default>
</layer>
<!-- Uncomment this to add a navaid layer (not yet fully implemented, and no LOD yet)
<layer>
<name>navaids</name>
<init-property>selected-airport/id</init-property>
<property>display-navaids</property>
<description>Display Navaids within current range</description>
<default>disabled</default>
</layer>
-->
</features>
</canvas>
<hrule/>
<group>
<name>canvas-control</name> <!-- this is the handle we use to procedurally add all "toggle layer" checkboxes and the zoom control-->
<layout>hbox</layout>
</group>
</group>
</group>
<hrule/>
<group>
<layout>hbox</layout>
<default-padding>10</default-padding>
<empty><stretch>true</stretch></empty>
<button>
<legend>Apply</legend>
<legend>Go To Airport</legend>
<equal>true</equal>
<default>true</default>
<binding>
<command>dialog-apply</command>
<object-name>airport-list</object-name>
@ -137,6 +700,9 @@
<binding>
<command>presets-commit</command>
</binding>
<binding>
<command>dialog-close</command>
</binding>
</button>
<empty><stretch>true</stretch></empty>

186
gui/dialogs/checklist.xml Normal file
View file

@ -0,0 +1,186 @@
<?xml version="1.0"?>
<PropertyList>
<name>checklist</name>
<layout>vbox</layout>
<default-padding>1</default-padding>
<color>
<red type="float">0.41</red>
<green type="float">0.4</green>
<blue type="float">0.42</blue>
<alpha type="float">1.0</alpha>
<alpha type="float">1.0</alpha>
</color>
<nasal>
<open>
var dlgRoot = cmdarg();
var checklists = props.globals.getNode("/sim/checklists", 1).getChildren("checklist");
if (size(checklists) > 0) {
var combo = gui.findElementByName(dlgRoot, "checklist-combo");
var group = gui.findElementByName(dlgRoot, "checklist-table-group");
forindex (var idx; checklists) {
combo.getChild("value", idx, 1).setValue(checklists[idx].getNode("title", 1).getValue());
var c = checklists[idx];
var row = 0;
# Set up a new table, only visible when this checklist is selected.
var table = group.getChild("group", idx, 1);
table.getNode("row", 1).setValue(0);
table.getNode("col", 1).setValue(0);
table.getNode("default-padding", 1).setValue(4);
table.getNode("layout", 1).setValue("table");
table.getNode("valign", 1).setValue("top");
var vis = table.getNode("visible", 1).getNode("equals", 1);
vis.getNode("property", 1).setValue("sim/gui/dialogs/checklist/selected-checklist");
vis.getNode("value", 1).setValue(c.getNode("title").getValue());
var items = c.getChildren("item");
var txtcount = 0;
forindex (var i; items) {
var item = items[i];
var t = table.getChild("text", txtcount, 1);
txtcount += 1;
t.getNode("halign", 1).setValue("left");
t.getNode("row", 1).setValue(row);
t.getNode("col", 1).setValue(0);
t.getNode("label", 1).setValue(item.getNode("name", 1).getValue());
var values = item.getChildren("value");
forindex (var v; values) {
var t = table.getChild("text", txtcount, 1);
txtcount += 1;
t.getNode("halign", 1).setValue("right");
t.getNode("row", 1).setValue(row);
if (v > 0) {
# The second row of values can overlap with the
# first column if required - helps keep the
# checklist dialog as compact as possible
t.getNode("col", 1).setValue(0);
t.getNode("colspan", 1).setValue(2);
} else {
t.getNode("col", 1).setValue(1);
}
t.getNode("label", 1).setValue(values[v].getValue());
row = row + 1;
}
}
}
setprop("sim/gui/dialogs/checklist/selected-checklist",
checklists[0].getNode("title").getValue());
} else {
var group = gui.findElementByName(dlgRoot, "checklist-table-group");
var table = group.getNode("text", 1);
table.getNode("row", 1).setValue(0);
table.getNode("col", 1).setValue(0);
table.getNode("default-padding", 1).setValue(4);
table.getNode("layout", 1).setValue("table");
table.getNode("valign", 1).setValue("top");
table.getNode("halign", 1).setValue("center");
table.getNode("label", 1).setValue("No checklists exist for this aircraft");
}
var setTransparency = func(updateDialog){
var alpha = (getprop("/sim/gui/dialogs/checklist/transparent") or 0);
dlgRoot.getNode("color/alpha").setValue(1-alpha*0.3);
dlgRoot.getNode("color/red").setValue(0.41-alpha*0.2);
dlgRoot.getNode("color/green").setValue(0.4-alpha*0.2);
dlgRoot.getNode("color/blue").setValue(0.42-alpha*0.2);
var n = props.Node.new({ "dialog-name": "checklist" });
if (updateDialog)
{
fgcommand("dialog-close", n);
fgcommand("dialog-show", n);
}
}
setTransparency(0);
</open>
</nasal>
<group>
<layout>hbox</layout>
<empty><stretch>1</stretch></empty>
<text>
<label>Aircraft Checklists</label>
</text>
<empty><stretch>1</stretch></empty>
<button>
<pref-width>16</pref-width>
<pref-height>16</pref-height>
<legend></legend>
<keynum>27</keynum>
<border>2</border>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
<hrule/>
<group>
<layout>hbox</layout>
<text>
<halign>right</halign>
<label>Checklist:</label>
</text>
<combo>
<name>checklist-combo</name>
<property>/sim/gui/dialogs/checklist/selected-checklist</property>
<editable>false</editable>
<pref-width>200</pref-width>
<halign>fill</halign>
<binding>
<command>dialog-apply</command>
<object-name>checklist-combo</object-name>
</binding>
</combo>
<empty><stretch>true</stretch></empty>
<checkbox>
<label>Transparent</label>
<pref-width>100</pref-width>
<property>/sim/gui/dialogs/checklist/transparent</property>
<live>true</live>
<halign>right</halign>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>property-toggle</command>
</binding>
<binding>
<command>nasal</command>
<script>setTransparency(1);</script>
</binding>
</checkbox>
</group>
<hrule/>
<group>
<default-padding>4</default-padding>
<halign>fill</halign>
<layout>table</layout>
<name>checklist-table-group</name>
</group>
</PropertyList>

140
gui/dialogs/doc-browser.xml Normal file
View file

@ -0,0 +1,140 @@
<?xml version="1.0"?>
<PropertyList>
<x>-20</x>
<y>-20</y>
<name>doc-browser</name>
<dialog-name>doc-browser</dialog-name>
<layout>vbox</layout>
<resizable>true</resizable>
<group>
<layout>hbox</layout>
<empty>
<stretch>1</stretch>
</empty>
<text>
<label>Documentation Browser</label>
</text>
<empty>
<stretch>1</stretch>
</empty>
<button>
<pref-width>16</pref-width>
<pref-height>16</pref-height>
<legend/>
<keynum>27</keynum>
<border>2</border>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
<hrule/>
<group>
<layout>hbox</layout>
<list>
<pref-width>170</pref-width>
<pref-height>500</pref-height>
<name>filename</name>
<halign>fill</halign>
<property>/sim/gui/dialogs/doc-browser/filename</property>
<value>clear</value>
<binding>
<command>dialog-apply</command>
<object-name>filename</object-name>
</binding>
<binding>
<command>dialog-update</command>
<object-name>editfield</object-name>
</binding>
</list>
<textbox>
<name>editfield</name>
<halign>fill</halign>
<valign>fill</valign>
<stretch>true</stretch>
<pref-width>600</pref-width>
<pref-height>250</pref-height>
<padding>6</padding>
<slider>20</slider>
<editable>falsee</editable>
<wrap>false</wrap>
<font>
<name>FIXED_8x13</name>
</font>
<property>/sim/gui/dialogs/doc-browser/edit</property>
</textbox>
</group>
<nasal>
<open>
var self = cmdarg();
var dlg = props.globals.getNode("/sim/gui/dialogs/doc-browser", 1);
var edit = dlg.getNode("edit", 1);
if( !contains(globals, "__doc_browser") )
globals["__doc_browser"] = {};
var path = getprop("/sim/fg-root") ~ "/Docs/";
# hard coded list of file names, because not all files are plain text - not even the README* files
# TODO: it would probably make sense to sort these files (README, introduction, properties etc)
var doc_files = [
"README",
"README.introduction",
"README.fgjs",
"README.xmlsyntax",
"README.multiscreen",
"README.properties",
"README.IO",
"README.logging",
"README.protocol",
"README.scenery",
"README.materials",
"README.yasim",
"README.JSBsim",
"README.submodels",
"README.3DClouds",
"README.flightrecorder",
"README.jsclient",
"README.multiplayer",
"README.tutorials",
"README.conditions",
"README.commands",
"README.digitalfilters",
"README.airspeed-indicator",
"README.hud",
# "README.xmlhud", deprecated?
"README.gui",
"README.layout",
"README.osgtext",
"README.wildfire",
"README.electrical",
"README.effects",
"README.xmlparticles",
"README.sound",
"README.xmlsound",
"README.xmlpanel",
"README.minipanel"
];
var filename_list = self.getNode("group[1]/list");
var n=0;
# add the filenames to the list box
foreach(var file; doc_files)
{
filename_list.getChild("value",n,1).setValue( file );
n+=1;
}
var filename_property = "/sim/gui/dialogs/doc-browser/filename";
var update = func {
var file = getprop(filename_property);
var doc_file = path ~ file;
setprop("/sim/gui/dialogs/doc-browser/edit", io.readfile(doc_file));
}
var listener = setlistener(filename_property, update);
setprop("/sim/gui/dialogs/doc-browser/filename", "README.introduction");
</open>
<close>removelistener(listener);</close>
</nasal>
</PropertyList>

View file

@ -17,7 +17,7 @@
</empty>
<text>
<label>Environmental Settings</label>
<label>Environment Settings</label>
</text>
<empty>
@ -226,23 +226,6 @@
</empty>
<layout>hbox</layout>
<button>
<legend>OK</legend>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>dialog-close</command>
</binding>
</button>
<button>
<legend>Apply</legend>
<binding>
<command>dialog-apply</command>
</binding>
</button>
<button>
<legend>Close</legend>
<default>true</default>

View file

@ -0,0 +1,744 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="50"
height="50"
id="svg2"
sodipodi:version="0.32"
inkscape:version="0.45.1"
sodipodi:docbase="C:\Documents and Settings\JJB\My Documents"
sodipodi:docname="NDB Symbol.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.0">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="3.1"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4"
inkscape:cx="71.027314"
inkscape:cy="17.078887"
inkscape:document-units="px"
inkscape:current-layer="g3816"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1404"
inkscape:window-height="874"
inkscape:window-x="28"
inkscape:window-y="0"
width="50px"
height="50px"
showgrid="false"
inkscape:grid-points="true"
gridspacingx="5px"
gridspacingy="5px"
inkscape:guide-points="false" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
id="g2842"
transform="matrix(0.9655323,-0.2602834,0.2602834,0.9655323,-98.55675,-17.522102)"
inkscape:transform-center-y="-186.61497"
inkscape:transform-center-x="50.854555" />
<g
id="g4183"
transform="translate(6.3118628,-54.869792)">
<g
transform="translate(-56.311844,-45.130208)"
id="g3816">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:3;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3586"
sodipodi:cx="75"
sodipodi:cy="125"
sodipodi:rx="5"
sodipodi:ry="5"
d="M 80 125 A 5 5 0 1 1 70,125 A 5 5 0 1 1 80 125 z" />
<path
sodipodi:type="arc"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3588"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,98.125)" />
<g
id="g3652">
<path
transform="matrix(0.25,0,0,0.25,63.125,88.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3648"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,108.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3650"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3656"
transform="matrix(0.8660254,-0.5,0.5,0.8660254,-52.451905,54.246825)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3658"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,88.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3660"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,108.125)" />
</g>
<g
transform="matrix(0.5,-0.8660254,0.8660254,0.5,-70.753175,127.45191)"
id="g3662">
<path
transform="matrix(0.25,0,0,0.25,63.125,88.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3664"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,108.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3666"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3668"
transform="matrix(0,-1,1,0,-50,200)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3670"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,88.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3672"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,108.125)" />
</g>
<g
transform="matrix(-0.5,-0.8660254,0.8660254,-0.5,4.2468245,252.45191)"
id="g3674">
<path
transform="matrix(0.25,0,0,0.25,63.125,88.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3676"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,108.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3678"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3680"
transform="matrix(-0.8660254,-0.5,0.5,-0.8660254,77.451905,270.75318)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3682"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,88.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3684"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,108.125)" />
</g>
<g
id="g3690"
transform="matrix(0.9063078,-0.4226182,0.4226182,0.9063078,-45.800367,43.407896)">
<path
transform="matrix(0.25,0,0,0.25,63.125,83.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3686"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,113.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3688"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
transform="matrix(0.7071067,-0.7071068,0.7071068,0.7071067,-66.421357,89.644658)"
id="g3694">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3696"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,83.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3698"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,113.125)" />
</g>
<g
id="g3700"
transform="matrix(0.4226183,-0.9063078,0.9063078,0.4226183,-69.984843,140.1458)">
<path
transform="matrix(0.25,0,0,0.25,63.125,83.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3702"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,113.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3704"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
transform="matrix(8.715577e-2,-0.9961946,0.9961946,8.715577e-2,-56.061019,188.82012)"
id="g3706">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3708"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,83.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3710"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,113.125)" />
</g>
<g
id="g3712"
transform="matrix(-0.258819,-0.9659258,0.9659258,-0.258819,-26.329304,229.7968)">
<path
transform="matrix(0.25,0,0,0.25,63.125,83.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3714"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,113.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3716"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
transform="matrix(-0.5735763,-0.819152,0.819152,-0.5735763,15.624218,258.13344)"
id="g3718">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3720"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,83.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3722"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,113.125)" />
</g>
<g
id="g3724"
transform="matrix(-0.8191519,-0.5735764,0.5735764,-0.8191519,64.739336,270.41222)">
<path
transform="matrix(0.25,0,0,0.25,63.125,83.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3726"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,113.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3728"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
transform="matrix(-0.9659257,-0.2588191,0.2588191,-0.9659257,115.09204,265.15215)"
id="g3730">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3732"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,83.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3734"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,113.125)" />
</g>
<g
id="g3736"
transform="matrix(-0.9961946,8.715564e-2,-8.715564e-2,-0.9961946,160.60905,242.98766)">
<path
transform="matrix(0.25,0,0,0.25,63.125,83.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3738"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,113.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3740"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3746">
<path
transform="matrix(0.25,0,0,0.25,63.125,118.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3742"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,78.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3744"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3750"
transform="matrix(0.9659258,-0.258819,0.258819,0.9659258,-29.796818,23.6707)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3752"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,118.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3754"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,78.125)" />
</g>
<g
transform="matrix(0.8660254,-0.4999999,0.4999999,0.8660254,-52.451906,54.246822)"
id="g3756">
<path
transform="matrix(0.25,0,0,0.25,63.125,118.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3758"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,78.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3760"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3762"
transform="matrix(0.7071068,-0.7071067,0.7071067,0.7071068,-66.421359,89.644655)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3764"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,118.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3766"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,78.125)" />
</g>
<g
transform="matrix(0.5,-0.8660253,0.8660253,0.5,-70.753181,127.4519)"
id="g3768">
<path
transform="matrix(0.25,0,0,0.25,63.125,118.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3770"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,78.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3772"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3774"
transform="matrix(0.2588191,-0.9659257,0.9659257,0.2588191,-65.152165,165.09205)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3776"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,118.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3778"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,78.125)" />
</g>
<g
transform="matrix(8.5712909e-8,-0.9999999,0.9999999,8.5712909e-8,-50.000013,199.99999)"
id="g3780">
<path
transform="matrix(0.25,0,0,0.25,63.125,118.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3782"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,78.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3784"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3786"
transform="matrix(-0.2588189,-0.9659258,0.9659258,-0.2588189,-26.329318,229.79681)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3788"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,118.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3790"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,78.125)" />
</g>
<g
transform="matrix(-0.4999999,-0.8660254,0.8660254,-0.4999999,4.2468015,252.4519)"
id="g3792">
<path
transform="matrix(0.25,0,0,0.25,63.125,118.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3794"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,78.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3796"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3798"
transform="matrix(-0.7071067,-0.7071068,0.7071068,-0.7071067,39.644635,266.42135)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3800"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,118.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3802"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,78.125)" />
</g>
<g
transform="matrix(-0.8660253,-0.5,0.5,-0.8660253,77.451877,270.75317)"
id="g3804">
<path
transform="matrix(0.25,0,0,0.25,63.125,118.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3806"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,78.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3808"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3810"
transform="matrix(-0.9659257,-0.2588191,0.2588191,-0.9659257,115.09202,265.15215)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3812"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,118.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3814"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,78.125)" />
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 35 KiB

View file

@ -1,303 +0,0 @@
<?xml version="1.0"?>
<PropertyList>
<name>location-on-ground</name>
<layout>vbox</layout>
<group>
<layout>hbox</layout>
<empty><stretch>1</stretch></empty>
<text>
<label>Position Aircraft On Ground</label>
</text>
<empty><stretch>1</stretch></empty>
<button>
<pref-width>16</pref-width>
<pref-height>16</pref-height>
<legend></legend>
<keynum>27</keynum>
<border>2</border>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
<hrule/>
<nasal>
<open>
var dlg = props.globals.getNode("/sim/gui/dialogs/location-on-ground", 1);
var apt = dlg.getNode("airport", 1);
var aptname = dlg.getNode("airport-name", 1);
apt.setValue(getprop("/sim/presets/airport-id"));
var rwy = dlg.getNode("runway", 1);
rwy.setValue("");
var parkpos = dlg.getNode("parkpos", 1);
parkpos.setValue("");
var mode = {
runway: dlg.getNode("use_runway", 1),
bestrunway: dlg.getNode("use_best_runway", 1),
parkpos: dlg.getNode("use_parkpos", 1)
};
var set_radio = func(m) {
foreach (k; keys(mode)) {
mode[k].setBoolValue(m == k);
}
}
var initialized = 0;
foreach (k; keys(mode)) {
if (mode[k].getType() == "NONE" or initialized) {
mode[k].setBoolValue(0);
} else {
initialized += mode[k].getBoolValue();
}
}
if (!initialized) {
set_radio("bestrunway");
}
var runways = dlg.getNode("available-runways", 1);
var parking = dlg.getNode("available-parking", 1);
var updateAirport = func {
var icao = apt.getValue();
runways.removeChildren("value");
parking.removeChildren("value");
var a = airportinfo(icao);
if (a == nil) {
aptname.setValue("");
return;
}
aptname.setValue(a.name);
var i=0;
foreach (var rwy; keys(a.runways)) {
runways.getNode("value[" ~ i ~ "]", 1).setValue(rwy);
i += 1;
}
i = 0;
foreach (var park; a.parking()) {
parking.getNode("value[" ~ i ~ "]", 1).setValue(park.name);
i += 1;
}
gui.dialog_update("location-on-ground");
}
updateAirport();
</open>
</nasal>
<group>
<layout>table</layout>
<halign>center</halign>
<text>
<row>0</row><col>1</col>
<halign>right</halign>
<label>Airport:</label>
</text>
<input>
<row>0</row><col>2</col>
<live>true</live>
<property>/sim/gui/dialogs/location-on-ground/airport</property>
<binding>
<command>dialog-apply</command>
</binding>
<binding>
<command>nasal</command>
<script>
updateAirport();
</script>
</binding>
</input>
<text>
<row>1</row>
<col>1</col>
<format>%s</format>
<property>/sim/gui/dialogs/location-on-ground/airport-name</property>
<live>true</live>
<stretch>true</stretch>
<halign>fill</halign>
</text>
<radio>
<row>2</row><col>0</col>
<property>/sim/gui/dialogs/location-on-ground/use_best_runway</property>
<live>true</live>
<binding>
<command>nasal</command>
<script>set_radio("bestrunway")</script>
</binding>
</radio>
<text>
<row>2</row><col>1</col>
<halign>right</halign>
<label>Best runway</label>
<enable>
<property>/sim/gui/dialogs/location-on-ground/use_best_runway</property>
</enable>
</text>
<text>
<row>2</row><col>2</col>
<halign>right</halign>
<label>(based on wind)</label>
<enable>
<property>/sim/gui/dialogs/location-on-ground/use_best_runway</property>
</enable>
</text>
<radio>
<row>3</row><col>0</col>
<property>/sim/gui/dialogs/location-on-ground/use_runway</property>
<live>true</live>
<binding>
<command>nasal</command>
<script>set_radio("runway")</script>
</binding>
</radio>
<text>
<row>3</row><col>1</col>
<halign>right</halign>
<label>Runway:</label>
<enable>
<property>/sim/gui/dialogs/location-on-ground/use_runway</property>
</enable>
</text>
<combo>
<name>runway</name>
<row>3</row><col>2</col>
<pref-width>85</pref-width>
<enable>
<property>/sim/gui/dialogs/location-on-ground/use_runway</property>
</enable>
<property>sim/gui/dialogs/location-on-ground/runway</property>
<editable>false</editable>
<properties>sim/gui/dialogs/location-on-ground/available-runways</properties>
<binding>
<command>dialog-apply</command>
<object-name>runway</object-name>
</binding>
</combo>
<radio>
<row>4</row><col>0</col>
<property>/sim/gui/dialogs/location-on-ground/use_parkpos</property>
<live>true</live>
<binding>
<command>nasal</command>
<script>set_radio("parkpos")</script>
</binding>
</radio>
<text>
<row>4</row><col>1</col>
<halign>right</halign>
<label>Parking:</label>
<enable>
<property>/sim/gui/dialogs/location-on-ground/use_parkpos</property>
</enable>
</text>
<combo>
<name>parking</name>
<row>4</row><col>2</col>
<pref-width>85</pref-width>
<enable>
<property>/sim/gui/dialogs/location-on-ground/use_parkpos</property>
</enable>
<property>/sim/gui/dialogs/location-on-ground/parkpos</property>
<editable>false</editable>
<properties>sim/gui/dialogs/location-on-ground/available-parking</properties>
<binding>
<command>dialog-apply</command>
<object-name>parking</object-name>
</binding>
</combo>
</group>
<hrule/>
<group>
<layout>hbox</layout>
<default-padding>10</default-padding>
<empty><stretch>true</stretch></empty>
<button>
<legend>OK</legend>
<default>true</default>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
</binding>
<enable>
<not>
<and>
<property>/sim/gui/dialogs/location-on-ground/use_runway</property>
<equals>
<property>/sim/gui/dialogs/location-on-ground/runway</property>
<value></value>
</equals>
</and>
</not>
</enable>
<binding>
<command>nasal</command>
<script>
setprop("/sim/presets/airport-id", apt.getValue());
if (mode["bestrunway"].getBoolValue()) {
setprop("/sim/presets/runway", "");
setprop("/sim/presets/parkpos", "");
} else if (mode["runway"].getBoolValue()) {
setprop("/sim/presets/runway", rwy.getValue());
setprop("/sim/presets/parkpos", "");
} else {
setprop("/sim/presets/runway", "");
setprop("/sim/presets/parkpos", parkpos.getValue());
}
setprop("/sim/presets/longitude-deg", -9999);
setprop("/sim/presets/latitude-deg", -9999);
setprop("/sim/presets/altitude-ft", -9999);
setprop("/sim/presets/airspeed-kt", 0);
setprop("/sim/presets/offset-distance-nm", 0);
setprop("/sim/presets/offset-azimuth-nm", 0);
setprop("/sim/presets/glideslope-deg", 0);
setprop("/sim/presets/heading-deg", 9999);
</script>
</binding>
<binding>
<command>presets-commit</command>
</binding>
<binding>
<command>dialog-close</command>
</binding>
</button>
<empty><stretch>true</stretch></empty>
<button>
<legend>Cancel</legend>
<equal>true</equal>
<key>Esc</key>
<binding>
<command>dialog-close</command>
</binding>
</button>
<empty><stretch>true</stretch></empty>
</group>
</PropertyList>

View file

@ -111,8 +111,39 @@
<empty><stretch>1</stretch></empty>
<button>
<legend>Clear</legend>
<legend>Copy to Clipboard</legend>
<key>Ctrl-c</key>
<key-desc>Copy buffer contents to clipboard</key-desc>
<equal>true</equal>
<binding>
<command>nasal</command>
<script>active and copy()</script>
</binding>
<binding>
<command>dialog-update</command>
<object-name>editfield</object-name>
</binding>
</button>
<button>
<legend>Paste from Clipboard</legend>
<key>Ctrl-v</key>
<key-desc>Paste clipboard contents into active buffer</key-desc>
<equal>true</equal>
<binding>
<command>nasal</command>
<script>active and paste()</script>
</binding>
<binding>
<command>dialog-update</command>
<object-name>editfield</object-name>
</binding>
</button>
<button>
<legend>Clear</legend>
<key>Ctrl-x</key>
<key-desc>Clear buffer</key-desc>
<equal>true</equal>
<binding>
<command>nasal</command>
@ -127,6 +158,7 @@
<button>
<legend>Dump</legend>
<key>Ctrl-d</key>
<key-desc>Dump buffer contents to console</key-desc>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
@ -181,6 +213,17 @@
select(active);
}
var copy = func {
gui.dialog_apply("nasal-console", "editfield");
select(active);
clipboard.setText( edit.getValue() );
}
var paste = func {
edit.setValue( clipboard.getText() );
select(active);
}
var execute = func(what = nil) {
var num = what != nil ? what.getIndex() : active;
var tag = "&lt;nasal-console/#" ~ num ~ ">";
@ -216,6 +259,21 @@
dlg.getNode("active").setIntValue(active = which);
edit.setValue(dlg.getChild("code", active).getValue());
}
var get_button_desc = func (b) {
var sep = " ... ";
var key=b.getChild("key");
var desc=b.getChild("key-desc");
if( !isa(key, props.Node) or !isa(desc, props.Node) )
return "";
return " "~key.getValue() ~sep~desc.getValue() ~"\n";
}
var key_bindings = (func {
var desc = "";
var buttons = self.getNode("group[2]").getChildren("button");
foreach(var b; buttons) desc ~= get_button_desc(b);
return desc;
})();
var help = func {
active = 0;
@ -225,8 +283,7 @@
edit.setValue("Keys:\n"
~ " tab ... leave edit mode (visible text cursor)\n"
~ " return ... execute active code\n"
~ " ctrl-c ... clear input field\n"
~ " ctrl-d ... dump input field contents to terminal\n"
~ key_bindings
~ " esc ... close dialog\n\n"
~ "Ctrl-click on tab buttons executes code without\n"
~ "switching to the tab. Add more &lt;code> properties\n"

View file

@ -38,7 +38,9 @@ command interface /autopilot/route-manager/input:
}
var clear = func {
#cmd.setValue("@clear");
# deactive first, see http://https://code.google.com/p/flightgear-bugs/issues/detail?id=885
fgcommand("activate-flightplan", props.Node.new({"activate": 0}));
flightplan().cleanPlan();
selection.setIntValue(-1);
}
@ -60,13 +62,10 @@ command interface /autopilot/route-manager/input:
}
var remove = func {
#cmd.setValue("@delete" ~ sel_index());
flightplan().deleteWP(sel_index());
}
var route = func {
#cmd.setValue("@route" ~ sel_index());
var route = func {
var fp = flightplan();
var from = fp.getWP(sel_index() - 1);
var to = fp.getWP(sel_index());
@ -81,7 +80,6 @@ command interface /autopilot/route-manager/input:
}
var jump_to = func {
#cmd.setValue("@jump" ~ sel_index());
flightplan().current = sel_index();
}
@ -101,7 +99,7 @@ command interface /autopilot/route-manager/input:
var save_selector = gui.FileSelector.new(save_route, "Save flight-plan", "Save");
var activate_fp = func {
cmd.setValue("@activate");
fgcommand("activate-flightplan", props.Node.new({"activate": 1}));
}
var departureRunways = dlg.getNode("departure-runways", 1);

View file

@ -356,6 +356,7 @@
if (cmp(current, new) != 0) {
setprop("sim/sound/devices/name", new);
setprop("sim/sound/device-name", new);
fgcommand("reinit", props.Node.new({ "subsystem" : "sound" }));
}
}

View file

@ -64,6 +64,7 @@
<command>dialog-show</command>
<dialog-name>sound-dialog</dialog-name>
</binding>
<enabled>false</enabled>
</item>
<item>
@ -172,14 +173,6 @@
<menu>
<name>location</name>
<item>
<name>position-on-ground</name>
<binding>
<command>dialog-show</command>
<dialog-name>location-on-ground</dialog-name>
</binding>
</item>
<item>
<name>position-in-air</name>
<binding>
@ -711,6 +704,14 @@
</binding>
</item>
<item>
<name>doc-browser</name>
<binding>
<command>dialog-show</command>
<dialog-name>doc-browser</dialog-name>
</binding>
</item>
<item>
<key>?</key>
<name>aircraft-keys</name>
@ -719,6 +720,14 @@
<script>gui.showHelpDialog("/sim/help")</script>
</binding>
</item>
<item>
<name>aircraft-checklists</name>
<binding>
<command>dialog-show</command>
<dialog-name>checklist</dialog-name>
</binding>
</item>
<item>
<name>common-keys</name>