| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 | import ClockRange from "./ClockRange.js";import ClockStep from "./ClockStep.js";import defaultValue from "./defaultValue.js";import defined from "./defined.js";import DeveloperError from "./DeveloperError.js";import Event from "./Event.js";import getTimestamp from "./getTimestamp.js";import JulianDate from "./JulianDate.js";/** * A simple clock for keeping track of simulated time. * * @alias Clock * @constructor * * @param {Object} [options] Object with the following properties: * @param {JulianDate} [options.startTime] The start time of the clock. * @param {JulianDate} [options.stopTime] The stop time of the clock. * @param {JulianDate} [options.currentTime] The current time. * @param {Number} [options.multiplier=1.0] Determines how much time advances when {@link Clock#tick} is called, negative values allow for advancing backwards. * @param {ClockStep} [options.clockStep=ClockStep.SYSTEM_CLOCK_MULTIPLIER] Determines if calls to {@link Clock#tick} are frame dependent or system clock dependent. * @param {ClockRange} [options.clockRange=ClockRange.UNBOUNDED] Determines how the clock should behave when {@link Clock#startTime} or {@link Clock#stopTime} is reached. * @param {Boolean} [options.canAnimate=true] Indicates whether {@link Clock#tick} can advance time.  This could be false if data is being buffered, for example.  The clock will only tick when both {@link Clock#canAnimate} and {@link Clock#shouldAnimate} are true. * @param {Boolean} [options.shouldAnimate=false] Indicates whether {@link Clock#tick} should attempt to advance time.  The clock will only tick when both {@link Clock#canAnimate} and {@link Clock#shouldAnimate} are true. * * @exception {DeveloperError} startTime must come before stopTime. * * * @example * // Create a clock that loops on Christmas day 2013 and runs in real-time. * const clock = new Cesium.Clock({ *    startTime : Cesium.JulianDate.fromIso8601("2013-12-25"), *    currentTime : Cesium.JulianDate.fromIso8601("2013-12-25"), *    stopTime : Cesium.JulianDate.fromIso8601("2013-12-26"), *    clockRange : Cesium.ClockRange.LOOP_STOP, *    clockStep : Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER * }); * * @see ClockStep * @see ClockRange * @see JulianDate */function Clock(options) {  options = defaultValue(options, defaultValue.EMPTY_OBJECT);  let currentTime = options.currentTime;  let startTime = options.startTime;  let stopTime = options.stopTime;  if (!defined(currentTime)) {    // if not specified, current time is the start time,    // or if that is not specified, 1 day before the stop time,    // or if that is not specified, then now.    if (defined(startTime)) {      currentTime = JulianDate.clone(startTime);    } else if (defined(stopTime)) {      currentTime = JulianDate.addDays(stopTime, -1.0, new JulianDate());    } else {      currentTime = JulianDate.now();    }  } else {    currentTime = JulianDate.clone(currentTime);  }  if (!defined(startTime)) {    // if not specified, start time is the current time    // (as determined above)    startTime = JulianDate.clone(currentTime);  } else {    startTime = JulianDate.clone(startTime);  }  if (!defined(stopTime)) {    // if not specified, stop time is 1 day after the start time    // (as determined above)    stopTime = JulianDate.addDays(startTime, 1.0, new JulianDate());  } else {    stopTime = JulianDate.clone(stopTime);  }  //>>includeStart('debug', pragmas.debug);  if (JulianDate.greaterThan(startTime, stopTime)) {    throw new DeveloperError("startTime must come before stopTime.");  }  //>>includeEnd('debug');  /**   * The start time of the clock.   * @type {JulianDate}   */  this.startTime = startTime;  /**   * The stop time of the clock.   * @type {JulianDate}   */  this.stopTime = stopTime;  /**   * Determines how the clock should behave when   * {@link Clock#startTime} or {@link Clock#stopTime}   * is reached.   * @type {ClockRange}   * @default {@link ClockRange.UNBOUNDED}   */  this.clockRange = defaultValue(options.clockRange, ClockRange.UNBOUNDED);  /**   * Indicates whether {@link Clock#tick} can advance time.  This could be false if data is being buffered,   * for example.  The clock will only advance time when both   * {@link Clock#canAnimate} and {@link Clock#shouldAnimate} are true.   * @type {Boolean}   * @default true   */  this.canAnimate = defaultValue(options.canAnimate, true);  /**   * An {@link Event} that is fired whenever {@link Clock#tick} is called.   * @type {Event}   */  this.onTick = new Event();  /**   * An {@link Event} that is fired whenever {@link Clock#stopTime} is reached.   * @type {Event}   */  this.onStop = new Event();  this._currentTime = undefined;  this._multiplier = undefined;  this._clockStep = undefined;  this._shouldAnimate = undefined;  this._lastSystemTime = getTimestamp();  // set values using the property setters to  // make values consistent.  this.currentTime = currentTime;  this.multiplier = defaultValue(options.multiplier, 1.0);  this.shouldAnimate = defaultValue(options.shouldAnimate, false);  this.clockStep = defaultValue(    options.clockStep,    ClockStep.SYSTEM_CLOCK_MULTIPLIER  );}Object.defineProperties(Clock.prototype, {  /**   * The current time.   * Changing this property will change   * {@link Clock#clockStep} from {@link ClockStep.SYSTEM_CLOCK} to   * {@link ClockStep.SYSTEM_CLOCK_MULTIPLIER}.   * @memberof Clock.prototype   * @type {JulianDate}   */  currentTime: {    get: function () {      return this._currentTime;    },    set: function (value) {      if (JulianDate.equals(this._currentTime, value)) {        return;      }      if (this._clockStep === ClockStep.SYSTEM_CLOCK) {        this._clockStep = ClockStep.SYSTEM_CLOCK_MULTIPLIER;      }      this._currentTime = value;    },  },  /**   * Gets or sets how much time advances when {@link Clock#tick} is called. Negative values allow for advancing backwards.   * If {@link Clock#clockStep} is set to {@link ClockStep.TICK_DEPENDENT}, this is the number of seconds to advance.   * If {@link Clock#clockStep} is set to {@link ClockStep.SYSTEM_CLOCK_MULTIPLIER}, this value is multiplied by the   * elapsed system time since the last call to {@link Clock#tick}.   * Changing this property will change   * {@link Clock#clockStep} from {@link ClockStep.SYSTEM_CLOCK} to   * {@link ClockStep.SYSTEM_CLOCK_MULTIPLIER}.   * @memberof Clock.prototype   * @type {Number}   * @default 1.0   */  multiplier: {    get: function () {      return this._multiplier;    },    set: function (value) {      if (this._multiplier === value) {        return;      }      if (this._clockStep === ClockStep.SYSTEM_CLOCK) {        this._clockStep = ClockStep.SYSTEM_CLOCK_MULTIPLIER;      }      this._multiplier = value;    },  },  /**   * Determines if calls to {@link Clock#tick} are frame dependent or system clock dependent.   * Changing this property to {@link ClockStep.SYSTEM_CLOCK} will set   * {@link Clock#multiplier} to 1.0, {@link Clock#shouldAnimate} to true, and   * {@link Clock#currentTime} to the current system clock time.   * @memberof Clock.prototype   * @type ClockStep   * @default {@link ClockStep.SYSTEM_CLOCK_MULTIPLIER}   */  clockStep: {    get: function () {      return this._clockStep;    },    set: function (value) {      if (value === ClockStep.SYSTEM_CLOCK) {        this._multiplier = 1.0;        this._shouldAnimate = true;        this._currentTime = JulianDate.now();      }      this._clockStep = value;    },  },  /**   * Indicates whether {@link Clock#tick} should attempt to advance time.   * The clock will only advance time when both   * {@link Clock#canAnimate} and {@link Clock#shouldAnimate} are true.   * Changing this property will change   * {@link Clock#clockStep} from {@link ClockStep.SYSTEM_CLOCK} to   * {@link ClockStep.SYSTEM_CLOCK_MULTIPLIER}.   * @memberof Clock.prototype   * @type {Boolean}   * @default false   */  shouldAnimate: {    get: function () {      return this._shouldAnimate;    },    set: function (value) {      if (this._shouldAnimate === value) {        return;      }      if (this._clockStep === ClockStep.SYSTEM_CLOCK) {        this._clockStep = ClockStep.SYSTEM_CLOCK_MULTIPLIER;      }      this._shouldAnimate = value;    },  },});/** * Advances the clock from the current time based on the current configuration options. * tick should be called every frame, regardless of whether animation is taking place * or not.  To control animation, use the {@link Clock#shouldAnimate} property. * * @returns {JulianDate} The new value of the {@link Clock#currentTime} property. */Clock.prototype.tick = function () {  const currentSystemTime = getTimestamp();  let currentTime = JulianDate.clone(this._currentTime);  if (this.canAnimate && this._shouldAnimate) {    const clockStep = this._clockStep;    if (clockStep === ClockStep.SYSTEM_CLOCK) {      currentTime = JulianDate.now(currentTime);    } else {      const multiplier = this._multiplier;      if (clockStep === ClockStep.TICK_DEPENDENT) {        currentTime = JulianDate.addSeconds(          currentTime,          multiplier,          currentTime        );      } else {        const milliseconds = currentSystemTime - this._lastSystemTime;        currentTime = JulianDate.addSeconds(          currentTime,          multiplier * (milliseconds / 1000.0),          currentTime        );      }      const clockRange = this.clockRange;      const startTime = this.startTime;      const stopTime = this.stopTime;      if (clockRange === ClockRange.CLAMPED) {        if (JulianDate.lessThan(currentTime, startTime)) {          currentTime = JulianDate.clone(startTime, currentTime);        } else if (JulianDate.greaterThan(currentTime, stopTime)) {          currentTime = JulianDate.clone(stopTime, currentTime);          this.onStop.raiseEvent(this);        }      } else if (clockRange === ClockRange.LOOP_STOP) {        if (JulianDate.lessThan(currentTime, startTime)) {          currentTime = JulianDate.clone(startTime, currentTime);        }        while (JulianDate.greaterThan(currentTime, stopTime)) {          currentTime = JulianDate.addSeconds(            startTime,            JulianDate.secondsDifference(currentTime, stopTime),            currentTime          );          this.onStop.raiseEvent(this);        }      }    }  }  this._currentTime = currentTime;  this._lastSystemTime = currentSystemTime;  this.onTick.raiseEvent(this);  return currentTime;};export default Clock;
 |