diff --git a/Aircraft/Generic/soaring-instrumentation-sdk.nas b/Aircraft/Generic/soaring-instrumentation-sdk.nas index c82bb2d79..fcce506d5 100644 --- a/Aircraft/Generic/soaring-instrumentation-sdk.nas +++ b/Aircraft/Generic/soaring-instrumentation-sdk.nas @@ -28,7 +28,7 @@ # - add wind correction to speed-to-fly # - final glide computer -io.include("update_loop.nas"); +io.include("updateloop.nas"); var MPS2KPH = 3.6; var sqr = func(x) {x * x} @@ -44,14 +44,19 @@ var InstrumentComponent = { # TODO: Refactor aircrafts that use it and remove this. var Instrument = UpdateLoop; -# update_prop(property) -# Helper generator for updating the given property on every element update +## +# Helper generator for updating a property on every element update # # Example: +# # var needle = Dampener.new( # input: probe, # dampening: 2.8, # on_update: update_prop("/instrumentation/variometer/te-reading-mps")); +# +# See Aircraft/Instruments-3d/glider/vario/ilec-sc7.nas and +# Aircraft/Generic/soaring-instrumentation-sdk.nas for usage examples. +# You can also refer to the soaring sdk wiki page. var update_prop = func(property) { func(value) { setprop(property, value) } diff --git a/Aircraft/Generic/updateloop.nas b/Aircraft/Generic/updateloop.nas index 55de150de..d2fd000df 100644 --- a/Aircraft/Generic/updateloop.nas +++ b/Aircraft/Generic/updateloop.nas @@ -1,4 +1,4 @@ -# update_loop.nas - Generic Nasal update loop for implementing sytems, +# updateloop.nas - Generic Nasal update loop for implementing sytems, # instruments or physics simulation. # # Copyright (C) 2014 Anton Gomez Alvedro @@ -17,45 +17,44 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# Updatable + +## +# The UpdateLoop accepts a vector of Updatable components that it will call +# at regular intervals. In order to define custom objects to be controlled by +# the loop, the Updatable interface must be implemented: # -# The update loop accepts a vector of Updatable elements that it will update at -# regular intervals. In order to make custom elements, you should add Updatable -# to the parents vector of your object: -# -# var MyElement = { +# var MyComponent = { # parents: [Updatable], +# +# reset: func { +# ... +# }, +# update: func(dt) { +# ... +# }, # ... # }; -# -# Your component shall then implement an "update" and "reset" methods that -# the UpdateLoop will call when needed. var Updatable = { + + ## + # When reset() is called, the component shall clean all internal state and + # reinitialize itself as if starting from scratch. + # + # Reset will be called automatically after a teleport, and then on demand + # when UpdateLoop.reset() is explicitly called. + reset: func { }, + + ## + # Called at regular intervals from the UdateLoop. + # dt: Elapsed time in seconds since the last call. + update: func(dt) { }, }; ## -# Helper generator for updating a property on every element update -# -# Example: -# -# var needle = Dampener.new( -# input: probe, -# dampening: 2.8, -# on_update: update_prop("/instrumentation/variometer/te-reading-mps")); -# -# See Aircraft/Instruments-3d/glider/vario/ilec-sc7.nas and -# Aircraft/Generic/soaring-instrumentation-sdk.nas for usage examples. -# You can also refer to the soaring sdk wiki page. - -var update_prop = func(property) { - func(value) { setprop(property, value) } -}; - -# UpdateLoop -# Wraps a set of user provided objects and updates them periodically. +# Wraps a set of user provided Updatable objects and calls them periodically. # Takes care of critical sim signals (reinit, fdm-initialized, speed-up). var UpdateLoop = { @@ -63,14 +62,16 @@ var UpdateLoop = { # UpdateLoop.new(components, [update_period], [enable]) # # components: Vector of components to update on every iteration. - # update_period: Time in seconds between updates (optional). - # enable: Enable the loop immediately after creation (optional). + # update_period: Time in seconds between updates. + # enable: Enable the loop immediately after creation. + # ignore_fdm: Do not wait for the fdm to be ready for starting the loop. - new: func(components, update_period = 0, enable = 1) { + new: func(components, update_period = 0, enable = 1, ignore_fdm = 0) { var m = { parents: [UpdateLoop] }; m.initialized = 0; m.enabled = enable; + m.ignore_fdm = ignore_fdm; m.update_period = update_period; m.time_last = 0; m.sim_speed = 1; @@ -84,16 +85,18 @@ var UpdateLoop = { append(m.lst, setlistener("/sim/speed-up", func(n) { m.sim_speed = n.getValue() }, 1, 0)); - append(m.lst, setlistener("sim/signals/reinit", func { - m.timer.stop(); - m.initialized = 0; - })); + append(m.lst, setlistener("sim/signals/reinit", + func(n) { m._on_teleport(n) })); - append(m.lst, setlistener("sim/signals/fdm-initialized", func { - if (m.timer.isRunning) m.timer.stop(); - call(me.reset, [], m); - if (m.enabled) m.timer.start(); - })); + if (ignore_fdm or getprop("sim/signals/fdm-initialized")) { + m.reset(); + enable and m.timer.start(); + } + + if (!ignore_fdm) { + append(m.lst, setlistener("sim/signals/fdm-initialized", + func(n) { m._on_teleport(n) })); + } return m; }, @@ -118,8 +121,7 @@ var UpdateLoop = { }, ## - # Enables the loop if it was disabled, i.e. the loop will start updating - # the components under control + # The loop will start updating the components under its control. enable: func { if (me.initialized) me.timer.start(); @@ -127,8 +129,8 @@ var UpdateLoop = { }, ## - # Disables the loop if it was enabled, i.e. the loop will freeze and its - # components will not get updates until enabled again + # The loop will freeze and its components will not get updates until + # enabled again. disable: func { me.timer.stop(); @@ -145,4 +147,18 @@ var UpdateLoop = { foreach (var component; me.components) component.update(dt); }, + + _on_teleport: func(n) { + var signal = n.getName(); + + if (signal == "reinit" and n.getValue()) { + me.timer.stop(); + me.initialized = 0; + } + elsif (me.ignore_fdm or signal == "fdm-initialized") { + me.timer.isRunning and me.timer.stop(); + me.reset(); + me.enabled and me.timer.start(); + } + } };