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;
|