Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bcd7d3cca8 | ||
|
|
6cd64a486a | ||
|
|
93a0d6f46d | ||
|
|
f4356c079f | ||
|
|
9ed54d98b6 | ||
|
|
b12e139b2c | ||
|
|
b1403b3066 | ||
|
|
3376a6f35d | ||
|
|
1d22597d3f | ||
|
|
467336590b |
+11
-3
@@ -1,15 +1,23 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
|
## v.1.6.0
|
||||||
|
|
||||||
|
- Add sound support from internal and external view for C-74 aircraft (thanks to wlbragg)
|
||||||
|
|
||||||
|
## v.1.5.0
|
||||||
|
|
||||||
|
- Add Towrope Configuration dialog
|
||||||
|
|
||||||
## v.1.4.1
|
## v.1.4.1
|
||||||
|
|
||||||
- Fix carsh by missing parameter
|
- Fix crash by missing parameter
|
||||||
|
|
||||||
## v.1.4.0
|
## v.1.4.0
|
||||||
|
|
||||||
- Add Douglas C-47 as a tow plane
|
- Add Douglas C-47 as a tow plane (thanks to wlbragg)
|
||||||
- Add possibility to take off in the bush
|
- Add possibility to take off in the bush
|
||||||
- Add a separate engine sound for the DR400
|
- Add a separate engine sound for the DR400
|
||||||
- Add French translation of meta data
|
- Add French translation of meta data (thanks to Florent)
|
||||||
- Add possibility to save/load route waypoints with description
|
- Add possibility to save/load route waypoints with description
|
||||||
|
|
||||||
## v.1.3.0
|
## v.1.3.0
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -2,11 +2,39 @@
|
|||||||
<PropertyList>
|
<PropertyList>
|
||||||
<fx>
|
<fx>
|
||||||
<engine>
|
<engine>
|
||||||
<name>engine</name>
|
<name>engineINT</name>
|
||||||
|
<mode>looped</mode>
|
||||||
|
<path>Croisiere_int_2.wav</path>
|
||||||
|
<condition>
|
||||||
|
<and>
|
||||||
|
<property>/addons/by-id/org.flightgear.addons.Aerotow/addon-devel/sound/enable</property>
|
||||||
|
<property>/sim/current-view/internal</property>
|
||||||
|
</and>
|
||||||
|
</condition>
|
||||||
|
<volume>
|
||||||
|
<offset>-0.80</offset>
|
||||||
|
</volume>
|
||||||
|
<pitch>
|
||||||
|
<property>velocities/true-airspeed-kt</property>
|
||||||
|
<factor>0.012</factor>
|
||||||
|
<offset>0.3</offset>
|
||||||
|
<min>0.3</min>
|
||||||
|
<max>1.0</max>
|
||||||
|
</pitch>
|
||||||
|
<reference-dist>150.0</reference-dist>
|
||||||
|
<max-dist>5000.0</max-dist>
|
||||||
|
</engine>
|
||||||
|
<engine>
|
||||||
|
<name>engineEXT</name>
|
||||||
<mode>looped</mode>
|
<mode>looped</mode>
|
||||||
<path>Croisiere_ext_2.wav</path>
|
<path>Croisiere_ext_2.wav</path>
|
||||||
<condition>
|
<condition>
|
||||||
<property>/addons/by-id/org.flightgear.addons.Aerotow/addon-devel/sound/enable</property>
|
<and>
|
||||||
|
<property>/addons/by-id/org.flightgear.addons.Aerotow/addon-devel/sound/enable</property>
|
||||||
|
<not>
|
||||||
|
<property>/sim/current-view/internal</property>
|
||||||
|
</not>
|
||||||
|
</and>
|
||||||
</condition>
|
</condition>
|
||||||
<volume>
|
<volume>
|
||||||
<offset>-0.80</offset>
|
<offset>-0.80</offset>
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ var main = func(addon) {
|
|||||||
#
|
#
|
||||||
var loadExtraNasalFiles = func (addon) {
|
var loadExtraNasalFiles = func (addon) {
|
||||||
var modules = [
|
var modules = [
|
||||||
|
"nasal/timer",
|
||||||
"nasal/aircraft",
|
"nasal/aircraft",
|
||||||
"nasal/message",
|
"nasal/message",
|
||||||
"nasal/dialogs/route",
|
"nasal/dialogs/route",
|
||||||
|
|||||||
@@ -36,6 +36,13 @@
|
|||||||
<dialog-name>route-aerotow</dialog-name>
|
<dialog-name>route-aerotow</dialog-name>
|
||||||
</binding>
|
</binding>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<label>Towrope Configuration</label>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-show</command>
|
||||||
|
<dialog-name>towrope-config</dialog-name>
|
||||||
|
</binding>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<label>Call for Piper J3 Cub aircraft</label>
|
<label>Call for Piper J3 Cub aircraft</label>
|
||||||
<binding>
|
<binding>
|
||||||
@@ -79,11 +86,9 @@
|
|||||||
<command>nasal</command>
|
<command>nasal</command>
|
||||||
<script><![CDATA[
|
<script><![CDATA[
|
||||||
# Run stopAerotow() with a delay to ensure that the engine sound turns off
|
# Run stopAerotow() with a delay to ensure that the engine sound turns off
|
||||||
var timer = maketimer(1, func () {
|
aerotow.Timer.new().singleShot(1, aerotow.g_Aerotow, func () {
|
||||||
aerotow.g_Aerotow.stopAerotow();
|
aerotow.g_Aerotow.stopAerotow();
|
||||||
});
|
});
|
||||||
timer.singleShot = 1;
|
|
||||||
timer.start();
|
|
||||||
]]></script>
|
]]></script>
|
||||||
</binding>
|
</binding>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@
|
|||||||
<addon>
|
<addon>
|
||||||
<identifier type="string">org.flightgear.addons.Aerotow</identifier>
|
<identifier type="string">org.flightgear.addons.Aerotow</identifier>
|
||||||
<name type="string">Aerotow Everywhere</name>
|
<name type="string">Aerotow Everywhere</name>
|
||||||
<version type="string">1.4.1</version>
|
<version type="string">1.6.0</version>
|
||||||
|
|
||||||
<authors>
|
<authors>
|
||||||
<author>
|
<author>
|
||||||
|
|||||||
+10
@@ -9,6 +9,16 @@
|
|||||||
# under the GNU Public License v3 (GPLv3)
|
# under the GNU Public License v3 (GPLv3)
|
||||||
#
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Global aliases for boolean types to distinguish the use of "int" from "bool".
|
||||||
|
# NOTE: unfortunately, it doesn't work as an assignment of a default value for a function parameter!
|
||||||
|
#
|
||||||
|
var true = 1;
|
||||||
|
var false = 0;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Global object of Aerotow
|
||||||
|
#
|
||||||
var g_Aerotow = nil;
|
var g_Aerotow = nil;
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
<hrule/>
|
<hrule/>
|
||||||
|
|
||||||
<text>
|
<text>
|
||||||
<label>Aerotow Everywhere version 1.4.1 - 20th August 2022</label>
|
<label>Aerotow Everywhere version 1.6.0 - 23nd August 2022</label>
|
||||||
</text>
|
</text>
|
||||||
|
|
||||||
<text>
|
<text>
|
||||||
|
|||||||
@@ -0,0 +1,342 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<PropertyList>
|
||||||
|
<name>towrope-config</name>
|
||||||
|
<layout>vbox</layout>
|
||||||
|
<default-padding>5</default-padding>
|
||||||
|
<modal>false</modal>
|
||||||
|
<width>680</width>
|
||||||
|
|
||||||
|
<!-- title bar -->
|
||||||
|
<group>
|
||||||
|
<layout>hbox</layout>
|
||||||
|
<empty>
|
||||||
|
<stretch>true</stretch>
|
||||||
|
</empty>
|
||||||
|
<text>
|
||||||
|
<label>Towrope Configuration</label>
|
||||||
|
</text>
|
||||||
|
<empty>
|
||||||
|
<stretch>true</stretch>
|
||||||
|
</empty>
|
||||||
|
<button>
|
||||||
|
<legend/>
|
||||||
|
<key>Esc</key>
|
||||||
|
<pref-width>16</pref-width>
|
||||||
|
<pref-height>16</pref-height>
|
||||||
|
<border>2</border>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-close</command>
|
||||||
|
</binding>
|
||||||
|
</button>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<hrule/>
|
||||||
|
|
||||||
|
<!-- aerotow parameters -->
|
||||||
|
<group>
|
||||||
|
<layout>hbox</layout>
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<layout>table</layout>
|
||||||
|
|
||||||
|
<!-- tow length -->
|
||||||
|
<text>
|
||||||
|
<row>0</row>
|
||||||
|
<col>0</col>
|
||||||
|
<halign>right</halign>
|
||||||
|
<label>Towrope Length</label>
|
||||||
|
</text>
|
||||||
|
<text>
|
||||||
|
<row>0</row>
|
||||||
|
<col>1</col>
|
||||||
|
<halign>right</halign>
|
||||||
|
<label></label>
|
||||||
|
<live>true</live>
|
||||||
|
<format>%.0f m </format>
|
||||||
|
<property>/sim/hitches/aerotow/tow/length</property>
|
||||||
|
<color>
|
||||||
|
<red>0.2</red>
|
||||||
|
<green>0.9</green>
|
||||||
|
<blue>0.2</blue>
|
||||||
|
</color>
|
||||||
|
</text>
|
||||||
|
|
||||||
|
<!-- break force -->
|
||||||
|
<text>
|
||||||
|
<row>1</row>
|
||||||
|
<col>0</col>
|
||||||
|
<halign>right</halign>
|
||||||
|
<label>Weak Link Break Force</label>
|
||||||
|
</text>
|
||||||
|
<text>
|
||||||
|
<row>1</row>
|
||||||
|
<col>1</col>
|
||||||
|
<halign>right</halign>
|
||||||
|
<label></label>
|
||||||
|
<live>true</live>
|
||||||
|
<format>%.0f N </format>
|
||||||
|
<property>/sim/hitches/aerotow/tow/brake-force</property>
|
||||||
|
<color>
|
||||||
|
<red>0.2</red>
|
||||||
|
<green>0.9</green>
|
||||||
|
<blue>0.2</blue>
|
||||||
|
</color>
|
||||||
|
</text>
|
||||||
|
|
||||||
|
<!-- tow characteristic -->
|
||||||
|
<text>
|
||||||
|
<row>2</row>
|
||||||
|
<col>0</col>
|
||||||
|
<halign>right</halign>
|
||||||
|
<label>Towrope Elastic Constant</label>
|
||||||
|
</text>
|
||||||
|
<text>
|
||||||
|
<row>2</row>
|
||||||
|
<col>1</col>
|
||||||
|
<halign>right</halign>
|
||||||
|
<label></label>
|
||||||
|
<live>true</live>
|
||||||
|
<format>%.0f N</format>
|
||||||
|
<property>/sim/hitches/aerotow/tow/elastic-constant</property>
|
||||||
|
<color>
|
||||||
|
<red>0.2</red>
|
||||||
|
<green>0.9</green>
|
||||||
|
<blue>0.2</blue>
|
||||||
|
</color>
|
||||||
|
</text>
|
||||||
|
|
||||||
|
<!-- tow thickness -->
|
||||||
|
<text>
|
||||||
|
<row>3</row>
|
||||||
|
<col>0</col>
|
||||||
|
<halign>right</halign>
|
||||||
|
<label>Towrope Diameter</label>
|
||||||
|
</text>
|
||||||
|
<text>
|
||||||
|
<row>3</row>
|
||||||
|
<col>1</col>
|
||||||
|
<halign>right</halign>
|
||||||
|
<label></label>
|
||||||
|
<live>true</live>
|
||||||
|
<format>%.0f mm</format>
|
||||||
|
<property>/sim/hitches/aerotow/rope/rope-diameter-mm</property>
|
||||||
|
<color>
|
||||||
|
<red>0.2</red>
|
||||||
|
<green>0.9</green>
|
||||||
|
<blue>0.2</blue>
|
||||||
|
</color>
|
||||||
|
</text>
|
||||||
|
|
||||||
|
<!-- tow weight -->
|
||||||
|
<text>
|
||||||
|
<row>4</row>
|
||||||
|
<col>0</col>
|
||||||
|
<halign>right</halign>
|
||||||
|
<label>Towrope Weight per Meter</label>
|
||||||
|
</text>
|
||||||
|
<text>
|
||||||
|
<row>4</row>
|
||||||
|
<col>1</col>
|
||||||
|
<halign>right</halign>
|
||||||
|
<label></label>
|
||||||
|
<live>true</live>
|
||||||
|
<format>%.3f kg/m</format>
|
||||||
|
<property>/sim/hitches/aerotow/tow/weight-per-m-kg-m</property>
|
||||||
|
<color>
|
||||||
|
<red>0.2</red>
|
||||||
|
<green>0.9</green>
|
||||||
|
<blue>0.2</blue>
|
||||||
|
</color>
|
||||||
|
</text>
|
||||||
|
</group>
|
||||||
|
<empty>
|
||||||
|
<stretch>true</stretch>
|
||||||
|
</empty>
|
||||||
|
|
||||||
|
<vrule/>
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<layout>table</layout>
|
||||||
|
|
||||||
|
<!-- tow length -->
|
||||||
|
<text>
|
||||||
|
<row>0</row>
|
||||||
|
<col>1</col>
|
||||||
|
<halign>right</halign>
|
||||||
|
<label>20 m</label>
|
||||||
|
</text>
|
||||||
|
<slider>
|
||||||
|
<row>0</row>
|
||||||
|
<col>2</col>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>fill</halign>
|
||||||
|
<pref-width>300</pref-width>
|
||||||
|
<name>tow_length</name>
|
||||||
|
<property>/sim/hitches/aerotow/tow/length</property>
|
||||||
|
<min>20</min>
|
||||||
|
<max>200</max>
|
||||||
|
<step>5</step>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
</slider>
|
||||||
|
<text>
|
||||||
|
<row>0</row>
|
||||||
|
<col>3</col>
|
||||||
|
<halign>left</halign>
|
||||||
|
<label>200 m</label>
|
||||||
|
</text>
|
||||||
|
|
||||||
|
<!-- break force -->
|
||||||
|
<text>
|
||||||
|
<row>1</row>
|
||||||
|
<col>1</col>
|
||||||
|
<halign>right</halign>
|
||||||
|
<label>100 N</label>
|
||||||
|
</text>
|
||||||
|
<slider>
|
||||||
|
<row>1</row>
|
||||||
|
<col>2</col>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>fill</halign>
|
||||||
|
<pref-width>300</pref-width>
|
||||||
|
<name>break_force</name>
|
||||||
|
<property>/sim/hitches/aerotow/tow/brake-force</property>
|
||||||
|
<min>100</min>
|
||||||
|
<max>100000</max>
|
||||||
|
<step>100</step>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
</slider>
|
||||||
|
<text>
|
||||||
|
<row>1</row>
|
||||||
|
<col>3</col>
|
||||||
|
<halign>left</halign>
|
||||||
|
<label>100,000 N</label>
|
||||||
|
</text>
|
||||||
|
|
||||||
|
<!-- tow characteristic -->
|
||||||
|
<text>
|
||||||
|
<row>2</row>
|
||||||
|
<col>1</col>
|
||||||
|
<halign>right</halign>
|
||||||
|
<label>0 N</label>
|
||||||
|
</text>
|
||||||
|
<slider>
|
||||||
|
<row>2</row>
|
||||||
|
<col>2</col>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>fill</halign>
|
||||||
|
<pref-width>300</pref-width>
|
||||||
|
<name>elastic_constant</name>
|
||||||
|
<property>/sim/hitches/aerotow/tow/elastic-constant</property>
|
||||||
|
<min>0</min>
|
||||||
|
<max>1500000</max>
|
||||||
|
<step>200</step>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
</slider>
|
||||||
|
<text>
|
||||||
|
<row>2</row>
|
||||||
|
<col>3</col>
|
||||||
|
<halign>left</halign>
|
||||||
|
<label>1,500,000 N</label>
|
||||||
|
</text>
|
||||||
|
|
||||||
|
<!-- tow thickness -->
|
||||||
|
<text>
|
||||||
|
<row>3</row>
|
||||||
|
<col>1</col>
|
||||||
|
<halign>right</halign>
|
||||||
|
<label>0 mm</label>
|
||||||
|
</text>
|
||||||
|
<slider>
|
||||||
|
<row>3</row>
|
||||||
|
<col>2</col>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>fill</halign>
|
||||||
|
<pref-width>300</pref-width>
|
||||||
|
<name>rope_diameter</name>
|
||||||
|
<property>/sim/hitches/aerotow/rope/rope-diameter-mm</property>
|
||||||
|
<min>0</min>
|
||||||
|
<max>50</max>
|
||||||
|
<step>1</step>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
</slider>
|
||||||
|
<text>
|
||||||
|
<row>3</row>
|
||||||
|
<col>3</col>
|
||||||
|
<halign>left</halign>
|
||||||
|
<label>50 mm</label>
|
||||||
|
</text>
|
||||||
|
|
||||||
|
<!-- tow weight -->
|
||||||
|
<text>
|
||||||
|
<row>4</row>
|
||||||
|
<col>1</col>
|
||||||
|
<halign>right</halign>
|
||||||
|
<label>0 kg/m</label>
|
||||||
|
</text>
|
||||||
|
<slider>
|
||||||
|
<row>4</row>
|
||||||
|
<col>2</col>
|
||||||
|
<live>true</live>
|
||||||
|
<halign>fill</halign>
|
||||||
|
<pref-width>300</pref-width>
|
||||||
|
<name>weight_per_m</name>
|
||||||
|
<property>/sim/hitches/aerotow/tow/weight-per-m-kg-m</property>
|
||||||
|
<min>0</min>
|
||||||
|
<max>1</max>
|
||||||
|
<step>0.001</step>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-apply</command>
|
||||||
|
</binding>
|
||||||
|
</slider>
|
||||||
|
<text>
|
||||||
|
<row>4</row>
|
||||||
|
<col>3</col>
|
||||||
|
<halign>left</halign>
|
||||||
|
<label>1 kg/m</label>
|
||||||
|
</text>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<hrule/>
|
||||||
|
|
||||||
|
<!-- bottom line -->
|
||||||
|
<group>
|
||||||
|
<layout>hbox</layout>
|
||||||
|
<empty>
|
||||||
|
<stretch>true</stretch>
|
||||||
|
</empty>
|
||||||
|
<button>
|
||||||
|
<legend>Close</legend>
|
||||||
|
<equal>true</equal>
|
||||||
|
<binding>
|
||||||
|
<command>dialog-close</command>
|
||||||
|
</binding>
|
||||||
|
</button>
|
||||||
|
<button>
|
||||||
|
<legend>Default</legend>
|
||||||
|
<equal>true</equal>
|
||||||
|
<binding>
|
||||||
|
<command>nasal</command>
|
||||||
|
<script><![CDATA[
|
||||||
|
setprop("/sim/hitches/aerotow/tow/length", 60.0); # hitch.nas 60.0
|
||||||
|
setprop("/sim/hitches/aerotow/tow/brake-force", 100000.0); # hitch.nas 12345.0
|
||||||
|
setprop("/sim/hitches/aerotow/tow/elastic-constant", 10000.0); # hitch.nas 9111.0
|
||||||
|
setprop("/sim/hitches/aerotow/rope/rope-diameter-mm", 20); # hitch.nas 20
|
||||||
|
setprop("/sim/hitches/aerotow/tow/weight-per-m-kg-m", 0.35); # hitch.nas 0.35
|
||||||
|
]]></script>
|
||||||
|
</binding>
|
||||||
|
</button>
|
||||||
|
<empty>
|
||||||
|
<stretch>true</stretch>
|
||||||
|
</empty>
|
||||||
|
</group>
|
||||||
|
</PropertyList>
|
||||||
+9
-15
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
#
|
#
|
||||||
# Aerotow object
|
# Class Aerotow for enable and disable scenario with aerotow aircraft.
|
||||||
#
|
#
|
||||||
var Aerotow = {
|
var Aerotow = {
|
||||||
#
|
#
|
||||||
@@ -51,20 +51,16 @@ var Aerotow = {
|
|||||||
#
|
#
|
||||||
# Function for restart AI scenario with delay when the sound has to stop.
|
# Function for restart AI scenario with delay when the sound has to stop.
|
||||||
#
|
#
|
||||||
# Return 1 on successful, otherwise 0.
|
|
||||||
#
|
|
||||||
restartAerotow: func () {
|
restartAerotow: func () {
|
||||||
me.message.success("Aerotow on the way");
|
me.message.success("Aerotow on the way");
|
||||||
|
|
||||||
# Stop playing engine sound
|
# Stop playing engine sound
|
||||||
setprop(me.addonNodePath ~ "/addon-devel/sound/enable", 0);
|
setprop(me.addonNodePath ~ "/addon-devel/sound/enable", false);
|
||||||
|
|
||||||
# Wait a second for the engine sound to turn off
|
# Wait a second for the engine sound to turn off
|
||||||
var timer = maketimer(1, func () {
|
Timer.new().singleShot(1, me, func () {
|
||||||
me.unloadScenario();
|
me.unloadScenario();
|
||||||
});
|
});
|
||||||
timer.singleShot = 1;
|
|
||||||
timer.start();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -76,25 +72,23 @@ var Aerotow = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Start aerotow with delay to avoid duplicate engine sound playing
|
# Start aerotow with delay to avoid duplicate engine sound playing
|
||||||
var timer = maketimer(1, func () {
|
Timer.new().singleShot(1, me, func () {
|
||||||
me.startAerotow();
|
me.startAerotow();
|
||||||
});
|
});
|
||||||
timer.singleShot = 1;
|
|
||||||
timer.start();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
#
|
#
|
||||||
# Main function to prepare AI scenario and run it.
|
# Main function to prepare AI scenario and run it.
|
||||||
#
|
#
|
||||||
# Return 1 on successful, otherwise 0.
|
# Return true on successful, otherwise false.
|
||||||
#
|
#
|
||||||
startAerotow: func () {
|
startAerotow: func () {
|
||||||
if (!me.scenario.unload()) {
|
if (!me.scenario.unload()) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!me.scenario.generateXml()) {
|
if (!me.scenario.generateXml()) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return me.scenario.load();
|
return me.scenario.load();
|
||||||
@@ -103,10 +97,10 @@ var Aerotow = {
|
|||||||
#
|
#
|
||||||
# Function for unload our AI scenario.
|
# Function for unload our AI scenario.
|
||||||
#
|
#
|
||||||
# Return 1 on successful, otherwise 0.
|
# Return true on successful, otherwise false.
|
||||||
#
|
#
|
||||||
stopAerotow: func () {
|
stopAerotow: func () {
|
||||||
var withMessages = 1;
|
var withMessages = true;
|
||||||
return me.scenario.unload(withMessages);
|
return me.scenario.unload(withMessages);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
+7
-7
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
#
|
#
|
||||||
# Parent object of Aircraft
|
# Parent class of Aircraft
|
||||||
#
|
#
|
||||||
var Aircraft = {
|
var Aircraft = {
|
||||||
#
|
#
|
||||||
@@ -50,7 +50,7 @@ var Aircraft = {
|
|||||||
#
|
#
|
||||||
# name - Name of aircraft to check.
|
# name - Name of aircraft to check.
|
||||||
#
|
#
|
||||||
# Return 1 when match, otherwise 0.
|
# Return true when match, otherwise false.
|
||||||
#
|
#
|
||||||
isModelName: func (name) {
|
isModelName: func (name) {
|
||||||
return name == me.name or name == me.nameMenuCall;
|
return name == me.name or name == me.nameMenuCall;
|
||||||
@@ -69,8 +69,8 @@ var Aircraft = {
|
|||||||
# Return selected Aircraft object
|
# Return selected Aircraft object
|
||||||
#
|
#
|
||||||
# addon - Addon object
|
# addon - Addon object
|
||||||
# isRouteMode - Use 1 to get the plane for the "Aerotow Route" dialog,
|
# isRouteMode - Use true to get the plane for the "Aerotow Route" dialog,
|
||||||
# use 0 (default) for call the airplane for towing.
|
# use false (default) for call the airplane for towing.
|
||||||
#
|
#
|
||||||
getSelected: func (addon, isRouteMode = 0) {
|
getSelected: func (addon, isRouteMode = 0) {
|
||||||
var name = Aircraft.getSelectedAircraftName(addon, isRouteMode);
|
var name = Aircraft.getSelectedAircraftName(addon, isRouteMode);
|
||||||
@@ -89,10 +89,10 @@ var Aircraft = {
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
# addon - Addon object
|
# addon - Addon object
|
||||||
# isRouteMode - Use 1 to get the plane for the "Aerotow Route" dialog,
|
# isRouteMode - Use true to get the plane for the "Aerotow Route" dialog,
|
||||||
# use 0 (default) for call the airplane for towing.
|
# use false (default) for call the airplane for towing.
|
||||||
#
|
#
|
||||||
getSelectedAircraftName: func (addon, isRouteMode = 0) {
|
getSelectedAircraftName: func (addon, isRouteMode) {
|
||||||
if (isRouteMode) {
|
if (isRouteMode) {
|
||||||
return getprop(addon.node.getPath() ~ "/addon-devel/route/ai-model") or g_Aircrafts[0].name;
|
return getprop(addon.node.getPath() ~ "/addon-devel/route/ai-model") or g_Aircrafts[0].name;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
#
|
#
|
||||||
# Object for hande Route Dialog
|
# Class for hande Route Dialog
|
||||||
#
|
#
|
||||||
var RouteDialog = {
|
var RouteDialog = {
|
||||||
#
|
#
|
||||||
@@ -64,9 +64,9 @@ var RouteDialog = {
|
|||||||
calculateAltChangeAndTotals: func () {
|
calculateAltChangeAndTotals: func () {
|
||||||
var totalDistance = 0.0;
|
var totalDistance = 0.0;
|
||||||
var totalAlt = 0.0;
|
var totalAlt = 0.0;
|
||||||
var isEnd = 0;
|
var isEnd = false;
|
||||||
|
|
||||||
var isRouteMode = 1;
|
var isRouteMode = true;
|
||||||
var aircraft = Aircraft.getSelected(me.addon, isRouteMode);
|
var aircraft = Aircraft.getSelected(me.addon, isRouteMode);
|
||||||
|
|
||||||
for (var i = 0; i < me.maxRouteWaypoints; i += 1) {
|
for (var i = 0; i < me.maxRouteWaypoints; i += 1) {
|
||||||
@@ -84,7 +84,7 @@ var RouteDialog = {
|
|||||||
totalAlt += altChange;
|
totalAlt += altChange;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
isEnd = 1;
|
isEnd = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
# under the GNU Public License v3 (GPLv3)
|
# under the GNU Public License v3 (GPLv3)
|
||||||
#
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Class Thermal for handle add new thermal.
|
||||||
|
#
|
||||||
var Thermal = {
|
var Thermal = {
|
||||||
#
|
#
|
||||||
# Constructor
|
# Constructor
|
||||||
@@ -59,7 +62,7 @@ var Thermal = {
|
|||||||
#
|
#
|
||||||
# Add thermal 300 m before glider position.
|
# Add thermal 300 m before glider position.
|
||||||
#
|
#
|
||||||
# Return 1 on successful, otherwise 0.
|
# Return true on successful, otherwise false.
|
||||||
#
|
#
|
||||||
add: func () {
|
add: func () {
|
||||||
var heading = getprop("/orientation/heading-deg") or 0;
|
var heading = getprop("/orientation/heading-deg") or 0;
|
||||||
@@ -84,10 +87,10 @@ var Thermal = {
|
|||||||
|
|
||||||
if (fgcommand("add-aiobject", args)) {
|
if (fgcommand("add-aiobject", args)) {
|
||||||
me.message.success("The thermal has been added");
|
me.message.success("The thermal has been added");
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
me.message.error("Adding thermal failed");
|
me.message.error("Adding thermal failed");
|
||||||
return 0;
|
return false;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
+27
-16
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
#
|
#
|
||||||
# Flight Plan object
|
# Class FlightPlan for crate and save as XML file the flight plan for AI scenario.
|
||||||
#
|
#
|
||||||
var FlightPlan = {
|
var FlightPlan = {
|
||||||
#
|
#
|
||||||
@@ -93,7 +93,7 @@ var FlightPlan = {
|
|||||||
"lat" : rwyResult.runway.lat,
|
"lat" : rwyResult.runway.lat,
|
||||||
"lon" : rwyResult.runway.lon,
|
"lon" : rwyResult.runway.lon,
|
||||||
"heading" : rwyResult.runway.heading,
|
"heading" : rwyResult.runway.heading,
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -124,17 +124,17 @@ var FlightPlan = {
|
|||||||
#
|
#
|
||||||
# Initialize flight plan and set it to property tree
|
# Initialize flight plan and set it to property tree
|
||||||
#
|
#
|
||||||
# Return 1 on successful, otherwise 0.
|
# Return true on successful, otherwise false.
|
||||||
#
|
#
|
||||||
initial: func () {
|
initial: func () {
|
||||||
var location = me.getLocation();
|
var location = me.getLocation();
|
||||||
if (location == nil) {
|
if (location == nil) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var aircraft = Aircraft.getSelected(me.addon);
|
var aircraft = Aircraft.getSelected(me.addon);
|
||||||
|
|
||||||
var isGliderPos = 0;
|
var isGliderPos = false;
|
||||||
me.initAircraftVariable(location, isGliderPos);
|
me.initAircraftVariable(location, isGliderPos);
|
||||||
|
|
||||||
# inittial readonly waypoint
|
# inittial readonly waypoint
|
||||||
@@ -189,28 +189,28 @@ var FlightPlan = {
|
|||||||
|
|
||||||
setprop(me.addonNodePath ~ "/addon-devel/route/wpts/description", "Default route around the start location");
|
setprop(me.addonNodePath ~ "/addon-devel/route/wpts/description", "Default route around the start location");
|
||||||
|
|
||||||
return 1;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
#
|
#
|
||||||
# Generate the XML file with the flight plane for our plane for AI scenario.
|
# Generate the XML file with the flight plane for our plane for AI scenario.
|
||||||
# The file will be stored to $Fobj.HOME/Export/aerotown-addon-flightplan.xml.
|
# The file will be stored to $FG_HOME/Export/Addons/org.flightgear.addons.Aerotow/AI/FlightPlans/aerotown-addon-flightplan.xml.
|
||||||
#
|
#
|
||||||
# Return 1 on successful, otherwise 0.
|
# Return true on successful, otherwise false.
|
||||||
#
|
#
|
||||||
generateXml: func () {
|
generateXml: func () {
|
||||||
me.wptCount = 0;
|
me.wptCount = 0;
|
||||||
|
|
||||||
var location = me.getLocation();
|
var location = me.getLocation();
|
||||||
if (location == nil) {
|
if (location == nil) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
me.flightPlanWriter.open();
|
me.flightPlanWriter.open();
|
||||||
|
|
||||||
var aircraft = Aircraft.getSelected(me.addon);
|
var aircraft = Aircraft.getSelected(me.addon);
|
||||||
|
|
||||||
var isGliderPos = 1;
|
var isGliderPos = true;
|
||||||
me.initAircraftVariable(location, isGliderPos);
|
me.initAircraftVariable(location, isGliderPos);
|
||||||
|
|
||||||
# Start at 2 o'clock from the glider...
|
# Start at 2 o'clock from the glider...
|
||||||
@@ -218,13 +218,13 @@ var FlightPlan = {
|
|||||||
me.addWptGround({"hdgChange": 60, "dist": 25}, {"altChange": 0, "ktas": 5});
|
me.addWptGround({"hdgChange": 60, "dist": 25}, {"altChange": 0, "ktas": 5});
|
||||||
|
|
||||||
# Reset coord and heading
|
# Reset coord and heading
|
||||||
isGliderPos = 0;
|
isGliderPos = false;
|
||||||
me.initAircraftVariable(location, isGliderPos);
|
me.initAircraftVariable(location, isGliderPos);
|
||||||
|
|
||||||
var gliderOffsetM = me.getGliderOffsetFromRunwayThreshold(location);
|
var gliderOffsetM = me.getGliderOffsetFromRunwayThreshold(location);
|
||||||
|
|
||||||
# ... and line up with the runway
|
# ... and line up with the runway
|
||||||
me.addWptGround({"hdgChange": 0, "dist": 30 + gliderOffsetM}, {"altChange": 0, "ktas": 2.5});
|
me.addWptGround({"hdgChange": 0, "dist": me.getInitialDistance() + gliderOffsetM}, {"altChange": 0, "ktas": 2.5});
|
||||||
|
|
||||||
# Rolling
|
# Rolling
|
||||||
me.addWptGround({"hdgChange": 0, "dist": 10}, {"altChange": 0, "ktas": 5});
|
me.addWptGround({"hdgChange": 0, "dist": 10}, {"altChange": 0, "ktas": 5});
|
||||||
@@ -268,16 +268,27 @@ var FlightPlan = {
|
|||||||
|
|
||||||
me.flightPlanWriter.close();
|
me.flightPlanWriter.close();
|
||||||
|
|
||||||
return 1;
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
#
|
||||||
|
# Get initial distance AI plane from the glider that the tow is nearly tautened.
|
||||||
|
#
|
||||||
|
# Return distance in meters.
|
||||||
|
#
|
||||||
|
getInitialDistance: func () {
|
||||||
|
var ropeLengthM = getprop("/sim/hitches/aerotow/tow/length") or 60;
|
||||||
|
var tautenRelative = 0.68;
|
||||||
|
return ropeLengthM * tautenRelative;
|
||||||
},
|
},
|
||||||
|
|
||||||
#
|
#
|
||||||
# Initialize AI aircraft variable
|
# Initialize AI aircraft variable
|
||||||
#
|
#
|
||||||
# location - Object of location from which the glider start.
|
# location - Object of location from which the glider start.
|
||||||
# isGliderPos - Pass 1 for set AI aircraft's coordinates as glider position, 0 set coordinates as runway threshold.
|
# isGliderPos - Pass true for set AI aircraft's coordinates as glider position, false set coordinates as runway threshold.
|
||||||
#
|
#
|
||||||
initAircraftVariable: func (location, isGliderPos = 1) {
|
initAircraftVariable: func (location, isGliderPos) {
|
||||||
var gliderCoord = geo.aircraft_position();
|
var gliderCoord = geo.aircraft_position();
|
||||||
|
|
||||||
# Set coordinates as glider position or runway threshold
|
# Set coordinates as glider position or runway threshold
|
||||||
@@ -307,7 +318,7 @@ var FlightPlan = {
|
|||||||
return rwyThreshold.distance_to(gliderCoord);
|
return rwyThreshold.distance_to(gliderCoord);
|
||||||
}
|
}
|
||||||
|
|
||||||
# We are not on runway
|
# We are not on the runway, return 0 distance
|
||||||
return 0;
|
return 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
#
|
#
|
||||||
# Object for write flight plan to the XML file
|
# Class FlightPlanWriter for write flight plan to the XML file
|
||||||
#
|
#
|
||||||
var FlightPlanWriter = {
|
var FlightPlanWriter = {
|
||||||
#
|
#
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
#
|
#
|
||||||
# Object for display messages
|
# Class Message for display messages on the screen with read by speech synthesizer.
|
||||||
#
|
#
|
||||||
var Message = {
|
var Message = {
|
||||||
#
|
#
|
||||||
|
|||||||
+26
-24
@@ -10,16 +10,16 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
#
|
#
|
||||||
# Scenario object
|
# Class Scenario for create AI scenario XML file and attach it to scenario property list for load it.
|
||||||
#
|
#
|
||||||
var Scenario = {
|
var Scenario = {
|
||||||
#
|
#
|
||||||
# Constants
|
# Constants
|
||||||
#
|
#
|
||||||
SCENARIO_ID: "aerotow_addon",
|
SCENARIO_ID: "aerotow_addon",
|
||||||
SCENARIO_NAME: "Aerotow Add-on",
|
SCENARIO_NAME: "Aerotow Add-on",
|
||||||
SCENARIO_DESC: "This scenario starts the towing plane at the airport where the pilot with the glider is located. Use Ctrl-o to hook the plane.",
|
SCENARIO_DESC: "This scenario starts the towing plane at the airport where the pilot with the glider is located. Use Ctrl-o to hook the plane.",
|
||||||
FILENAME_SCENARIO: "aerotown-addon.xml",
|
FILENAME_SCENARIO: "aerotown-addon.xml",
|
||||||
|
|
||||||
#
|
#
|
||||||
# Constructor
|
# Constructor
|
||||||
@@ -38,7 +38,7 @@ var Scenario = {
|
|||||||
obj.listeners = [];
|
obj.listeners = [];
|
||||||
obj.routeDialog = RouteDialog.new(addon, message);
|
obj.routeDialog = RouteDialog.new(addon, message);
|
||||||
obj.flightPlan = FlightPlan.new(addon, message, obj.routeDialog);
|
obj.flightPlan = FlightPlan.new(addon, message, obj.routeDialog);
|
||||||
obj.isScenarioLoaded = 0;
|
obj.isScenarioLoaded = false;
|
||||||
obj.scenarioPath = addon.storagePath ~ "/" ~ Scenario.FILENAME_SCENARIO;
|
obj.scenarioPath = addon.storagePath ~ "/" ~ Scenario.FILENAME_SCENARIO;
|
||||||
|
|
||||||
obj.flightPlan.initial();
|
obj.flightPlan.initial();
|
||||||
@@ -64,11 +64,13 @@ var Scenario = {
|
|||||||
|
|
||||||
#
|
#
|
||||||
# Generate the XML file with the AI scenario.
|
# Generate the XML file with the AI scenario.
|
||||||
# The file will be stored to $FG_HOME/Export/aerotown-addon.xml.
|
# The file will be stored to $FG_HOME/Export/Addons/org.flightgear.addons.Aerotow/aerotown-addon.xml.
|
||||||
|
#
|
||||||
|
# Return true on successful, otherwise false
|
||||||
#
|
#
|
||||||
generateXml: func () {
|
generateXml: func () {
|
||||||
if (!me.flightPlan.generateXml()) {
|
if (!me.flightPlan.generateXml()) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var scenarioXml = {
|
var scenarioXml = {
|
||||||
@@ -82,7 +84,7 @@ var Scenario = {
|
|||||||
"class": "aerotow-dragger",
|
"class": "aerotow-dragger",
|
||||||
"model": Aircraft.getSelected(me.addon).modelPath,
|
"model": Aircraft.getSelected(me.addon).modelPath,
|
||||||
"flightplan": FlightPlan.FILENAME_FLIGHTPLAN,
|
"flightplan": FlightPlan.FILENAME_FLIGHTPLAN,
|
||||||
"repeat": 1,
|
"repeat": true, # start again indefinitely
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,7 +95,7 @@ var Scenario = {
|
|||||||
|
|
||||||
me.addScenarioToPropertyList();
|
me.addScenarioToPropertyList();
|
||||||
|
|
||||||
return 1;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -114,67 +116,67 @@ var Scenario = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
#
|
#
|
||||||
# Return 1 if scenario is already added to "/sim/ai/scenarios" property list, otherwise return 0.
|
# Return true if scenario is already added to "/sim/ai/scenarios" property list, otherwise return false.
|
||||||
#
|
#
|
||||||
isAlreadyAdded: func () {
|
isAlreadyAdded: func () {
|
||||||
foreach (var scenario; props.globals.getNode("/sim/ai/scenarios").getChildren("scenario")) {
|
foreach (var scenario; props.globals.getNode("/sim/ai/scenarios").getChildren("scenario")) {
|
||||||
var id = scenario.getChild("id");
|
var id = scenario.getChild("id");
|
||||||
if (id != nil and id.getValue() == Scenario.SCENARIO_ID) {
|
if (id != nil and id.getValue() == Scenario.SCENARIO_ID) {
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
#
|
#
|
||||||
# Load scenario
|
# Load scenario
|
||||||
#
|
#
|
||||||
# Return 1 on successful, otherwise 0.
|
# Return true on successful, otherwise false.
|
||||||
#
|
#
|
||||||
load: func () {
|
load: func () {
|
||||||
var args = props.Node.new({ "name": Scenario.SCENARIO_ID });
|
var args = props.Node.new({ "name": Scenario.SCENARIO_ID });
|
||||||
if (fgcommand("load-scenario", args)) {
|
if (fgcommand("load-scenario", args)) {
|
||||||
me.isScenarioLoaded = 1;
|
me.isScenarioLoaded = true;
|
||||||
me.message.success("Let's fly!");
|
me.message.success("Let's fly!");
|
||||||
|
|
||||||
# Enable engine sound
|
# Enable engine sound
|
||||||
setprop(me.addonNodePath ~ "/addon-devel/sound/enable", 1);
|
setprop(me.addonNodePath ~ "/addon-devel/sound/enable", true);
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
me.message.error("Tow failed!");
|
me.message.error("Tow failed!");
|
||||||
return 0;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
#
|
#
|
||||||
# Unload scenario
|
# Unload scenario
|
||||||
#
|
#
|
||||||
# withMessages - Set 1 to display messages.
|
# withMessages - Set true to display messages.
|
||||||
#
|
#
|
||||||
# Return 1 on successful, otherwise 0.
|
# Return true on successful, otherwise false.
|
||||||
#
|
#
|
||||||
unload: func (withMessages = 0) {
|
unload: func (withMessages = 0) {
|
||||||
if (me.isScenarioLoaded) {
|
if (me.isScenarioLoaded) {
|
||||||
var args = props.Node.new({ "name": Scenario.SCENARIO_ID });
|
var args = props.Node.new({ "name": Scenario.SCENARIO_ID });
|
||||||
if (fgcommand("unload-scenario", args)) {
|
if (fgcommand("unload-scenario", args)) {
|
||||||
me.isScenarioLoaded = 0;
|
me.isScenarioLoaded = false;
|
||||||
|
|
||||||
if (withMessages) {
|
if (withMessages) {
|
||||||
me.message.success("Aerotown disabled");
|
me.message.success("Aerotown disabled");
|
||||||
}
|
}
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (withMessages) {
|
if (withMessages) {
|
||||||
me.message.error("Aerotown disable failed");
|
me.message.error("Aerotown disable failed");
|
||||||
}
|
}
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (withMessages) {
|
if (withMessages) {
|
||||||
me.message.success("Aerotown already disabled");
|
me.message.success("Aerotown already disabled");
|
||||||
}
|
}
|
||||||
return 1;
|
return true;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#
|
||||||
|
# Aerotow Everywhere - Add-on for FlightGear
|
||||||
|
#
|
||||||
|
# Written and developer by Roman Ludwicki (PlayeRom, SP-ROM)
|
||||||
|
#
|
||||||
|
# Copyright (C) 2022 Roman Ludwicki
|
||||||
|
#
|
||||||
|
# Aerotow Everywhere is an Open Source project and it is licensed
|
||||||
|
# under the GNU Public License v3 (GPLv3)
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Class Timer for wrapping maketimer() function.
|
||||||
|
#
|
||||||
|
var Timer = {
|
||||||
|
#
|
||||||
|
# Constructor
|
||||||
|
#
|
||||||
|
new: func () {
|
||||||
|
return { parents: [Timer] };
|
||||||
|
},
|
||||||
|
|
||||||
|
#
|
||||||
|
# Run timer as single shot
|
||||||
|
#
|
||||||
|
# delaySec - Delay in seconds for execute timer's callback.
|
||||||
|
# self - Specifying what any "me" references in the function being called will refer to.
|
||||||
|
# callback - Function to be called after given delay.
|
||||||
|
#
|
||||||
|
# Return timer handler object
|
||||||
|
#
|
||||||
|
singleShot: func (delaySec, self, callback) {
|
||||||
|
var timer = maketimer(delaySec, self, func () {
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
timer.singleShot = true;
|
||||||
|
timer.start();
|
||||||
|
|
||||||
|
return timer;
|
||||||
|
},
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user